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:
Zach Brown
2018-02-14 15:01:16 -08:00
committed by Zach Brown
parent 7d674fa4bf
commit e68a999ed5
4 changed files with 1 additions and 528 deletions
-101
View File
@@ -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 */
-420
View File
@@ -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
View File
@@ -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;
-6
View File
@@ -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