[Ocfs2-tools-devel] [PATCH 1/3] debugfs: Add dlm_locks command to debugfs.ocfs2 tool
Sunil Mushran
Sunil.Mushran at oracle.com
Fri May 9 11:50:46 PDT 2008
Thanks. I fixed those and other issues reported by checkpatch.
Tao Ma wrote:
> Signed-off-by: Tao Ma <tao.ma at oracle.com>
>
> Just small comment. When using git apply, find some trailing
> whitespace and one space before tab in indent.
>
> git apply ~/patches/review/dlm_locks/\[Ocfs2-tools-devel\]\ \[PATCH\
> 1_3\]\ debugfs\:\ Add\ dlm_locks\ command\ to\ debugfs.ocfs2\
> tool.eml
> /home/taoma/patches/review/dlm_locks/[Ocfs2-tools-devel] [PATCH 1_3]
> debugfs: Add dlm_locks command to debugfs.ocfs2 tool.eml:217:
> trailing whitespace.
> *
> /home/taoma/patches/review/dlm_locks/[Ocfs2-tools-devel] [PATCH 1_3]
> debugfs: Add dlm_locks command to debugfs.ocfs2 tool.eml:222:
> trailing whitespace.
> *
> /home/taoma/patches/review/dlm_locks/[Ocfs2-tools-devel] [PATCH 1_3]
> debugfs: Add dlm_locks command to debugfs.ocfs2 tool.eml:361:
> space before tab in indent.
> numlocks, lists->str);
> /home/taoma/patches/review/dlm_locks/[Ocfs2-tools-devel] [PATCH 1_3]
> debugfs: Add dlm_locks command to debugfs.ocfs2 tool.eml:750:
> trailing whitespace.
> *
> /home/taoma/patches/review/dlm_locks/[Ocfs2-tools-devel] [PATCH 1_3]
> debugfs: Add dlm_locks command to debugfs.ocfs2 tool.eml:755:
> trailing whitespace.
> *
>
>
> Sunil Mushran wrote:
>> This patch adds the ability to debugfs.ocfs2 to read the dlm locking
>> state file, lockres, and dump the lock information in a readable manner.
>>
>> Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
>> ---
>> debugfs.ocfs2/Makefile | 6 +-
>> debugfs.ocfs2/commands.c | 54 ++++-
>> debugfs.ocfs2/dump_dlm_locks.c | 528
>> ++++++++++++++++++++++++++++++++
>> debugfs.ocfs2/include/dump_dlm_locks.h | 85 +++++
>> debugfs.ocfs2/include/main.h | 5 +-
>> 5 files changed, 672 insertions(+), 6 deletions(-)
>> create mode 100644 debugfs.ocfs2/dump_dlm_locks.c
>> create mode 100644 debugfs.ocfs2/include/dump_dlm_locks.h
>>
>> diff --git a/debugfs.ocfs2/Makefile b/debugfs.ocfs2/Makefile
>> index b17886d..bb70e76 100644
>> --- a/debugfs.ocfs2/Makefile
>> +++ b/debugfs.ocfs2/Makefile
>> @@ -11,7 +11,8 @@ DEFINES += -DVERSION=\"$(VERSION)\"
>> INCLUDES = -I$(TOPDIR)/include -Iinclude
>> INCLUDES += $(GLIB_CFLAGS)
>>
>> -CFILES = main.c commands.c dump.c utils.c journal.c
>> find_block_inode.c find_inode_paths.c dump_fs_locks.c
>> +CFILES = main.c commands.c dump.c utils.c journal.c
>> find_block_inode.c \
>> + find_inode_paths.c dump_fs_locks.c dump_dlm_locks.c
>>
>> HFILES = \
>> include/main.h \
>> @@ -22,7 +23,8 @@ HFILES = \
>> include/find_block_inode.h \
>> include/find_inode_paths.h \
>> include/ocfs2_internals.h \
>> - include/dump_fs_locks.h
>> + include/dump_fs_locks.h \
>> + include/dump_dlm_locks.h
>>
>> OBJS = $(subst .c,.o,$(CFILES))
>>
>> diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
>> index ed93759..cdab387 100644
>> --- a/debugfs.ocfs2/commands.c
>> +++ b/debugfs.ocfs2/commands.c
>> @@ -3,7 +3,7 @@
>> *
>> * handles debugfs commands
>> *
>> - * Copyright (C) 2004 Oracle. All rights reserved.
>> + * Copyright (C) 2004, 2008 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
>> @@ -20,7 +20,6 @@
>> * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>> * Boston, MA 021110-1307, USA.
>> *
>> - * Authors: Sunil Mushran, Manish Singh
>> */
>>
>> #include "main.h"
>> @@ -69,6 +68,7 @@ static void do_locate (char **args);
>> static void do_fs_locks (char **args);
>> static void do_bmap (char **args);
>> static void do_icheck (char **args);
>> +static void do_dlm_locks (char **args);
>>
>> dbgfs_gbls gbls;
>>
>> @@ -79,6 +79,7 @@ static Command commands[] = {
>> { "chroot", do_chroot },
>> { "close", do_close },
>> { "curdev", do_curdev },
>> + { "dlm_locks", do_dlm_locks },
>> { "dump", do_dump },
>> { "extent", do_extent },
>> { "fs_locks", do_fs_locks },
>> @@ -795,6 +796,7 @@ static void do_help (char **args)
>> printf ("close\t\t\t\t\tClose a device\n");
>> printf ("curdev\t\t\t\t\tShow current device\n");
>> printf ("decode <lockname#> ...\t\t\tDecode block#(s) from the
>> lockname(s)\n");
>> + printf ("dlm_locks [-l] lockname\t\t\tShow live dlm locking
>> state\n");
>> printf ("dump [-p] <filespec> <outfile>\t\tDumps file to outfile
>> on a mounted fs\n");
>> printf ("encode <filespec>\t\t\tShow lock name\n");
>> printf ("extent <block#>\t\t\t\tShow extent block\n");
>> @@ -1412,6 +1414,54 @@ static void do_locate(char **args)
>> }
>>
>> /*
>> + * do_dlm_locks()
>> + *
>> + */
>> +static void do_dlm_locks(char **args)
>> +{
>> + FILE *out;
>> + int dump_lvbs = 0;
>> + int i;
>> + struct locknames *lock;
>> + struct list_head locklist;
>> + struct list_head *iter, *iter2;
>> +
>> + if (check_device_open())
>> + return;
>> +
>> + INIT_LIST_HEAD(&locklist);
>> +
>> + i = 1;
>> + if (args[i] && strlen(args[i])) {
>> + if (!strcmp("-l", args[i])) {
>> + dump_lvbs = 1;
>> + i++;
>> + }
>> +
>> + for ( ; args[i] && strlen(args[i]); ++i) {
>> + lock = calloc(1, sizeof(struct locknames));
>> + if (lock) {
>> + INIT_LIST_HEAD(&lock->list);
>> + strncpy(lock->name, args[i], sizeof(lock->name));
>> + list_add_tail(&lock->list, &locklist);
>> + }
>> + }
>> + }
>> +
>> + out = open_pager(gbls.interactive);
>> + dump_dlm_locks(gbls.fs->uuid_str, out, dump_lvbs, &locklist);
>> + close_pager(out);
>> +
>> + if (!list_empty(&locklist)) {
>> + list_for_each_safe(iter, iter2, &locklist) {
>> + lock = list_entry(iter, struct locknames, list);
>> + list_del(iter);
>> + free(lock);
>> + }
>> + }
>> +}
>> +
>> +/*
>> * do_dump_fs_locks()
>> *
>> */
>> diff --git a/debugfs.ocfs2/dump_dlm_locks.c
>> b/debugfs.ocfs2/dump_dlm_locks.c
>> new file mode 100644
>> index 0000000..c7b964a
>> --- /dev/null
>> +++ b/debugfs.ocfs2/dump_dlm_locks.c
>> @@ -0,0 +1,528 @@
>> +/* -*- mode: c; c-basic-offset: 8; -*-
>> + * vim: noexpandtab sw=8 ts=8 sts=0:
>> + *
>> + * dump_dlm_locks.c
>> + *
>> + * Interface with the kernel and dump current dlm locking state
>> + *
>> + * Copyright (C) 2008 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, version 2, as published by the Free Software Foundation.
>> + * + * 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.
>> + *
>> + */
>> +
>> +#define _XOPEN_SOURCE 600 /* Triggers XOPEN2K in features.h */
>> +#define _LARGEFILE64_SOURCE
>> +
>> +#include "main.h"
>> +#include "ocfs2/byteorder.h"
>> +#include "ocfs2_internals.h"
>> +
>> +static void dump_raw_lvb(const char *lvb, FILE *out)
>> +{
>> + int i, j;
>> +
>> + fprintf(out, "Raw LVB:\t");
>> +
>> + for(i = 0, j = 0; i < DLM_LVB_LEN; i++, j += 2) {
>> + fprintf(out, "%c%c ", lvb[j], lvb[j+1]);
>> + if (!((i+1) % 16) && i != (DLM_LVB_LEN-1))
>> + fprintf(out, "\n\t\t");
>> + }
>> + fprintf(out, "\n");
>> +}
>> +
>> +static void dump_lock(struct lock *lock, char *queue, FILE *out)
>> +{
>> + GString *action = NULL;
>> + char *ast, *bast, *level;
>> +
>> + action = g_string_new(NULL);
>> +
>> + if (lock->type == 0)
>> + level = "NL";
>> + else if (lock->type == 3)
>> + level = "PR";
>> + else if (lock->type == 5)
>> + level = "EX";
>> + else
>> + level = "??";
>> +
>> + ast = (lock->ast_list) ? "Yes" : "No";
>> + bast = (lock->bast_list) ? "Yes" : "No";
>> +
>> + if (lock->ast_pending)
>> + g_string_append(action, "Ast ");
>> + if (lock->bast_pending)
>> + g_string_append(action, "Bast ");
>> + if (lock->convert_pending)
>> + g_string_append(action, "Convert ");
>> + if (lock->lock_pending)
>> + g_string_append(action, "Lock ");
>> + if (lock->cancel_pending)
>> + g_string_append(action, "Cancel ");
>> + if (lock->unlock_pending)
>> + g_string_append(action, "Unlock ");
>> + if (!action->len)
>> + g_string_append(action, "None");
>> +
>> + fprintf(out, " %-10s %-4d %-5s %-4d %-15s %-4d %-3s %-4s
>> %s\n",
>> + queue, lock->node, level, lock->convert_type, lock->cookie,
>> + lock->refs, ast, bast, action->str);
>> +
>> + g_string_free(action, 1);
>> +}
>> +
>> +static void get_lockres_state(__u16 state, GString *str)
>> +{
>> + if (state && DLM_LOCK_RES_UNINITED)
>> + g_string_append(str, "Uninitialized");
>> + if (state && DLM_LOCK_RES_RECOVERING)
>> + g_string_append(str, "Recovering");
>> + if (state && DLM_LOCK_RES_READY)
>> + g_string_append(str, "Ready");
>> + if (state && DLM_LOCK_RES_DIRTY)
>> + g_string_append(str, "Dirty");
>> + if (state && DLM_LOCK_RES_IN_PROGRESS)
>> + g_string_append(str, "InProgress");
>> + if (state && DLM_LOCK_RES_MIGRATING)
>> + g_string_append(str, "Migrating");
>> + if (state && DLM_LOCK_RES_DROPPING_REF)
>> + g_string_append(str, "DroppingRef");
>> + if (state && DLM_LOCK_RES_BLOCK_DIRTY)
>> + g_string_append(str, "BlockDirty");
>> + if (state && DLM_LOCK_RES_SETREF_INPROG)
>> + g_string_append(str, "SetRefInProg");
>> + if (!str->len)
>> + g_string_append(str, "");
>> +}
>> +
>> +static void dump_lockres(char *name, struct lockres *res, FILE *out)
>> +{
>> + struct lock *lock;
>> + struct list_head *iter;
>> + GString *lists = NULL;
>> + GString *state = NULL;
>> + int numlocks = 0;
>> +
>> + state = g_string_new(NULL);
>> + lists = g_string_new(NULL);
>> +
>> + if (res->purge)
>> + g_string_append(lists, "Purge ");
>> + if (res->dirty)
>> + g_string_append(lists, "Dirty ");
>> + if (res->recovering)
>> + g_string_append(lists, "Recovering ");
>> + if (!lists->len)
>> + g_string_append(lists, "None");
>> +
>> + get_lockres_state(res->state, state);
>> +
>> + if (!list_empty(&res->granted))
>> + list_for_each(iter, &res->granted)
>> + ++numlocks;
>> +
>> + if (!list_empty(&res->converting))
>> + list_for_each(iter, &res->converting)
>> + ++numlocks;
>> +
>> + if (!list_empty(&res->blocked))
>> + list_for_each(iter, &res->blocked)
>> + ++numlocks;
>> +
>> + /* Lockres: xx Owner: xx State: 0x1 xxx */
>> + fprintf(out, "Lockres: %-32s Owner: %-3d State: 0x%X %s\n",
>> + name, res->owner, res->state, state->str);
>> +
>> + /* Last Used: x ASTs Reserved: x Inflight: x Migration
>> Pending: x */
>> + fprintf(out, "Last Used: %-5d ASTs Reserved: %-3d Inflight:
>> %-3d "
>> + "Migration Pending: %s\n", res->last_used, res->asts_reserved,
>> + res->inflight_locks, (res->migration_pending ? "Yes" : "No"));
>> +
>> + /* Refs: xx Locks: xx On Lists: xx */
>> + fprintf(out, "Refs: %-3d Locks: %-3d On Lists: %s\n", res->refs,
>> + numlocks, lists->str);
>> +
>> + /* Reference Map: xx, xx, xx, xx, xx */
>> + fprintf(out, "Reference Map: ");
>> + if (res->refmap)
>> + fprintf(out, "%s", res->refmap);
>> + fprintf(out, "\n");
>> +
>> + /* Raw LVB: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */
>> + if (res->lvb)
>> + dump_raw_lvb(res->lvb, out);
>> +
>> + /* Lock-Queue Node Level Conv Cookie Refs AST BAST
>> Pendi... */
>> + fprintf(out, " %-10s %-4s %-5s %-4s %-15s %-4s %-3s %-4s
>> %s\n",
>> + "Lock-Queue", "Node", "Level", "Conv", "Cookie", "Refs", "AST",
>> + "BAST", "Pending-Action");
>> +
>> + /* Granted Queue: */
>> + if (!list_empty(&res->granted)) {
>> + list_for_each(iter, &res->granted) {
>> + lock = list_entry(iter, struct lock, list);
>> + dump_lock(lock, "Granted", out);
>> + }
>> + }
>> +
>> + /* Converting Queue: */
>> + if (!list_empty(&res->converting)) {
>> + list_for_each(iter, &res->converting) {
>> + lock = list_entry(iter, struct lock, list);
>> + dump_lock(lock, "Converting", out);
>> + }
>> + }
>> +
>> + /* Blocked Queue: */
>> + if (!list_empty(&res->blocked)) {
>> + list_for_each(iter, &res->blocked) {
>> + lock = list_entry(iter, struct lock, list);
>> + dump_lock(lock, "Blocked", out);
>> + }
>> + }
>> +
>> + fprintf(out, "\n");
>> +
>> + g_string_free(state, 1);
>> + g_string_free(lists, 1);
>> +}
>> +
>> +static int read_lvbx(char *line, struct lockres *res)
>> +{
>> + if (!(res->lvb = strdup(line)))
>> + return 0;
>> + return 1;
>> +}
>> +
>> +static int read_rmap(char *line, struct lockres *res)
>> +{
>> + int i;
>> +
>> + if (!(res->refmap = strdup(line)))
>> + return 0;
>> + i = strlen(res->refmap);
>> + if (i)
>> + res->refmap[i - 1] = '\0';
>> + return 1;
>> +}
>> +
>> +#define CURRENT_LOCK_PROTO 1
>> +static int read_lock(char *line, struct lockres *res)
>> +{
>> + char data[512];
>> + int version;
>> + struct lock *lock = NULL;
>> + __u8 queue;
>> + int ret;
>> + __u32 ck1, ck2;
>> +
>> + lock = calloc(1, sizeof(struct lock));
>> + if (!lock)
>> + goto bail;
>> +
>> + INIT_LIST_HEAD(&lock->list);
>> +
>> + /* read version */
>> + ret = sscanf(line, "%d,%s\n", &version, data);
>> + if (ret != 2)
>> + goto bail;
>> +
>> + if (version > CURRENT_LOCK_PROTO) {
>> + fprintf(stdout, "Lock string proto %u found, but %u is the "
>> + "highest I understand.\n", version, CURRENT_LOCK_PROTO);
>> + goto bail;
>> + }
>> +
>> + /* Version 1 */
>> + if (version == 1) {
>> + ret = sscanf(data, "%hhu,%hhd,%hhd,%hhu,%u:%u,%hhu,%hhu,%hhu,"
>> + "%hhu,%hhu,%hhu,%hhu,%hhu,%u", &queue, &lock->type,
>> + &lock->convert_type, &lock->node, &ck1, &ck2,
>> + &lock->ast_list, &lock->bast_list,
>> + &lock->ast_pending, &lock->bast_pending,
>> + &lock->convert_pending, &lock->lock_pending,
>> + &lock->cancel_pending, &lock->unlock_pending,
>> + &lock->refs);
>> + if (ret != 15)
>> + goto bail;
>> +
>> + snprintf(lock->cookie, sizeof(lock->cookie) - 1, "%u:%u",
>> + ck1, ck2);
>> + }
>> +
>> + switch (queue) {
>> + case GRANTED: list_add_tail(&lock->list, &res->granted);
>> + break;
>> + case CONVERTING:
>> + list_add_tail(&lock->list, &res->converting);
>> + break;
>> + case BLOCKED:
>> + list_add_tail(&lock->list, &res->blocked);
>> + break;
>> + default:
>> + free(lock);
>> + return 0;
>> + }
>> +
>> + return 1;
>> +
>> +bail:
>> + if (lock)
>> + free(lock);
>> + return 0;
>> +}
>> +
>> +#define CURRENT_LRES_PROTO 1
>> +static int read_lres(char *line, struct lockres *res)
>> +{
>> + char data[512];
>> + int version;
>> + int ret;
>> +
>> + /* read version */
>> + ret = sscanf(line, "%d,%s\n", &version, data);
>> + if (ret != 2)
>> + return 0;
>> +
>> + if (version > CURRENT_LRES_PROTO) {
>> + fprintf(stdout, "Lockres string proto %u found, but %u is the "
>> + "highest I understand.\n", version,
>> + CURRENT_LRES_PROTO);
>> + return 0;
>> + }
>> +
>> + /* Version 1 */
>> + if (version == 1) {
>> + ret = sscanf(data, "%hhu,%hu,%u,%hhu,%hhu,%hhu,%u,%hhu,%u,%u",
>> + &res->owner, &res->state, &res->last_used,
>> + &res->purge, &res->dirty, &res->recovering,
>> + &res->inflight_locks, &res->migration_pending,
>> + &res->asts_reserved, &res->refs);
>> + if (ret != 10)
>> + return 0;
>> + }
>> +
>> + return 1;
>> +}
>> +
>> +static void init_lockres(struct lockres *res)
>> +{
>> + memset(res, 0, sizeof(struct lockres));
>> + INIT_LIST_HEAD(&res->granted);
>> + INIT_LIST_HEAD(&res->converting);
>> + INIT_LIST_HEAD(&res->blocked);
>> +}
>> +
>> +static void clean_lockres(struct lockres *res)
>> +{
>> + struct list_head *iter, *iter2;
>> + struct lock *lock;
>> +
>> + if (res->lvb)
>> + free(res->lvb);
>> + if (res->refmap)
>> + free(res->refmap);
>> +
>> + if (!list_empty(&res->granted)) {
>> + list_for_each_safe(iter, iter2, &res->granted) {
>> + lock = list_entry(iter, struct lock, list);
>> + list_del(iter);
>> + free(lock);
>> + }
>> + }
>> +
>> + if (!list_empty(&res->converting)) {
>> + list_for_each_safe(iter, iter2, &res->converting) {
>> + lock = list_entry(iter, struct lock, list);
>> + list_del(iter);
>> + free(lock);
>> + }
>> + }
>> +
>> + if (!list_empty(&res->blocked)) {
>> + list_for_each_safe(iter, iter2, &res->blocked) {
>> + lock = list_entry(iter, struct lock, list);
>> + list_del(iter);
>> + free(lock);
>> + }
>> + }
>> +
>> + init_lockres(res);
>> +}
>> +
>> +static void read_lockres(FILE *file, struct lockres *res, int lvb)
>> +{
>> + char line[512];
>> +
>> + while (fgets(line, sizeof(line), file)) {
>> + if (line[0] == '\n')
>> + break;
>> + if (!strncmp(line, "LRES:", 5))
>> + read_lres(line + 5, res);
>> + else if (!strncmp(line, "RMAP:", 5))
>> + read_rmap(line + 5, res);
>> + else if (!strncmp(line, "LOCK:", 5))
>> + read_lock(line + 5, res);
>> + else if (!strncmp(line, "LVBX:", 5)) {
>> + if (lvb)
>> + read_lvbx(line + 5, res);
>> + }
>> + }
>> +}
>> +
>> +static int lockname_in_list(char *name, struct list_head *locklist)
>> +{
>> + struct locknames *l;
>> + struct list_head *iter, *iter2;
>> +
>> + if (!list_empty(locklist)) {
>> + list_for_each_safe(iter, iter2, locklist) {
>> + l = list_entry(iter, struct locknames, list);
>> + if (!strncmp(name, l->name, sizeof(l->name))) {
>> + list_del(iter);
>> + return 1;
>> + }
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int get_next_dlm_lockname(FILE *file, char *name, int len)
>> +{
>> + char line[512];
>> +
>> + while (fgets(line, sizeof(line), file)) {
>> + if (strncmp(line, "NAME:", 5))
>> + continue;
>> + sscanf(line + 5, "%s\n", name);
>> + return 1;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +#define DEBUGFS_MAGIC 0x64626720
>> +static errcode_t try_debugfs_path(const char *path)
>> +{
>> + errcode_t ret;
>> + struct stat64 stat_buf;
>> + struct statfs64 statfs_buf;
>> +
>> + ret = stat64(path, &stat_buf);
>> + if (ret || !S_ISDIR(stat_buf.st_mode))
>> + return O2CB_ET_SERVICE_UNAVAILABLE;
>> + ret = statfs64(path, &statfs_buf);
>> + if (ret || (statfs_buf.f_type != DEBUGFS_MAGIC))
>> + return O2CB_ET_SERVICE_UNAVAILABLE;
>> +
>> + return 0;
>> +}
>> +
>> +#define DLM_LOCKING_STATE_FORMAT_PATH "%s/o2dlm/%s/locking_state"
>> +static errcode_t open_dlm_locking_state(const char *debugfs_path,
>> + const char *uuid_str,
>> + FILE **state_file)
>> +{
>> + errcode_t ret = 0;
>> + char path[PATH_MAX];
>> +
>> + ret = snprintf(path, PATH_MAX - 1, DLM_LOCKING_STATE_FORMAT_PATH,
>> + debugfs_path, uuid_str);
>> + if ((ret <= 0) || (ret == (PATH_MAX - 1)))
>> + return O2CB_ET_INTERNAL_FAILURE;
>> +
>> + *state_file = fopen(path, "r");
>> + if (!*state_file) {
>> + switch (errno) {
>> + default:
>> + ret = O2CB_ET_INTERNAL_FAILURE;
>> + break;
>> +
>> + case ENOTDIR:
>> + case ENOENT:
>> + case EISDIR:
>> + ret = O2CB_ET_SERVICE_UNAVAILABLE;
>> + break;
>> +
>> + case EACCES:
>> + case EPERM:
>> + case EROFS:
>> + ret = O2CB_ET_PERMISSION_DENIED;
>> + break;
>> + }
>> + goto out;
>> + }
>> +
>> + ret = 0;
>> +out:
>> + return ret;
>> +}
>> +
>> +#define SYSFS_BASE "/sys/kernel/"
>> +#define DEBUGFS_PATH SYSFS_BASE "debug"
>> +#define DEBUGFS_ALTERNATE_PATH "/debug"
>> +
>> +void dump_dlm_locks(char *uuid, FILE *out, int dump_lvbs,
>> + struct list_head *locklist)
>> +{
>> + errcode_t ret;
>> + int err;
>> + const char *debugfs_path = DEBUGFS_PATH;
>> + struct stat64 stat_buf;
>> + FILE *file;
>> + char name[OCFS2_LOCK_ID_MAX_LEN];
>> + struct lockres res;
>> + int show_all_locks = 0;
>> +
>> + err = stat64(SYSFS_BASE, &stat_buf);
>> + if (err)
>> + debugfs_path = DEBUGFS_ALTERNATE_PATH;
>> +
>> + ret = try_debugfs_path(debugfs_path);
>> + if (ret) {
>> + fprintf(stderr, "Could not locate debugfs file system. "
>> + "Perhaps it is not mounted?\n");
>> + return;
>> + }
>> +
>> + ret = open_dlm_locking_state(debugfs_path, uuid, &file);
>> + if (ret) {
>> + fprintf(stderr, "Could not open debug state for \"%s\".\n"
>> + "Perhaps that OCFS2 file system is not mounted?\n",
>> + uuid);
>> + return;
>> + }
>> +
>> + show_all_locks = list_empty(locklist);
>> + init_lockres(&res);
>> +
>> + while (get_next_dlm_lockname(file, name, sizeof(name))) {
>> + if (show_all_locks || lockname_in_list(name, locklist)) {
>> + read_lockres(file, &res, dump_lvbs);
>> +
>> + dump_lockres(name, &res, out);
>> +
>> + clean_lockres(&res);
>> + }
>> +
>> + if (!show_all_locks && list_empty(locklist))
>> + break;
>> + }
>> +
>> + fclose(file);
>> +}
>> diff --git a/debugfs.ocfs2/include/dump_dlm_locks.h
>> b/debugfs.ocfs2/include/dump_dlm_locks.h
>> new file mode 100644
>> index 0000000..cf43318
>> --- /dev/null
>> +++ b/debugfs.ocfs2/include/dump_dlm_locks.h
>> @@ -0,0 +1,85 @@
>> +/*
>> + * dump_dlm_locks.h
>> + *
>> + * Function prototypes, macros, etc. for related 'C' files
>> + *
>> + * Copyright (C) 2008 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 _DUMP_DLM_LOCKS_H_
>> +#define _DUMP_DLM_LOCKS_H_
>> +
>> +#define DLM_LOCK_RES_UNINITED 0x00000001
>> +#define DLM_LOCK_RES_RECOVERING 0x00000002
>> +#define DLM_LOCK_RES_READY 0x00000004
>> +#define DLM_LOCK_RES_DIRTY 0x00000008
>> +#define DLM_LOCK_RES_IN_PROGRESS 0x00000010
>> +#define DLM_LOCK_RES_MIGRATING 0x00000020
>> +#define DLM_LOCK_RES_DROPPING_REF 0x00000040
>> +#define DLM_LOCK_RES_BLOCK_DIRTY 0x00001000
>> +#define DLM_LOCK_RES_SETREF_INPROG 0x00002000
>> +
>> +#define GRANTED 0
>> +#define CONVERTING 1
>> +#define BLOCKED 2
>> +
>> +struct lockres {
>> + __u8 owner;
>> + __u16 state;
>> + __u32 last_used;
>> + __u32 inflight_locks;
>> + __u32 asts_reserved;
>> + __u32 refs;
>> + __u8 purge;
>> + __u8 dirty;
>> + __u8 recovering;
>> + __u8 migration_pending;
>> + char *refmap;
>> + char *lvb;
>> + struct list_head granted;
>> + struct list_head converting;
>> + struct list_head blocked;
>> +};
>> +
>> +struct lock {
>> + __s8 type;
>> + __s8 convert_type;
>> + __u8 node;
>> + __u8 ast_list;
>> + __u8 bast_list;
>> + __u8 ast_pending;
>> + __u8 bast_pending;
>> + __u8 convert_pending;
>> + __u8 lock_pending;
>> + __u8 cancel_pending;
>> + __u8 unlock_pending;
>> + __u32 refs;
>> + char cookie[32];
>> + struct list_head list;
>> +};
>> +
>> +struct locknames {
>> + char name[OCFS2_LOCK_ID_MAX_LEN];
>> + struct list_head list;
>> +};
>> +
>> +void dump_dlm_locks(char *uuid, FILE *out, int dump_lvbs,
>> + struct list_head *all_locks);
>> +
>> +#endif /* _DUMP_DLM_LOCKS_H_ */
>> diff --git a/debugfs.ocfs2/include/main.h b/debugfs.ocfs2/include/main.h
>> index f0e0c2b..942a1e4 100644
>> --- a/debugfs.ocfs2/include/main.h
>> +++ b/debugfs.ocfs2/include/main.h
>> @@ -3,7 +3,7 @@
>> *
>> * Function prototypes, macros, etc. for related 'C' files
>> *
>> - * Copyright (C) 2004 Oracle. All rights reserved.
>> + * Copyright (C) 2004, 2008 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
>> @@ -20,7 +20,6 @@
>> * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>> * Boston, MA 021110-1307, USA.
>> *
>> - * Authors: Sunil Mushran
>> */
>>
>> #ifndef __MAIN_H__
>> @@ -34,6 +33,7 @@
>> #include <string.h>
>> #include <sys/types.h>
>> #include <sys/stat.h>
>> +#include <sys/statfs.h>
>> #include <fcntl.h>
>> #include <errno.h>
>> #include <pwd.h>
>> @@ -161,6 +161,7 @@ typedef struct _dbgfs_opts {
>> #include <find_block_inode.h>
>> #include <find_inode_paths.h>
>> #include <dump_fs_locks.h>
>> +#include <dump_dlm_locks.h>
>> #include <dump.h>
>>
>> #endif /* __MAIN_H__ */
More information about the Ocfs2-tools-devel
mailing list