mirror of
https://github.com/versity/scoutfs.git
synced 2026-08-18 21:26:51 +00:00
scoutfs-utils: remove locks command
scoutfs now directly uses the kernel dlm subsystem and offsers a debugfs file with the current lock state. We don't need userspace to read and format the contents of a debugging file. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
/* -*- mode: c; c-basic-offset: 8; -*-
|
||||
* vim: noexpandtab sw=8 ts=8 sts=0:
|
||||
*
|
||||
* dlmglue.h
|
||||
*
|
||||
* dlmglue constants for userspace decoding
|
||||
*
|
||||
* Copyright (C) 2002, 2004 Oracle. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLMGLUE_H
|
||||
#define DLMGLUE_H
|
||||
|
||||
/* Max length of lockid name */
|
||||
#define OCFS2_LOCK_ID_MAX_LEN 32
|
||||
|
||||
#define DLM_LVB_LEN 64
|
||||
|
||||
enum ocfs2_ast_action {
|
||||
OCFS2_AST_INVALID = 0,
|
||||
OCFS2_AST_ATTACH,
|
||||
OCFS2_AST_CONVERT,
|
||||
OCFS2_AST_DOWNCONVERT,
|
||||
};
|
||||
|
||||
/* actions for an unlockast function to take. */
|
||||
enum ocfs2_unlock_action {
|
||||
OCFS2_UNLOCK_INVALID = 0,
|
||||
OCFS2_UNLOCK_CANCEL_CONVERT,
|
||||
OCFS2_UNLOCK_DROP_LOCK,
|
||||
};
|
||||
|
||||
/* ocfs2_lock_res->l_flags flags. */
|
||||
#define OCFS2_LOCK_ATTACHED (0x00000001) /* we have initialized
|
||||
* the lvb */
|
||||
#define OCFS2_LOCK_BUSY (0x00000002) /* we are currently in
|
||||
* dlm_lock */
|
||||
#define OCFS2_LOCK_BLOCKED (0x00000004) /* blocked waiting to
|
||||
* downconvert*/
|
||||
#define OCFS2_LOCK_LOCAL (0x00000008) /* newly created inode */
|
||||
#define OCFS2_LOCK_NEEDS_REFRESH (0x00000010)
|
||||
#define OCFS2_LOCK_REFRESHING (0x00000020)
|
||||
#define OCFS2_LOCK_INITIALIZED (0x00000040) /* track initialization
|
||||
* for shutdown paths */
|
||||
#define OCFS2_LOCK_FREEING (0x00000080) /* help dlmglue track
|
||||
* when to skip queueing
|
||||
* a lock because it's
|
||||
* about to be
|
||||
* dropped. */
|
||||
#define OCFS2_LOCK_QUEUED (0x00000100) /* queued for downconvert */
|
||||
#define OCFS2_LOCK_NOCACHE (0x00000200) /* don't use a holder count */
|
||||
#define OCFS2_LOCK_PENDING (0x00000400) /* This lockres is pending a
|
||||
call to dlm_lock. Only
|
||||
exists with BUSY set. */
|
||||
#define OCFS2_LOCK_UPCONVERT_FINISHING (0x00000800) /* blocks the dc thread
|
||||
* from downconverting
|
||||
* before the upconvert
|
||||
* has completed */
|
||||
|
||||
#define OCFS2_LOCK_NONBLOCK_FINISHED (0x00001000) /* NONBLOCK cluster
|
||||
* lock has already
|
||||
* returned, do not block
|
||||
* dc thread from
|
||||
* downconverting */
|
||||
|
||||
/* The cluster stack fields */
|
||||
#define OCFS2_STACK_LABEL_LEN 4
|
||||
#define OCFS2_CLUSTER_NAME_LEN 16
|
||||
|
||||
/*
|
||||
* Return value from ->downconvert_worker functions.
|
||||
*
|
||||
* These control the precise actions of ocfs2_unblock_lock()
|
||||
* and ocfs2_process_blocked_lock()
|
||||
*
|
||||
*/
|
||||
enum ocfs2_unblock_action {
|
||||
UNBLOCK_CONTINUE = 0, /* Continue downconvert */
|
||||
UNBLOCK_CONTINUE_POST = 1, /* Continue downconvert, fire
|
||||
* ->post_unlock callback */
|
||||
UNBLOCK_STOP_POST = 2, /* Do not downconvert, fire
|
||||
* ->post_unlock() callback. */
|
||||
};
|
||||
|
||||
#endif /* DLMGLUE_H */
|
||||
@@ -1,420 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/dlmconstants.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "cmd.h"
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
#include "list.h"
|
||||
#include "dlmglue.h"
|
||||
|
||||
static int print_lvbs = 0;
|
||||
static int oneline = 0;
|
||||
|
||||
static char *level_str(int level)
|
||||
{
|
||||
char *s;
|
||||
|
||||
switch (level) {
|
||||
case DLM_LOCK_IV:
|
||||
s = "IV";
|
||||
break;
|
||||
case DLM_LOCK_NL:
|
||||
s = "NL";
|
||||
break;
|
||||
case DLM_LOCK_CR:
|
||||
s = "CR";
|
||||
break;
|
||||
case DLM_LOCK_CW:
|
||||
s = "CW";
|
||||
break;
|
||||
case DLM_LOCK_PR:
|
||||
s = "PR";
|
||||
break;
|
||||
case DLM_LOCK_PW:
|
||||
s = "PW";
|
||||
break;
|
||||
case DLM_LOCK_EX:
|
||||
s = "EX";
|
||||
break;
|
||||
default:
|
||||
s = "Unknown";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void print_flags(unsigned long flags, FILE *out)
|
||||
{
|
||||
if (flags & OCFS2_LOCK_INITIALIZED )
|
||||
fprintf(out, " Initialized");
|
||||
|
||||
if (flags & OCFS2_LOCK_ATTACHED)
|
||||
fprintf(out, " Attached");
|
||||
|
||||
if (flags & OCFS2_LOCK_BUSY)
|
||||
fprintf(out, " Busy");
|
||||
|
||||
if (flags & OCFS2_LOCK_BLOCKED)
|
||||
fprintf(out, " Blocked");
|
||||
|
||||
if (flags & OCFS2_LOCK_LOCAL)
|
||||
fprintf(out, " Local");
|
||||
|
||||
if (flags & OCFS2_LOCK_NEEDS_REFRESH)
|
||||
fprintf(out, " Needs Refresh");
|
||||
|
||||
if (flags & OCFS2_LOCK_REFRESHING)
|
||||
fprintf(out, " Refreshing");
|
||||
|
||||
if (flags & OCFS2_LOCK_FREEING)
|
||||
fprintf(out, " Freeing");
|
||||
|
||||
if (flags & OCFS2_LOCK_QUEUED)
|
||||
fprintf(out, " Queued");
|
||||
}
|
||||
|
||||
static char *action_str(unsigned int action)
|
||||
{
|
||||
char *s;
|
||||
|
||||
switch (action) {
|
||||
case OCFS2_AST_INVALID:
|
||||
s = "None";
|
||||
break;
|
||||
case OCFS2_AST_ATTACH:
|
||||
s = "Attach";
|
||||
break;
|
||||
case OCFS2_AST_CONVERT:
|
||||
s = "Convert";
|
||||
break;
|
||||
case OCFS2_AST_DOWNCONVERT:
|
||||
s = "Downconvert";
|
||||
break;
|
||||
default:
|
||||
s = "Unknown";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *unlock_action_str(unsigned int unlock_action)
|
||||
{
|
||||
char *s;
|
||||
switch (unlock_action) {
|
||||
case OCFS2_UNLOCK_INVALID:
|
||||
s = "None";
|
||||
break;
|
||||
case OCFS2_UNLOCK_CANCEL_CONVERT:
|
||||
s = "Cancel Convert";
|
||||
break;
|
||||
case OCFS2_UNLOCK_DROP_LOCK:
|
||||
s = "Drop Lock";
|
||||
break;
|
||||
default:
|
||||
s = "Unknown";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void dump_raw_lvb(const char *lvb, FILE *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(out, "Raw LVB:\t");
|
||||
|
||||
for(i = 0; i < DLM_LVB_LEN; i++) {
|
||||
fprintf(out, "%02hhx ", lvb[i]);
|
||||
if (!((i+1) % 16) && i != (DLM_LVB_LEN-1))
|
||||
fprintf(out, "\n\t\t");
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
static int end_line(FILE *f)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = fgetc(f);
|
||||
if (ret == EOF)
|
||||
return 1;
|
||||
} while (ret != '\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the printing/scanning code here was modified from ocfs2-tools */
|
||||
static int print_fields(FILE *file, FILE *out)
|
||||
{
|
||||
char id[OCFS2_LOCK_ID_MAX_LEN + 1];
|
||||
char lvb[DLM_LVB_LEN];
|
||||
int ret, i, level, requested, blocking;
|
||||
unsigned long flags;
|
||||
unsigned int action, unlock_action, cw, ro, ex, dummy;
|
||||
const char *format;
|
||||
unsigned long long num_prmode, num_exmode, num_cwmode;
|
||||
unsigned int num_prmode_failed, num_exmode_failed, num_cwmode_failed;
|
||||
unsigned long long total_prmode, total_exmode, total_cwmode;
|
||||
unsigned long long avg_prmode = 0, avg_exmode = 0, avg_cwmode = 0;
|
||||
unsigned int max_prmode, max_exmode, max_cwmode, num_refresh;
|
||||
|
||||
ret = fscanf(file, "%s\t"
|
||||
"%d\t"
|
||||
"0x%lx\t"
|
||||
"0x%x\t"
|
||||
"0x%x\t"
|
||||
"%u\t"
|
||||
"%u\t"
|
||||
"%d\t"
|
||||
"%d\t",
|
||||
id,
|
||||
&level,
|
||||
&flags,
|
||||
&action,
|
||||
&unlock_action,
|
||||
&ro,
|
||||
&ex,
|
||||
&requested,
|
||||
&blocking);
|
||||
if (ret != 9) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
format = "0x%x\t";
|
||||
for (i = 0; i < DLM_LVB_LEN; i++) {
|
||||
ret = fscanf(file, format, &dummy);
|
||||
if (ret != 1) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lvb[i] = (char) dummy;
|
||||
}
|
||||
|
||||
ret = fscanf(file, "%llu\t"
|
||||
"%llu\t"
|
||||
"%u\t"
|
||||
"%u\t"
|
||||
"%llu\t"
|
||||
"%llu\t"
|
||||
"%u\t"
|
||||
"%u\t"
|
||||
"%u\t"
|
||||
"%u\t"
|
||||
"%llu\t"
|
||||
"%u\t"
|
||||
"%llu\t"
|
||||
"%u",
|
||||
&num_prmode,
|
||||
&num_exmode,
|
||||
&num_prmode_failed,
|
||||
&num_exmode_failed,
|
||||
&total_prmode,
|
||||
&total_exmode,
|
||||
&max_prmode,
|
||||
&max_exmode,
|
||||
&num_refresh,
|
||||
&cw,
|
||||
&num_cwmode,
|
||||
&num_cwmode_failed,
|
||||
&total_cwmode,
|
||||
&max_cwmode);
|
||||
if (ret != 14) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (oneline) {
|
||||
fprintf(out, "%s mode %s flags", id, level_str(level));
|
||||
print_flags(flags, out);
|
||||
fprintf(out, " cw/ro/ex %u/%u/%u act %s unlock %s req %s "
|
||||
"block %s\n", cw, ro, ex, action_str(action),
|
||||
unlock_action_str(unlock_action), level_str(requested),
|
||||
level_str(blocking));
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(out, "Lockres: %s Mode: %s\nFlags:", id, level_str(level));
|
||||
print_flags(flags, out);
|
||||
fprintf(out, "\nCW Holders: %u RO Holders: %u EX Holders: %u\n", cw,
|
||||
ro, ex);
|
||||
fprintf(out, "Pending Action: %s Pending Unlock Action: %s\n",
|
||||
action_str(action), unlock_action_str(unlock_action));
|
||||
fprintf(out, "Requested Mode: %s Blocking Mode: %s\n",
|
||||
level_str(requested), level_str(blocking));
|
||||
|
||||
if (print_lvbs)
|
||||
dump_raw_lvb(lvb, out);
|
||||
#define NSEC_PER_USEC 1000
|
||||
|
||||
if (num_prmode)
|
||||
avg_prmode = total_prmode/num_prmode;
|
||||
|
||||
if (num_exmode)
|
||||
avg_exmode = total_exmode/num_exmode;
|
||||
|
||||
if (num_cwmode)
|
||||
avg_cwmode = total_cwmode/num_cwmode;
|
||||
|
||||
fprintf(out, "CW > Gets: %llu Fails: %u Waits Total: %lluus "
|
||||
"Max: %uus Avg: %lluns\n",
|
||||
num_cwmode, num_cwmode_failed, total_cwmode/NSEC_PER_USEC,
|
||||
max_cwmode, avg_cwmode);
|
||||
fprintf(out, "PR > Gets: %llu Fails: %u Waits Total: %lluus "
|
||||
"Max: %uus Avg: %lluns\n",
|
||||
num_prmode, num_prmode_failed, total_prmode/NSEC_PER_USEC,
|
||||
max_prmode, avg_prmode);
|
||||
fprintf(out, "EX > Gets: %llu Fails: %u Waits Total: %lluus "
|
||||
"Max: %uus Avg: %lluns\n",
|
||||
num_exmode, num_exmode_failed, total_exmode/NSEC_PER_USEC,
|
||||
max_exmode, avg_exmode);
|
||||
fprintf(out, "Disk Refreshes: %u\n", num_refresh);
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CURRENT_PROTO 4
|
||||
static void print_locks(int fd)
|
||||
{
|
||||
FILE *file = fdopen(fd, "r");
|
||||
unsigned int version;
|
||||
int ret;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Version is printed on every line (silly but easy to
|
||||
* implement)
|
||||
*/
|
||||
ret = fscanf(file, "%x\t", &version);
|
||||
if (ret != 1)
|
||||
goto out;
|
||||
|
||||
if (version > CURRENT_PROTO) {
|
||||
fprintf(stdout,
|
||||
"Lock debug proto is %u, but %u is the "
|
||||
"highest I understand.\n", version,
|
||||
CURRENT_PROTO);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = print_fields(file, stdout);
|
||||
|
||||
/* Read to the end of the record here. Any new fields tagged
|
||||
* onto the current format will be silently ignored. */
|
||||
} while (!end_line(file));
|
||||
|
||||
out:
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
static int get_fsid(int fd, u64 *fsid)
|
||||
{
|
||||
struct scoutfs_super_block *super;
|
||||
|
||||
super = read_block(fd, SCOUTFS_SUPER_BLKNO);
|
||||
if (!super)
|
||||
return -ENOMEM;
|
||||
|
||||
*fsid = le64_to_cpu(super->hdr.fsid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int locks_func(int argc, char *argv[])
|
||||
{
|
||||
char sysfs[PATH_MAX];
|
||||
char *path;
|
||||
u64 fsid;
|
||||
int ret;
|
||||
int fd;
|
||||
int c = 10000;
|
||||
|
||||
static struct option long_ops[] = {
|
||||
{ "oneline", 0, NULL, 'o' },
|
||||
{ "lvbs=", 1, NULL, 'L'},
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
if (argc < 1) {
|
||||
printf("scoutfs: locks: a device argument is required\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((c = getopt_long(argc, argv, "l:", long_ops, NULL))
|
||||
!= -1) {
|
||||
switch (c) {
|
||||
case 'o':
|
||||
oneline = 1;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (strcasecmp(optarg, "yes") == 0)
|
||||
print_lvbs = 1;
|
||||
else if (strcasecmp(optarg, "no") == 0)
|
||||
print_lvbs = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
path = argv[optind];
|
||||
|
||||
/* XXX: Take mountpoint argument instead and turn that into a
|
||||
* device for below */
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n",
|
||||
path, strerror(errno), errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = get_fsid(fd, &fsid);
|
||||
close(fd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* open sysfs file, print now */
|
||||
snprintf(sysfs, PATH_MAX,
|
||||
"/sys/kernel/debug/scoutfs/%llx/locking_state", fsid);
|
||||
|
||||
fd = open(sysfs, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n", sysfs,
|
||||
strerror(errno), errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
print_locks(fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) locks_ctor(void)
|
||||
{
|
||||
cmd_register("locks", "--lvbs=[yes|no] --oneline <path>",
|
||||
"show file system locking state", locks_func);
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
#include "crc.h"
|
||||
#include "key.h"
|
||||
|
||||
void *read_block(int fd, u64 blkno)
|
||||
static void *read_block(int fd, u64 blkno)
|
||||
{
|
||||
ssize_t ret;
|
||||
void *buf;
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sparse.h"
|
||||
|
||||
|
||||
/*
|
||||
* Generate build warnings if the condition is false but generate no
|
||||
* code at run time if it's true.
|
||||
@@ -78,7 +75,4 @@ static inline int memcmp_lens(const void *a, int a_len,
|
||||
return memcmp(a, b, len) ?: a_len - b_len;
|
||||
}
|
||||
|
||||
/* exported from print.c, we should probably just move it into a util.c */
|
||||
void *read_block(int fd, u64 blkno);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user