Stefan Behrens
2013-Apr-12  08:26 UTC
[PATCH v3 3/4] Btrfs-progs: add more subvol fields to btrfs-list
The parent UUID, all generation values and all timestamps that
are available in the root_item are added.
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
---
v2 -> v3:
- After Wang Shilong explained the purpose of one part of the code
  where I added a "TODO: what is it good for?" comment, a mistake was
  visible, and it was possible to replace the question in the comment
  with some meaningful explanation.
 btrfs-list.c | 276 +++++++++++++++++++++++++++++++++++------------------------
 btrfs-list.h |  39 ++++++++-
 2 files changed, 200 insertions(+), 115 deletions(-)
diff --git a/btrfs-list.c b/btrfs-list.c
index 70da9a3..f816bbd 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -68,6 +68,21 @@ static struct {
 		.width		= 6,
 	},
 	{
+		.name		= "ogen",
+		.column_name	= "OGen",
+		.width		= 6,
+	},
+	{
+		.name		= "sgen",
+		.column_name	= "SGen",
+		.width		= 6,
+	},
+	{
+		.name		= "rgen",
+		.column_name	= "RGen",
+		.width		= 6,
+	},
+	{
 		.name		= "parent",
 		.column_name	= "Parent",
 		.width		= 7,
@@ -78,13 +93,24 @@ static struct {
 		.width		= 10,
 	},
 	{
+		.name		= "ctime",
+		.column_name	= "CTime",
+		.width		= 21,
+	},
+	{
 		.name		= "otime",
 		.column_name	= "OTime",
 		.width		= 21,
 	},
 	{
-		.name		= "parent_uuid",
-		.column_name	= "Parent UUID",
+		.name		= "stime",
+		.column_name	= "STime",
+		.width		= 21,
+	},
+	{
+		.name		= "rtime",
+		.column_name	= "RTime",
+		.width		= 21,
 	},
 	{
 		.name		= "uuid",
@@ -92,6 +118,21 @@ static struct {
 		.width		= 38,
 	},
 	{
+		.name		= "puuid",
+		.column_name	= "PUUID",
+		.width		= 38,
+	},
+	{
+		.name		= "ruuid",
+		.column_name	= "RUUID",
+		.width		= 38,
+	},
+	{
+		.name		= "dirid",
+		.column_name	= "DirID",
+		.width		= 6,
+	},
+	{
 		.name		= "path",
 		.column_name	= "Path",
 		.width		= 0,
@@ -391,52 +432,73 @@ static struct root_info *root_tree_search(struct
root_lookup *root_tree,
 	return NULL;
 }
 
-static int update_root(struct root_lookup *root_lookup,
-		       u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
-		       u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
-		       time_t ot, void *uuid, void *puuid)
+static int set_root_info(struct root_info *rinfo, u64 ref_tree, u64
root_offset,
+			 u64 dir_id, char *name, int name_len,
+			 struct btrfs_root_item *ritem, u32 ritem_len)
 {
-	struct root_info *ri;
+	int is_v0 = (ritem_len <= sizeof(struct btrfs_root_item_v0));
 
-	ri = root_tree_search(root_lookup, root_id);
-	if (!ri || ri->root_id != root_id)
-		return -ENOENT;
-	if (name && name_len > 0) {
-		if (ri->name)
-			free(ri->name);
+	if (root_offset)
+		rinfo->root_offset = root_offset;
+	if (ref_tree)
+		rinfo->ref_tree = ref_tree;
+	if (dir_id)
+		rinfo->dir_id = dir_id;
+
+	if (ritem) {
+		rinfo->gen = btrfs_root_generation(ritem);
+		rinfo->flags = btrfs_root_flags(ritem);
+	}
 
-		ri->name = malloc(name_len + 1);
-		if (!ri->name) {
+	if (ritem && !is_v0) {
+		rinfo->cgen = btrfs_root_ctransid(ritem);
+		rinfo->ogen = btrfs_root_otransid(ritem);
+		rinfo->sgen = btrfs_root_stransid(ritem);
+		rinfo->rgen = btrfs_root_rtransid(ritem);
+		rinfo->ctime = btrfs_stack_timespec_sec(&ritem->ctime);
+		rinfo->otime = btrfs_stack_timespec_sec(&ritem->otime);
+		rinfo->stime = btrfs_stack_timespec_sec(&ritem->stime);
+		rinfo->rtime = btrfs_stack_timespec_sec(&ritem->rtime);
+		memcpy(rinfo->uuid, ritem->uuid, BTRFS_UUID_SIZE);
+		memcpy(rinfo->puuid, ritem->parent_uuid, BTRFS_UUID_SIZE);
+		memcpy(rinfo->ruuid, ritem->received_uuid, BTRFS_UUID_SIZE);
+	} else if (ritem && is_v0 && root_offset) {
+		/*
+		 * old style (v0) root items don''t contain an otransid field.
+		 * But for snapshots, root_offset equals to its original
+		 * generation.
+		 */
+		rinfo->ogen = root_offset;
+	}
+
+	if (name && name_len > 0) {
+		rinfo->name = malloc(name_len + 1);
+		if (!rinfo->name) {
 			fprintf(stderr, "memory allocation failed\n");
-			exit(1);
+			return -1;
 		}
-		strncpy(ri->name, name, name_len);
-		ri->name[name_len] = 0;
+		strncpy(rinfo->name, name, name_len);
+		rinfo->name[name_len] = 0;
 	}
-	if (ref_tree)
-		ri->ref_tree = ref_tree;
-	if (root_offset)
-		ri->root_offset = root_offset;
-	if (flags)
-		ri->flags = flags;
-	if (dir_id)
-		ri->dir_id = dir_id;
-	if (gen)
-		ri->gen = gen;
-	if (ogen)
-		ri->ogen = ogen;
-	if (!ri->ogen && root_offset)
-		ri->ogen = root_offset;
-	if (ot)
-		ri->otime = ot;
-	if (uuid)
-		memcpy(&ri->uuid, uuid, BTRFS_UUID_SIZE);
-	if (puuid)
-		memcpy(&ri->puuid, puuid, BTRFS_UUID_SIZE);
 
 	return 0;
 }
 
+static int update_root(struct root_lookup *root_lookup, u64 root_id,
+		       u64 ref_tree, u64 root_offset, u64 dir_id, char *name,
+		       int name_len, struct btrfs_root_item *ritem,
+		       u32 ritem_len)
+{
+	struct root_info *rinfo;
+
+	rinfo = root_tree_search(root_lookup, root_id);
+	if (!rinfo || rinfo->root_id != root_id)
+		return -ENOENT;
+
+	return set_root_info(rinfo, ref_tree, root_offset, dir_id, name,
+			     name_len, ritem, ritem_len);
+}
+
 /*
  * add_root - update the existed root, or allocate a new root and insert it
  *	      into the lookup tree.
@@ -446,66 +508,36 @@ static int update_root(struct root_lookup *root_lookup,
  * dir_id: inode id of the directory in ref_tree where this root can be found.
  * name: the name of root_id in that directory
  * name_len: the length of name
- * ogen: the original generation of the root
- * gen: the current generation of the root
- * ot: the original time(create time) of the root
- * uuid: uuid of the root
- * puuid: uuid of the root parent if any
+ * ritem: root_item
+ * ritem_len: root_item length
  */
-static int add_root(struct root_lookup *root_lookup,
-		    u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
-		    u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
-		    time_t ot, void *uuid, void *puuid)
+static int add_root(struct root_lookup *root_lookup, u64 root_id, u64 ref_tree,
+		    u64 root_offset, u64 dir_id, char *name, int name_len,
+		    struct btrfs_root_item *ritem, u32 ritem_len)
 {
-	struct root_info *ri;
+	struct root_info *rinfo;
 	int ret;
 
-	ret = update_root(root_lookup, root_id, ref_tree, root_offset, flags,
-			  dir_id, name, name_len, ogen, gen, ot, uuid, puuid);
+	ret = update_root(root_lookup, root_id, ref_tree, root_offset, dir_id,
+			  name, name_len, ritem, ritem_len);
 	if (!ret)
 		return 0;
 
-	ri = malloc(sizeof(*ri));
-	if (!ri) {
+	rinfo = malloc(sizeof(*rinfo));
+	if (!rinfo) {
 		printf("memory allocation failed\n");
 		exit(1);
 	}
-	memset(ri, 0, sizeof(*ri));
-	ri->root_id = root_id;
 
-	if (name && name_len > 0) {
-		ri->name = malloc(name_len + 1);
-		if (!ri->name) {
-			fprintf(stderr, "memory allocation failed\n");
-			exit(1);
-		}
-		strncpy(ri->name, name, name_len);
-		ri->name[name_len] = 0;
-	}
-	if (ref_tree)
-		ri->ref_tree = ref_tree;
-	if (dir_id)
-		ri->dir_id = dir_id;
-	if (root_offset)
-		ri->root_offset = root_offset;
-	if (flags)
-		ri->flags = flags;
-	if (gen)
-		ri->gen = gen;
-	if (ogen)
-		ri->ogen = ogen;
-	if (!ri->ogen && root_offset)
-		ri->ogen = root_offset;
-	if (ot)
-		ri->otime = ot;
-
-	if (uuid)
-		memcpy(&ri->uuid, uuid, BTRFS_UUID_SIZE);
-
-	if (puuid)
-		memcpy(&ri->puuid, puuid, BTRFS_UUID_SIZE);
-
-	ret = root_tree_insert(root_lookup, ri);
+	memset(rinfo, 0, sizeof(*rinfo));
+	rinfo->root_id = root_id;
+
+	ret = set_root_info(rinfo, ref_tree, root_offset, dir_id, name,
+			    name_len, ritem, ritem_len);
+	if (ret)
+		exit(1);
+
+	ret = root_tree_insert(root_lookup, rinfo);
 	if (ret) {
 		printf("failed to insert tree %llu\n", (unsigned long
long)root_id);
 		exit(1);
@@ -993,13 +1025,7 @@ static int __list_subvol_search(int fd, struct root_lookup
*root_lookup)
 	int name_len;
 	char *name;
 	u64 dir_id;
-	u64 gen = 0;
-	u64 ogen;
-	u64 flags;
 	int i;
-	time_t t;
-	u8 uuid[BTRFS_UUID_SIZE];
-	u8 puuid[BTRFS_UUID_SIZE];
 
 	root_lookup_init(root_lookup);
 	memset(&args, 0, sizeof(args));
@@ -1051,28 +1077,11 @@ static int __list_subvol_search(int fd, struct
root_lookup *root_lookup)
 				dir_id = btrfs_stack_root_ref_dirid(ref);
 
 				add_root(root_lookup, sh.objectid, sh.offset,
-					 0, 0, dir_id, name, name_len, 0, 0, 0,
-					 NULL, NULL);
+					 0, dir_id, name, name_len, NULL, 0);
 			} else if (sh.type == BTRFS_ROOT_ITEM_KEY) {
 				ri = (struct btrfs_root_item *)(args.buf + off);
-				gen = btrfs_root_generation(ri);
-				flags = btrfs_root_flags(ri);
-				if(sh.len >
-				   sizeof(struct btrfs_root_item_v0)) {
-					t = ri->otime.sec;
-					ogen = btrfs_root_otransid(ri);
-					memcpy(uuid, ri->uuid, BTRFS_UUID_SIZE);
-					memcpy(puuid, ri->parent_uuid, BTRFS_UUID_SIZE);
-				} else {
-					t = 0;
-					ogen = 0;
-					memset(uuid, 0, BTRFS_UUID_SIZE);
-					memset(puuid, 0, BTRFS_UUID_SIZE);
-				}
-
 				add_root(root_lookup, sh.objectid, 0,
-					 sh.offset, flags, 0, NULL, 0, ogen,
-					 gen, t, uuid, puuid);
+					 sh.offset, 0, NULL, 0, ri, sh.len);
 			}
 
 			off += sh.len;
@@ -1335,15 +1344,32 @@ static int print_subvolume_column(struct root_info
*subv,
 	case BTRFS_LIST_GENERATION:
 		width = printf("%llu", subv->gen);
 		break;
+	case BTRFS_LIST_CGENERATION:
+		width = printf("%llu", subv->cgen);
+		break;
 	case BTRFS_LIST_OGENERATION:
 		width = printf("%llu", subv->ogen);
 		break;
+	case BTRFS_LIST_SGENERATION:
+		width = printf("%llu", subv->sgen);
+		break;
+	case BTRFS_LIST_RGENERATION:
+		width = printf("%llu", subv->rgen);
+		break;
 	case BTRFS_LIST_PARENT:
 		width = printf("%llu", subv->ref_tree);
 		break;
 	case BTRFS_LIST_TOP_LEVEL:
 		width = printf("%llu", subv->top_id);
 		break;
+	case BTRFS_LIST_CTIME:
+		if (subv->ctime)
+			strftime(tstr, 256, "%Y-%m-%d %X",
+				 localtime(&subv->ctime));
+		else
+			strcpy(tstr, "-");
+		width = printf("%s", tstr);
+		break;
 	case BTRFS_LIST_OTIME:
 		if (subv->otime)
 			strftime(tstr, 256, "%Y-%m-%d %X",
@@ -1352,6 +1378,22 @@ static int print_subvolume_column(struct root_info *subv,
 			strcpy(tstr, "-");
 		width = printf("%s", tstr);
 		break;
+	case BTRFS_LIST_STIME:
+		if (subv->stime)
+			strftime(tstr, 256, "%Y-%m-%d %X",
+				 localtime(&subv->stime));
+		else
+			strcpy(tstr, "-");
+		width = printf("%s", tstr);
+		break;
+	case BTRFS_LIST_RTIME:
+		if (subv->rtime)
+			strftime(tstr, 256, "%Y-%m-%d %X",
+				 localtime(&subv->rtime));
+		else
+			strcpy(tstr, "-");
+		width = printf("%s", tstr);
+		break;
 	case BTRFS_LIST_UUID:
 		if (uuid_is_null(subv->uuid))
 			strcpy(uuidparse, "-");
@@ -1359,6 +1401,13 @@ static int print_subvolume_column(struct root_info *subv,
 			uuid_unparse(subv->uuid, uuidparse);
 		width = printf("%s", uuidparse);
 		break;
+	case BTRFS_LIST_RUUID:
+		if (uuid_is_null(subv->ruuid))
+			strcpy(uuidparse, "-");
+		else
+			uuid_unparse(subv->ruuid, uuidparse);
+		width = printf("%s", uuidparse);
+		break;
 	case BTRFS_LIST_PUUID:
 		if (uuid_is_null(subv->puuid))
 			strcpy(uuidparse, "-");
@@ -1370,6 +1419,9 @@ static int print_subvolume_column(struct root_info *subv,
 		BUG_ON(!subv->full_path);
 		width = printf("%s", subv->full_path);
 		break;
+	case BTRFS_LIST_DIRID:
+		width = printf("%llu", subv->dir_id);
+		break;
 	default:
 		width = 0;
 		break;
diff --git a/btrfs-list.h b/btrfs-list.h
index d3fd9e2..27be3b1 100644
--- a/btrfs-list.h
+++ b/btrfs-list.h
@@ -53,15 +53,39 @@ struct root_info {
 	/* generation when the root is created or last updated */
 	u64 gen;
 
-	/* creation generation of this root in sec*/
+	/* updated when an inode changes */
+	u64 cgen;
+
+	/* creation generation of this root */
 	u64 ogen;
 
-	/* creation time of this root in sec*/
+	/* trans when sent. non-zero for received subvol */
+	u64 sgen;
+
+	/* trans when received. non-zero for received subvol */
+	u64 rgen;
+
+	/* time of last inode change in sec */
+	time_t ctime;
+
+	/* creation time of this root in sec */
 	time_t otime;
 
+	/* time in sec of send operation */
+	time_t stime;
+
+	/* time in sec of receive operation */
+	time_t rtime;
+
+	/* subvolume UUID */
 	u8 uuid[BTRFS_UUID_SIZE];
+
+	/* parent UUID */
 	u8 puuid[BTRFS_UUID_SIZE];
 
+	/* received UUID */
+	u8 ruuid[BTRFS_UUID_SIZE];
+
 	/* path from the subvol we live in to this root, including the
 	 * root''s name.  This is null until we do the extra lookup ioctl.
 	 */
@@ -102,14 +126,23 @@ struct btrfs_list_comparer_set {
 enum btrfs_list_column_enum {
 	BTRFS_LIST_OBJECTID,
 	BTRFS_LIST_GENERATION,
+	BTRFS_LIST_CGENERATION,
 	BTRFS_LIST_OGENERATION,
+	BTRFS_LIST_SGENERATION,
+	BTRFS_LIST_RGENERATION,
 	BTRFS_LIST_PARENT,
 	BTRFS_LIST_TOP_LEVEL,
+	BTRFS_LIST_CTIME,
 	BTRFS_LIST_OTIME,
-	BTRFS_LIST_PUUID,
+	BTRFS_LIST_STIME,
+	BTRFS_LIST_RTIME,
 	BTRFS_LIST_UUID,
+	BTRFS_LIST_PUUID,
+	BTRFS_LIST_RUUID,
+	BTRFS_LIST_DIRID,
 	BTRFS_LIST_PATH,
 	BTRFS_LIST_ALL,
+	BTRFS_LIST_MAX,
 };
 
 enum btrfs_list_filter_enum {
-- 
1.8.2.1
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wang Shilong
2013-Apr-12  08:39 UTC
Re: [PATCH v3 3/4] Btrfs-progs: add more subvol fields to btrfs-list
Hello Stefan, [snip] ..> -static int update_root(struct root_lookup *root_lookup, > - u64 root_id, u64 ref_tree, u64 root_offset, u64 flags, > - u64 dir_id, char *name, int name_len, u64 ogen, u64 gen, > - time_t ot, void *uuid, void *puuid) > +static int set_root_info(struct root_info *rinfo, u64 ref_tree, u64 root_offset, > + u64 dir_id, char *name, int name_len, > + struct btrfs_root_item *ritem, u32 ritem_len) > { > - struct root_info *ri; > + int is_v0 = (ritem_len <= sizeof(struct btrfs_root_item_v0)); > > - ri = root_tree_search(root_lookup, root_id); > - if (!ri || ri->root_id != root_id) > - return -ENOENT; > - if (name && name_len > 0) { > - if (ri->name) > - free(ri->name); > + if (root_offset) > + rinfo->root_offset = root_offset; > + if (ref_tree) > + rinfo->ref_tree = ref_tree; > + if (dir_id) > + rinfo->dir_id = dir_id; > + > + if (ritem) { > + rinfo->gen = btrfs_root_generation(ritem); > + rinfo->flags = btrfs_root_flags(ritem); > + } > > - ri->name = malloc(name_len + 1); > - if (!ri->name) { > + if (ritem && !is_v0) { > + rinfo->cgen = btrfs_root_ctransid(ritem); > + rinfo->ogen = btrfs_root_otransid(ritem); > + rinfo->sgen = btrfs_root_stransid(ritem); > + rinfo->rgen = btrfs_root_rtransid(ritem); > + rinfo->ctime = btrfs_stack_timespec_sec(&ritem->ctime); > + rinfo->otime = btrfs_stack_timespec_sec(&ritem->otime); > + rinfo->stime = btrfs_stack_timespec_sec(&ritem->stime); > + rinfo->rtime = btrfs_stack_timespec_sec(&ritem->rtime); > + memcpy(rinfo->uuid, ritem->uuid, BTRFS_UUID_SIZE); > + memcpy(rinfo->puuid, ritem->parent_uuid, BTRFS_UUID_SIZE); > + memcpy(rinfo->ruuid, ritem->received_uuid, BTRFS_UUID_SIZE);> + } else if (ritem && is_v0 && root_offset) { > + /* > + * old style (v0) root items don''t contain an otransid field. > + * But for snapshots, root_offset equals to its original > + * generation. > + */ > + rinfo->ogen = root_offset; > + }We set it rinfo->ogen = root_offset only if: 1> for root_item_v0 2> it is a snapshot. Besides for a snapshot it''s root_offset is always none zero. so we do not need (is_v0 && root_offset) both. Actually, Patch V2 doses the correct thing. Thanks, Wang> + > + if (name && name_len > 0) { > + rinfo->name = malloc(name_len + 1); > + if (!rinfo->name) { > fprintf(stderr, "memory allocation failed\n"); > - exit(1); > + return -1; > } > - strncpy(ri->name, name, name_len); > - ri->name[name_len] = 0; > + strncpy(rinfo->name, name, name_len); > + rinfo->name[name_len] = 0; > } > - if (ref_tree) > - ri->ref_tree = ref_tree; > - if (root_offset) > - ri->root_offset = root_offset; > - if (flags) > - ri->flags = flags; > - if (dir_id) > - ri->dir_id = dir_id; > - if (gen) > - ri->gen = gen; > - if (ogen) > - ri->ogen = ogen; > - if (!ri->ogen && root_offset) > - ri->ogen = root_offset; > - if (ot) > - ri->otime = ot; > - if (uuid) > - memcpy(&ri->uuid, uuid, BTRFS_UUID_SIZE); > - if (puuid) > - memcpy(&ri->puuid, puuid, BTRFS_UUID_SIZE); > > return 0; > } >[snpi] .... -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Stefan Behrens
2013-Apr-12  09:05 UTC
Re: [PATCH v3 3/4] Btrfs-progs: add more subvol fields to btrfs-list
On Fri, 12 Apr 2013 16:39:55 +0800, Wang Shilong wrote: [...]>> + if (ritem && !is_v0) { >> + rinfo->cgen = btrfs_root_ctransid(ritem); >> + rinfo->ogen = btrfs_root_otransid(ritem); >> + rinfo->sgen = btrfs_root_stransid(ritem); >> + rinfo->rgen = btrfs_root_rtransid(ritem); >> + rinfo->ctime = btrfs_stack_timespec_sec(&ritem->ctime); >> + rinfo->otime = btrfs_stack_timespec_sec(&ritem->otime); >> + rinfo->stime = btrfs_stack_timespec_sec(&ritem->stime); >> + rinfo->rtime = btrfs_stack_timespec_sec(&ritem->rtime); >> + memcpy(rinfo->uuid, ritem->uuid, BTRFS_UUID_SIZE); >> + memcpy(rinfo->puuid, ritem->parent_uuid, BTRFS_UUID_SIZE); >> + memcpy(rinfo->ruuid, ritem->received_uuid, BTRFS_UUID_SIZE); > >> + } else if (ritem && is_v0 && root_offset) { >> + /* >> + * old style (v0) root items don''t contain an otransid field. >> + * But for snapshots, root_offset equals to its original >> + * generation. >> + */ >> + rinfo->ogen = root_offset; >> + } > > > We set it rinfo->ogen = root_offset only if: > 1> for root_item_v0 > 2> it is a snapshot. > > Besides for a snapshot it''s root_offset is always none zero. > so we do not need (is_v0 && root_offset) both. > Actually, Patch V2 doses the correct thing. >Patch V2 was accessing the otransid field also for root_item_v0 which does not have this field. This was not correct. That root_offset != 0 thing is because add_root() and therefore set_root_info() is called twice, once for BTRFS_ROOT_BACKREF_KEY and once for BTRFS_ROOT_ITEM_KEY. In both cases, the arguments to add_root() are only partially supplied and those values that are not available are set to zero. The old code everywhere had this ... != 0 else don''t set the value, to handle this double call to add_root(), and I replaced most of it by passing a root_item pointer of NULL in the BACKREF case (where the old code just set gen=0, time=0, uuid=0 ...), and reading the values of the root_item down in set_root_info() in the ROOT_ITEM case. Only root_offset remains which is set to 0 in the BACKREF case and to the key''s offset value in the ROOT_ITEM case. One could now argue that in the first case where root_offset is not valid, ritem is set to NULL and therefore the equation (ritem && is_v0 && root_offset) is equal to (ritem && is_v0), but IMHO a deep subfunction should not make use of too much information that is part of the functions that call the subfunction. Summary: Patch V3 does the correct thing. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Wang Shilong
2013-Apr-12  09:33 UTC
Re: [PATCH v3 3/4] Btrfs-progs: add more subvol fields to btrfs-list
Hello,> On Fri, 12 Apr 2013 16:39:55 +0800, Wang Shilong wrote: > [...] >>> + if (ritem && !is_v0) { >>> + rinfo->cgen = btrfs_root_ctransid(ritem); >>> + rinfo->ogen = btrfs_root_otransid(ritem); >>> + rinfo->sgen = btrfs_root_stransid(ritem); >>> + rinfo->rgen = btrfs_root_rtransid(ritem); >>> + rinfo->ctime = btrfs_stack_timespec_sec(&ritem->ctime); >>> + rinfo->otime = btrfs_stack_timespec_sec(&ritem->otime); >>> + rinfo->stime = btrfs_stack_timespec_sec(&ritem->stime); >>> + rinfo->rtime = btrfs_stack_timespec_sec(&ritem->rtime); >>> + memcpy(rinfo->uuid, ritem->uuid, BTRFS_UUID_SIZE); >>> + memcpy(rinfo->puuid, ritem->parent_uuid, BTRFS_UUID_SIZE); >>> + memcpy(rinfo->ruuid, ritem->received_uuid, BTRFS_UUID_SIZE); >>> + } else if (ritem && is_v0 && root_offset) { >>> + /* >>> + * old style (v0) root items don''t contain an otransid field. >>> + * But for snapshots, root_offset equals to its original >>> + * generation. >>> + */ >>> + rinfo->ogen = root_offset; >>> + } >> >> We set it rinfo->ogen = root_offset only if: >> 1> for root_item_v0 >> 2> it is a snapshot. >> >> Besides for a snapshot it''s root_offset is always none zero. >> so we do not need (is_v0 && root_offset) both. >> Actually, Patch V2 doses the correct thing. >> > > Patch V2 was accessing the otransid field also for root_item_v0 which > does not have this field. This was not correct. > > That root_offset != 0 thing is because add_root() and therefore > set_root_info() is called twice, once for BTRFS_ROOT_BACKREF_KEY and > once for BTRFS_ROOT_ITEM_KEY. In both cases, the arguments to add_root() > are only partially supplied and those values that are not available are > set to zero. The old code everywhere had this ... != 0 else don''t set > the value, to handle this double call to add_root(), and I replaced most > of it by passing a root_item pointer of NULL in the BACKREF case (where > the old code just set gen=0, time=0, uuid=0 ...), and reading the values > of the root_item down in set_root_info() in the ROOT_ITEM case. Only > root_offset remains which is set to 0 in the BACKREF case and to the > key''s offset value in the ROOT_ITEM case. One could now argue that in > the first case where root_offset is not valid, ritem is set to NULL and > therefore the equation (ritem && is_v0 && root_offset) is equal to > (ritem && is_v0), but IMHO a deep subfunction should not make use of too > much information that is part of the functions that call the subfunction. > > Summary: Patch V3 does the correct thing. >After reading carefully, i agree patch V3 is correct~~, thanks for so detailed illustration^_^ Thanks, Wang> -- > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > >-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html