[Ocfs2-tools-devel] [PATCH 05/10] debugfs: Decode dentry locks

Sunil Mushran sunil.mushran at oracle.com
Tue Jul 22 14:44:13 PDT 2008


This patch teaches debugfs to encode and decode dentry lockres'
that have a different encoding scheme than others.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 debugfs.ocfs2/commands.c            |   50 ++++++------------
 debugfs.ocfs2/main.c                |   42 ++++++++-------
 debugfs.ocfs2/utils.c               |   36 ++++++++-----
 include/ocfs2-kernel/ocfs2_lockid.h |   35 +++++++++++++
 include/ocfs2/ocfs2.h               |    8 ++-
 libocfs2/dlm.c                      |    8 ++--
 libocfs2/lockid.c                   |   97 +++++++++++++++-------------------
 7 files changed, 148 insertions(+), 128 deletions(-)

diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 0fb89c4..7fff4ba 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -1360,49 +1360,33 @@ static void do_rdump(char **args)
  */
 static void do_encode_lockres (char **args)
 {
-	struct ocfs2_dinode *inode;
+	struct ocfs2_dinode *inode = (struct ocfs2_dinode *)gbls.blockbuf;
 	uint64_t blkno;
-	char *buf = NULL;
+	uint32_t gen;
 	errcode_t ret = 0;
-	char suprlock[50] = "\0";
-	char metalock[50] = "\0";
-	char datalock[50] = "\0";
-	char rdwrlock[50] = "\0";
+	char lock[50] = "\0";
+	enum ocfs2_lock_type type = OCFS2_LOCK_TYPE_META;
 
 	if (process_inode_args(args, &blkno))
-		return ;
+		return;
 
-	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
-		ret = ocfs2_encode_lockres(OCFS2_LOCK_TYPE_SUPER, blkno, 0,
-					   suprlock);
-	} else {
-		buf = gbls.blockbuf;
-		ret = ocfs2_read_inode(gbls.fs, blkno, buf);
-		if (!ret) {
-			inode = (struct ocfs2_dinode *)buf;
-			ocfs2_encode_lockres(OCFS2_LOCK_TYPE_META, blkno,
-					     inode->i_generation, metalock);
-			ocfs2_encode_lockres(OCFS2_LOCK_TYPE_DATA, blkno,
-					     inode->i_generation, datalock);
-			ocfs2_encode_lockres(OCFS2_LOCK_TYPE_RW, blkno,
-					     inode->i_generation, rdwrlock);
+	if (blkno == OCFS2_SUPER_BLOCK_BLKNO)
+		type = OCFS2_LOCK_TYPE_SUPER;
+	else {
+		ret = ocfs2_read_inode(gbls.fs, blkno, (char *)inode);
+		if (ret) {
+			com_err(args[0], ret, "while reading inode %"PRIu64"",
+				blkno);
+			return;
 		}
+		gen = inode->i_generation;
 	}
 
-	if (ret) {
-		com_err(args[0], ret, "while reading inode %"PRIu64"", blkno);
-		return ;
-	}
+	ocfs2_encode_lockres(type, blkno, gen, 0, lock);
 
 	printf("\t");
-	if (*suprlock)
-		printf("%s ", suprlock);
-	if (*metalock)
-		printf("%s ", metalock);
-	if (*datalock)
-		printf("%s ", datalock);
-	if (*rdwrlock)
-		printf("%s ", rdwrlock);
+	if (*lock)
+		printf("%s ", lock);
 	printf("\n");
 
 	return ;
diff --git a/debugfs.ocfs2/main.c b/debugfs.ocfs2/main.c
index 3588726..36a5192 100644
--- a/debugfs.ocfs2/main.c
+++ b/debugfs.ocfs2/main.c
@@ -115,8 +115,9 @@ static void process_decode_lockres(int argc, char **argv, int startind)
 	int i;
 	errcode_t ret;
 	enum ocfs2_lock_type type;
-	uint64_t blkno;
-	uint32_t generation;
+	uint64_t blkno = 0;
+	uint32_t generation = 0;
+	uint64_t parent = 0;
 
 	if (startind + 1 > argc) {
 		usage(gbls.progname);
@@ -124,34 +125,33 @@ static void process_decode_lockres(int argc, char **argv, int startind)
 	}
 
 	for (i = startind; i < argc; ++i) {
-		ret = ocfs2_decode_lockres(argv[i], -1, &type, &blkno,
-					   &generation);
-		if (ret) {
-			com_err(gbls.progname, ret, "while decoding lockres %s",
-				argv[i]);
+		ret = ocfs2_decode_lockres(argv[i], &type, &blkno,
+					   &generation, &parent);
+		if (ret)
 			continue;
-		}
 
 		printf("Lockres:    %s\n", argv[i]);
-		printf("Type:       %s\n",
-		       ocfs2_get_lock_type_string(type));
-		printf("Block:      %"PRIu64"\n", blkno);
-		printf("Generation: 0x%08x\n", generation);
+		printf("Type:       %s\n", ocfs2_lock_type_string(type));
+		if (blkno)
+			printf("Block:      %"PRIu64"\n", blkno);
+		if (generation)
+			printf("Generation: 0x%08x\n", generation);
+		if (parent)
+			printf("Parent:	    %"PRIu64"\n", parent);
 		printf("\n");
 	}
 
 	return ;
 }
 
-/* [M|D|S] [blkno] [generation] */
 static void process_encode_lockres(int argc, char **argv, int startind)
 {
 	int i;
 	errcode_t ret;
 	enum ocfs2_lock_type type;
 	uint64_t blkno;
-	uint32_t generation;
-	char lockres[50];
+	uint64_t extra; /* generation or parent */
+	char lock[50];
 
 	if (startind + 3 > argc) {
 		usage(gbls.progname);
@@ -162,15 +162,19 @@ static void process_encode_lockres(int argc, char **argv, int startind)
 
 	type = ocfs2_get_lock_type(argv[i++][0]);
 	blkno = strtoull(argv[i++], NULL, 0);
-	generation = strtoul(argv[i++], NULL, 0);
+	extra = strtoull(argv[i++], NULL, 0);
 
-	ret = ocfs2_encode_lockres(type, blkno, generation, lockres);
+	if (type == OCFS2_LOCK_TYPE_DENTRY)
+		ret = ocfs2_encode_lockres(type, blkno, 0, extra, lock);
+	else
+		ret = ocfs2_encode_lockres(type, blkno, (uint32_t)extra, 0,
+					   lock);
 	if (ret) {
-		com_err(gbls.progname, ret, "while encoding lockres");
+		com_err(gbls.progname, ret, "while encoding lockname");
 		return ;
 	}
 
-	printf("%s\n", lockres);
+	printf("%s\n", lock);
 
 	return ;
 }
diff --git a/debugfs.ocfs2/utils.c b/debugfs.ocfs2/utils.c
index 5eb6e90..c78d5b7 100644
--- a/debugfs.ocfs2/utils.c
+++ b/debugfs.ocfs2/utils.c
@@ -325,30 +325,36 @@ void close_pager(FILE *stream)
  * inodestr_to_inode()
  *
  * Returns ino if string is of the form <ino>
- *
- * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
- * redistributed under the terms of the GNU Public License.
  */
 int inodestr_to_inode(char *str, uint64_t *blkno)
 {
 	int len;
+	char *buf = NULL;
 	char *end;
+	int ret = OCFS2_ET_INVALID_LOCKRES;
 
 	len = strlen(str);
-	if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) {
-		if (ocfs2_get_lock_type(str[1]) < OCFS2_NUM_LOCK_TYPES) {
-			if (!ocfs2_decode_lockres(str+1, len-2, NULL, blkno,
-						  NULL))
-				return 0;
-			else
-				return -1;
-		}
-		*blkno = strtoull(str+1, &end, 0);
-		if (*end=='>')
-			return 0;
+	if (!((len > 2) && (str[0] == '<') && (str[len - 1] == '>')))
+		goto bail;
+
+	ret = OCFS2_ET_NO_MEMORY;
+	buf = strndup(str + 1, len - 2);
+	if (!buf)
+		goto bail;
+
+	if (ocfs2_get_lock_type(*buf < OCFS2_NUM_LOCK_TYPES))
+		ret = ocfs2_decode_lockres(buf, NULL, blkno, NULL, NULL);
+	else {
+		*blkno = strtoull(buf, &end, 0);
+		if (*end)
+			ret = OCFS2_ET_INVALID_LOCKRES;
 	}
 
-	return -1;
+bail:
+	if (buf)
+		free(buf);
+
+	return ret;
 }
 
 /*
diff --git a/include/ocfs2-kernel/ocfs2_lockid.h b/include/ocfs2-kernel/ocfs2_lockid.h
index 7dd9e1e..82c200f 100644
--- a/include/ocfs2-kernel/ocfs2_lockid.h
+++ b/include/ocfs2-kernel/ocfs2_lockid.h
@@ -35,12 +35,17 @@
 #define OCFS2_LOCK_ID_MAX_LEN  32
 #define OCFS2_LOCK_ID_PAD "000000"
 
+#define OCFS2_DENTRY_LOCK_INO_START 18
+
 enum ocfs2_lock_type {
 	OCFS2_LOCK_TYPE_META = 0,
 	OCFS2_LOCK_TYPE_DATA,
 	OCFS2_LOCK_TYPE_SUPER,
 	OCFS2_LOCK_TYPE_RENAME,
 	OCFS2_LOCK_TYPE_RW,
+	OCFS2_LOCK_TYPE_DENTRY,
+	OCFS2_LOCK_TYPE_OPEN,
+	OCFS2_LOCK_TYPE_FLOCK,
 	OCFS2_NUM_LOCK_TYPES
 };
 
@@ -63,6 +68,15 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
 		case OCFS2_LOCK_TYPE_RW:
 			c = 'W';
 			break;
+		case OCFS2_LOCK_TYPE_DENTRY:
+			c = 'N';
+			break;
+		case OCFS2_LOCK_TYPE_OPEN:
+			c = 'O';
+			break;
+		case OCFS2_LOCK_TYPE_FLOCK:
+			c = 'F';
+			break;
 		default:
 			c = '\0';
 	}
@@ -70,4 +84,25 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
 	return c;
 }
 
+static char *ocfs2_lock_type_strings[] = {
+	[OCFS2_LOCK_TYPE_META] = "Meta",
+	[OCFS2_LOCK_TYPE_DATA] = "Data",
+	[OCFS2_LOCK_TYPE_SUPER] = "Super",
+	[OCFS2_LOCK_TYPE_RENAME] = "Rename",
+	/* Need to differntiate from [R]ename.. serializing writes is the
+	 * important job it does, anyway. */
+	[OCFS2_LOCK_TYPE_RW] = "Write/Read",
+	[OCFS2_LOCK_TYPE_DENTRY] = "Dentry",
+	[OCFS2_LOCK_TYPE_OPEN] = "Open",
+	[OCFS2_LOCK_TYPE_FLOCK] = "Flock",
+};
+
+static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
+{
+#ifdef __KERNEL__
+	BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
+#endif
+	return ocfs2_lock_type_strings[type];
+}
+
 #endif  /* OCFS2_LOCKID_H */
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 7c21d28..c8d446e 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -583,10 +583,12 @@ enum ocfs2_lock_type ocfs2_get_lock_type(char c);
 char *ocfs2_get_lock_type_string(enum ocfs2_lock_type type);
 
 errcode_t ocfs2_encode_lockres(enum ocfs2_lock_type type, uint64_t blkno,
-			       uint32_t generation, char *lockres);
+			       uint32_t generation, uint64_t parent,
+			       char *lockres);
 
