The parent UUID, all generation values and all timestamps that
are available in the root_item are added.

Signed-off-by: Stefan Behrens <sbehr...@giantdisaster.de>
---
 btrfs-list.c | 273 +++++++++++++++++++++++++++++++++++------------------------
 btrfs-list.h |  39 ++++++++-
 2 files changed, 197 insertions(+), 115 deletions(-)

diff --git a/btrfs-list.c b/btrfs-list.c
index 70da9a3..2d53290 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,70 @@ 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);
+       }
+
+       /* TODO: this is copied from the old code, what is it good for? */
+       if ((!ritem || !btrfs_root_otransid(ritem)) && root_offset)
+               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 +505,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 +1022,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 +1074,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 +1341,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 +1375,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 +1398,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 +1416,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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to