-errcode_t ocfs2_decode_lockres(char *lockres, int len, enum ocfs2_lock_type *type,
-			       uint64_t *blkno, uint32_t *generation);
+errcode_t ocfs2_decode_lockres(char *lockres, enum ocfs2_lock_type *type,
+			       uint64_t *blkno, uint32_t *generation,
+			       uint64_t *parent);
 
 /* write the superblock at the specific block. */
 errcode_t ocfs2_write_backup_super(ocfs2_filesys *fs, uint64_t blkno);
diff --git a/libocfs2/dlm.c b/libocfs2/dlm.c
index cf5f61b..3a5015c 100644
--- a/libocfs2/dlm.c
+++ b/libocfs2/dlm.c
@@ -253,7 +253,7 @@ errcode_t ocfs2_super_lock(ocfs2_filesys *fs)
 	errcode_t ret;
 
 	ocfs2_encode_lockres(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,
-			     0, lock_name);
+			     0, 0, lock_name);
 
 	ret = o2dlm_lock(fs->fs_dlm_ctxt, lock_name,
 			 O2DLM_TRYLOCK, O2DLM_LEVEL_EXMODE);
@@ -267,7 +267,7 @@ errcode_t ocfs2_super_unlock(ocfs2_filesys *fs)
 	errcode_t ret;
 
 	ocfs2_encode_lockres(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,
-			     0, lock_name);
+			     0, 0, lock_name);
 
 	ret = o2dlm_unlock(fs->fs_dlm_ctxt, lock_name);
 
@@ -283,7 +283,7 @@ errcode_t ocfs2_meta_lock(ocfs2_filesys *fs,
 	errcode_t ret;
 
 	ocfs2_encode_lockres(OCFS2_LOCK_TYPE_META, ci->ci_blkno,
-			     ci->ci_inode->i_generation, lock_name);
+			     ci->ci_inode->i_generation, 0, lock_name);
 
 	ret = o2dlm_lock(fs->fs_dlm_ctxt, lock_name, flags, level);
 
@@ -297,7 +297,7 @@ errcode_t ocfs2_meta_unlock(ocfs2_filesys *fs,
 	errcode_t ret;
 
 	ocfs2_encode_lockres(OCFS2_LOCK_TYPE_META, ci->ci_blkno,
-			     ci->ci_inode->i_generation, lock_name);
+			     ci->ci_inode->i_generation, 0, lock_name);
 
 	ret = o2dlm_unlock(fs->fs_dlm_ctxt, lock_name);
 
diff --git a/libocfs2/lockid.c b/libocfs2/lockid.c
index 7046e51..b2f1e76 100644
--- a/libocfs2/lockid.c
+++ b/libocfs2/lockid.c
@@ -5,7 +5,7 @@
  *
  * Encode and decode lockres name
  *
- * 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
@@ -22,6 +22,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include "ocfs2/byteorder.h"
 #include "ocfs2/ocfs2.h"
 
 #include <string.h>
@@ -40,31 +41,20 @@ enum ocfs2_lock_type ocfs2_get_lock_type(char c)
 		return OCFS2_LOCK_TYPE_RENAME;
 	case 'W':
 		return OCFS2_LOCK_TYPE_RW;
+	case 'N':
+		return OCFS2_LOCK_TYPE_DENTRY;
+	case 'O':
+		return OCFS2_LOCK_TYPE_OPEN;
+	case 'F':
+		return OCFS2_LOCK_TYPE_FLOCK;
 	default:
 		return OCFS2_NUM_LOCK_TYPES;
 	}
 }
 
-char *ocfs2_get_lock_type_string(enum ocfs2_lock_type type)
-{
-	switch (type) {
-	case OCFS2_LOCK_TYPE_META:
-		return "Metadata";
-	case OCFS2_LOCK_TYPE_DATA:
-		return "Data";
-	case OCFS2_LOCK_TYPE_SUPER:
-		return "Superblock";
-	case OCFS2_LOCK_TYPE_RENAME:
-		return "Rename";
-	case OCFS2_LOCK_TYPE_RW:
-		return "Write/Read";
-	default:
-		return NULL;
-	}
-}
-
 errcode_t ocfs2_encode_lockres(enum ocfs2_lock_type type, uint64_t blkno,
-			       uint32_t generation, char *lockres)
+			       uint32_t generation, uint64_t parent,
+			       char *lockres)
 {
 	if (type >= OCFS2_NUM_LOCK_TYPES)
 		return OCFS2_ET_INVALID_LOCKRES;
@@ -73,53 +63,52 @@ errcode_t ocfs2_encode_lockres(enum ocfs2_lock_type type, uint64_t blkno,
 	generation = ((type == OCFS2_LOCK_TYPE_SUPER) ||
 		      (type == OCFS2_LOCK_TYPE_RENAME)) ? 0 : generation;
 
-	snprintf(lockres, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016"PRIx64"%08x",
-		 ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD,
-		 blkno, generation);
+	if (type != OCFS2_LOCK_TYPE_DENTRY) {
+		snprintf(lockres, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016"PRIx64"%08x",
+			 ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD,
+			 blkno, generation);
+	} else {
+	}
 
 	return 0;
 }
 
-errcode_t ocfs2_decode_lockres(char *lockres, int len, enum ocfs2_lock_type *type,
-			       uint64_t *blkno, uint32_t *generation)
+errcode_t ocfs2_decode_lockres(char *lockres, enum ocfs2_lock_type *type,
+			       uint64_t *blkno, uint32_t *generation,
+			       uint64_t *parent)
 {
-	char *lock = NULL;
-	errcode_t ret = OCFS2_ET_NO_MEMORY;
-	char blkstr[20];
 	int i = 0;
+	enum ocfs2_lock_type t;
+	char *l = lockres;
+	uint64_t b = 0;
+	uint64_t p = 0;
+	uint32_t g = 0;
 	
-	if (len != -1) {
-		lock = calloc(len+1, 1);
-		if (!lock)
-			goto bail;
-		strncpy(lock, lockres, len);
-	} else
-		lock = lockres;
-
-	ret = OCFS2_ET_INVALID_LOCKRES;
-	
-	if ((strlen(lock) + 1) != OCFS2_LOCK_ID_MAX_LEN)
-		goto bail;
+	if ((t = ocfs2_get_lock_type(*l)) >= OCFS2_NUM_LOCK_TYPES)
+		return OCFS2_ET_INVALID_LOCKRES;
 
-	if (ocfs2_get_lock_type(lock[0]) >= OCFS2_NUM_LOCK_TYPES)
-		goto bail;
+	if (t != OCFS2_LOCK_TYPE_DENTRY) {
+		i = sscanf(l + 1, OCFS2_LOCK_ID_PAD"%016llx%08x", &b, &g);
+		if (i != 2)
+			return OCFS2_ET_INVALID_LOCKRES;
+	} else {
+		i = sscanf(l + 1, "%016llx", &p);
+		if (i != 1)
+			return OCFS2_ET_INVALID_LOCKRES;
+		b = strtoull(&l[OCFS2_DENTRY_LOCK_INO_START], NULL, 16);
+	}
 
 	if (type)
-		*type = ocfs2_get_lock_type(lock[i]);
+		*type = t;
 
-	i = 1 + strlen(OCFS2_LOCK_ID_PAD);
-	memset(blkstr, 0, sizeof(blkstr));
-	memcpy(blkstr, &lock[i], 16);
 	if (blkno)
-		*blkno = strtoull(blkstr, NULL, 16);
+		*blkno = b;
 
-	i += 16;
 	if (generation)
-		*generation = strtoul(&lock[i], NULL, 16);
+		*generation = g;
+
+	if (parent)
+		*parent = p;
 
-	ret = 0;
-bail:
-	if (len != -1 && lock)
-		free(lock);
-	return ret;
+	return 0;
 }
-- 
1.5.4.3




More information about the Ocfs2-tools-devel mailing list