From 0f67331582db8b0e7d99a786a1a4cd21f9fd769cc4c4be823dabd6126e5635f2 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Thu, 28 Jul 2011 17:55:26 +0000 Subject: [PATCH] - add option -p to print parent subvolume - add subvolume 'get-default' subsubcommand OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=106 --- ...int-parent-ID-in-btrfs-suvolume-list.patch | 158 +++++++++++++ ...age-entries-for-btrfs-subvolume-list.patch | 54 +++++ 0500-btrfs-progs-get-default-subvolume.patch | 216 ++++++++++++++++++ btrfsprogs.changes | 6 + btrfsprogs.spec | 9 + 5 files changed, 443 insertions(+) create mode 100644 0130-print-parent-ID-in-btrfs-suvolume-list.patch create mode 100644 0131-update-manpage-entries-for-btrfs-subvolume-list.patch create mode 100644 0500-btrfs-progs-get-default-subvolume.patch diff --git a/0130-print-parent-ID-in-btrfs-suvolume-list.patch b/0130-print-parent-ID-in-btrfs-suvolume-list.patch new file mode 100644 index 0000000..882783d --- /dev/null +++ b/0130-print-parent-ID-in-btrfs-suvolume-list.patch @@ -0,0 +1,158 @@ +From a763e90c48053b60e78a455252c1a5735b6d19d5 Mon Sep 17 00:00:00 2001 +From: Andreas Philipp +Date: Sun, 3 Jul 2011 00:26:39 +0200 +Subject: [PATCH 48/50] print parent ID in btrfs suvolume list + +There was some discussion on "where" subvolumes live in. Why do we not +simply print the parent ID for each subvolume in btrfs subvolume list? +This patch adds this functionality when called with parameter "-p". + +Signed-off-by: Andreas Philipp +--- + btrfs-list.c | 24 ++++++++++++++++++------ + btrfs.c | 6 ++++-- + btrfs_cmds.c | 22 ++++++++++++++++++++-- + btrfs_cmds.h | 2 +- + 4 files changed, 43 insertions(+), 11 deletions(-) + +diff --git a/btrfs-list.c b/btrfs-list.c +index e61c14d..2a1f58e 100644 +--- a/btrfs-list.c ++++ b/btrfs-list.c +@@ -200,9 +200,10 @@ static int add_root(struct root_lookup *root_lookup, + * This can't be called until all the root_info->path fields are filled + * in by lookup_ino_path + */ +-static int resolve_root(struct root_lookup *rl, struct root_info *ri) ++static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_parent) + { + u64 top_id; ++ u64 parent_id = 0; + char *full_path = NULL; + int len = 0; + struct root_info *found; +@@ -233,6 +234,11 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri) + } + + next = found->ref_tree; ++ /* record the first parent */ ++ if ( parent_id == 0 ) { ++ parent_id = next; ++ } ++ + /* if the ref_tree refers to ourselves, we're at the top */ + if (next == found->root_id) { + top_id = next; +@@ -249,9 +255,15 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri) + break; + } + } +- printf("ID %llu top level %llu path %s\n", +- (unsigned long long)ri->root_id, (unsigned long long)top_id, +- full_path); ++ if (print_parent) { ++ printf("ID %llu parent %llu top level %llu path %s\n", ++ (unsigned long long)ri->root_id, (unsigned long long)parent_id, (unsigned long long)top_id, ++ full_path); ++ } else { ++ printf("ID %llu top level %llu path %s\n", ++ (unsigned long long)ri->root_id, (unsigned long long)top_id, ++ full_path); ++ } + free(full_path); + return 0; + } +@@ -549,7 +561,7 @@ build: + return full; + } + +-int list_subvols(int fd) ++int list_subvols(int fd, int print_parent) + { + struct root_lookup root_lookup; + struct rb_node *n; +@@ -669,7 +681,7 @@ int list_subvols(int fd) + while (n) { + struct root_info *entry; + entry = rb_entry(n, struct root_info, rb_node); +- resolve_root(&root_lookup, entry); ++ resolve_root(&root_lookup, entry, print_parent); + n = rb_prev(n); + } + +diff --git a/btrfs.c b/btrfs.c +index 8ad1e4e..67d6f6f 100644 +--- a/btrfs.c ++++ b/btrfs.c +@@ -66,9 +66,11 @@ static struct Command commands[] = { + "not passed).", + NULL + }, +- { do_subvol_list, 1, "subvolume list", "\n" ++ { do_subvol_list, -1, "subvolume list", "[-p] \n" + "List the snapshot/subvolume of a filesystem.", +- NULL ++ "[-p] \n" ++ "List the snapshot/subvolume of a filesystem.\n" ++ "-p print parent ID" + }, + { do_set_default_subvol, 2, + "subvolume set-default", " \n" +diff --git a/btrfs_cmds.c b/btrfs_cmds.c +index 1d18c59..0612f34 100644 +--- a/btrfs_cmds.c ++++ b/btrfs_cmds.c +@@ -303,9 +303,27 @@ int do_subvol_list(int argc, char **argv) + { + int fd; + int ret; ++ int print_parent = 0; + char *subvol; ++ int optind = 1; + +- subvol = argv[1]; ++ while(1) { ++ int c = getopt(argc, argv, "p"); ++ if (c < 0) break; ++ switch(c) { ++ case 'p': ++ print_parent = 1; ++ optind++; ++ break; ++ } ++ } ++ ++ if (argc - optind != 1) { ++ fprintf(stderr, "ERROR: invalid arguments for subvolume list\n"); ++ return 1; ++ } ++ ++ subvol = argv[optind]; + + ret = test_issubvolume(subvol); + if (ret < 0) { +@@ -322,7 +340,7 @@ int do_subvol_list(int argc, char **argv) + fprintf(stderr, "ERROR: can't access '%s'\n", subvol); + return 12; + } +- ret = list_subvols(fd); ++ ret = list_subvols(fd, print_parent); + if (ret) + return 19; + return 0; +diff --git a/btrfs_cmds.h b/btrfs_cmds.h +index 61456fa..83faa5b 100644 +--- a/btrfs_cmds.h ++++ b/btrfs_cmds.h +@@ -34,7 +34,7 @@ int do_scan(int nargs, char **argv); + int do_resize(int nargs, char **argv); + int do_subvol_list(int nargs, char **argv); + int do_set_default_subvol(int nargs, char **argv); +-int list_subvols(int fd); ++int list_subvols(int fd, int print_parent); + int do_df_filesystem(int nargs, char **argv); + int find_updated_files(int fd, u64 root_id, u64 oldest_gen); + int do_find_newer(int argc, char **argv); +-- +1.7.6.233.gd79bc + diff --git a/0131-update-manpage-entries-for-btrfs-subvolume-list.patch b/0131-update-manpage-entries-for-btrfs-subvolume-list.patch new file mode 100644 index 0000000..a0144df --- /dev/null +++ b/0131-update-manpage-entries-for-btrfs-subvolume-list.patch @@ -0,0 +1,54 @@ +From 4280e502029f2c37dff8ed74c48e1c66c60c50d3 Mon Sep 17 00:00:00 2001 +From: Andreas Philipp +Date: Sun, 3 Jul 2011 00:26:40 +0200 +Subject: [PATCH 49/50] update manpage entries for btrfs subvolume list + +Update the manpage entries for the btrfs subvolume list command to +reflect the newly created additional option '-p'. + +Signed-off-by: Andreas Philipp +--- + man/btrfs.8.in | 19 +++++++++++-------- + 1 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/man/btrfs.8.in b/man/btrfs.8.in +index 91663e5..84a60cd 100644 +--- a/man/btrfs.8.in ++++ b/man/btrfs.8.in +@@ -11,7 +11,7 @@ btrfs \- control a btrfs filesystem + .PP + \fBbtrfs\fP \fBsubvolume create\fP\fI [/]\fP + .PP +-\fBbtrfs\fP \fBsubvolume list\fP\fI \fP ++\fBbtrfs\fP \fBsubvolume list\fP\fI [-p] \fP + .PP + \fBbtrfs\fP \fBsubvolume set-default\fP\fI \fP + .PP +@@ -107,14 +107,17 @@ Create a subvolume in \fI\fR (or in the current directory if + \fI\fR is omitted). + .TP + +-\fBsubvolume list\fR\fI \fR ++\fBsubvolume list\fR\fI [-p] \fR + List the subvolumes present in the filesystem \fI\fR. For every +-subvolume is showed the subvolume ID (second column), +-the ID of the \fItop level\fR +-subvolume (fifth column), and the path (seventh column) relative to the +-\fItop level\fR subvolume. +-These may be used by the \fBsubvolume set-default\fR command, or at +-mount time via the \fIsubvol=\fR option. ++subvolume the following information is shown by default. ++ID top level path ++where path is the relative path of the subvolume to the \fItop level\fR ++subvolume. ++The subvolume's ID may be used by the \fBsubvolume set-default\fR command, or ++at mount time via the \fIsubvol=\fR option. ++If \fI-p\fR is given, then \fIparent \fR is added to the output between ID ++and top level. The parent's ID may be used at mount time via the ++\fIsubvolrootid=\fR option. + .TP + + \fBsubvolume set-default\fR\fI \fR +-- +1.7.6.233.gd79bc + diff --git a/0500-btrfs-progs-get-default-subvolume.patch b/0500-btrfs-progs-get-default-subvolume.patch new file mode 100644 index 0000000..8dd7638 --- /dev/null +++ b/0500-btrfs-progs-get-default-subvolume.patch @@ -0,0 +1,216 @@ +Date: Tue, 12 Jul 2011 10:48:37 +0800 +From: "Zhong, Xin" +Subject: [PATCH V3] Btrfs-progs: add "btrfs subvolume get-default" subcommand + +Add subcommand to get the default subvolume of btrfs filesystem + +Reviewed-by: Andreas Philipp +Reviewed-by: Goffredo Baroncelli +Reported-by: Yang, Yi +Signed-off-by: Zhong, Xin +--- + btrfs-list.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + btrfs.c | 3 ++ + btrfs_cmds.c | 31 ++++++++++++++++++++++++++++- + btrfs_cmds.h | 3 +- + man/btrfs.8.in | 7 ++++++ + 5 files changed, 98 insertions(+), 4 deletions(-) + +diff --git a/btrfs-list.c b/btrfs-list.c +index 07b179a..016d09c 100644 +--- a/btrfs-list.c ++++ b/btrfs-list.c +@@ -560,7 +560,7 @@ build: + return full; + } + +-int list_subvols(int fd, int print_parent) ++int list_subvols(int fd, int print_parent, int get_default) + { + struct root_lookup root_lookup; + struct rb_node *n; +@@ -569,10 +569,12 @@ int list_subvols(int fd, int print_parent) + struct btrfs_ioctl_search_key *sk = &args.key; + struct btrfs_ioctl_search_header *sh; + struct btrfs_root_ref *ref; ++ struct btrfs_dir_item *di; + unsigned long off = 0; + int name_len; + char *name; + u64 dir_id; ++ u64 subvol_id = 0; + int i; + int e; + +@@ -672,6 +674,52 @@ int list_subvols(int fd, int print_parent) + n = rb_next(n); + } + ++ memset(&args, 0, sizeof(args)); ++ ++ /* search in the tree of tree roots */ ++ sk->tree_id = BTRFS_ROOT_TREE_OBJECTID; ++ ++ /* search dir item */ ++ sk->max_type = BTRFS_DIR_ITEM_KEY; ++ sk->min_type = BTRFS_DIR_ITEM_KEY; ++ ++ sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID; ++ sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID; ++ sk->max_offset = (u64)-1; ++ sk->max_transid = (u64)-1; ++ ++ /* just a big number, doesn't matter much */ ++ sk->nr_items = 4096; ++ ++ /* try to get the objectid of default subvolume */ ++ if (get_default) { ++ ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: can't perform the search\n"); ++ return ret; ++ } ++ ++ off = 0; ++ /* go through each item to find dir item named "default" */ ++ for (i = 0; i < sk->nr_items; i++) { ++ sh = (struct btrfs_ioctl_search_header *)(args.buf + ++ off); ++ off += sizeof(*sh); ++ if (sh->type == BTRFS_DIR_ITEM_KEY) { ++ di = (struct btrfs_dir_item *)(args.buf + off); ++ name_len = le16_to_cpu(di->name_len); ++ name = (char *)di + sizeof(struct btrfs_dir_item); ++ if (!strncmp("default", name, name_len)) { ++ subvol_id = btrfs_disk_key_objectid( ++ &di->location); ++ break; ++ } ++ } ++ ++ off += sh->len; ++ } ++ } ++ + /* now that we have all the subvol-relative paths filled in, + * we have to string the subvols together so that we can get + * a path all the way back to the FS root +@@ -680,7 +728,13 @@ int list_subvols(int fd, int print_parent) + while (n) { + struct root_info *entry; + entry = rb_entry(n, struct root_info, rb_node); +- resolve_root(&root_lookup, entry, print_parent); ++ if (!get_default) ++ resolve_root(&root_lookup, entry, print_parent); ++ /* we only want the default subvolume */ ++ else if (subvol_id == entry->root_id) ++ resolve_root(&root_lookup, entry, print_parent); ++ else if (subvol_id == 0) ++ break; + n = rb_prev(n); + } + +diff --git a/btrfs.c b/btrfs.c +index 67d6f6f..1af8360 100644 +--- a/btrfs.c ++++ b/btrfs.c +@@ -94,6 +94,9 @@ static struct Command commands[] = { + "-l len defragment only up to len bytes\n" + "-t size minimal size of file to be considered for defragmenting\n" + }, ++ { do_get_default_subvol, 1, "subvolume get-default", "\n" ++ "Get the default subvolume of a filesystem." ++ }, + { do_fssync, 1, + "filesystem sync", "\n" + "Force a sync on the filesystem .", +diff --git a/btrfs_cmds.c b/btrfs_cmds.c +index 0612f34..e151c25 100644 +--- a/btrfs_cmds.c ++++ b/btrfs_cmds.c +@@ -340,7 +340,7 @@ int do_subvol_list(int argc, char **argv) + fprintf(stderr, "ERROR: can't access '%s'\n", subvol); + return 12; + } +- ret = list_subvols(fd, print_parent); ++ ret = list_subvols(fd, print_parent, 0); + if (ret) + return 19; + return 0; +@@ -1443,6 +1443,35 @@ int do_change_label(int nargs, char **argv) + } + + ++int do_get_default_subvol(int nargs, char **argv) ++{ ++ int fd; ++ int ret; ++ char *subvol; ++ ++ subvol = argv[1]; ++ ++ ret = test_issubvolume(subvol); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: error accessing '%s'\n", subvol); ++ return 12; ++ } ++ if (!ret) { ++ fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol); ++ return 13; ++ } ++ ++ fd = open_file_or_dir(subvol); ++ if (fd < 0) { ++ fprintf(stderr, "ERROR: can't access '%s'\n", subvol); ++ return 12; ++ } ++ ret = list_subvols(fd, 0, 1); ++ if (ret) ++ return 19; ++ return 0; ++} ++ + int do_df_filesystem(int nargs, char **argv) + { + struct btrfs_ioctl_space_args *sargs; +diff --git a/btrfs_cmds.h b/btrfs_cmds.h +index 83faa5b..d983588 100644 +--- a/btrfs_cmds.h ++++ b/btrfs_cmds.h +@@ -34,7 +34,8 @@ int do_scan(int nargs, char **argv); + int do_resize(int nargs, char **argv); + int do_subvol_list(int nargs, char **argv); + int do_set_default_subvol(int nargs, char **argv); +-int list_subvols(int fd, int print_parent); ++int do_get_default_subvol(int nargs, char **argv); ++int list_subvols(int fd, int print_parent, int get_default); + int do_df_filesystem(int nargs, char **argv); + int find_updated_files(int fd, u64 root_id, u64 oldest_gen); + int do_find_newer(int argc, char **argv); +diff --git a/man/btrfs.8.in b/man/btrfs.8.in +index 84a60cd..61ce0df 100644 +--- a/man/btrfs.8.in ++++ b/man/btrfs.8.in +@@ -15,6 +15,8 @@ btrfs \- control a btrfs filesystem + .PP + \fBbtrfs\fP \fBsubvolume set-default\fP\fI \fP + .PP ++\fBbtrfs\fP \fBsubvolume get-default\fP\fI \fP ++.PP + \fBbtrfs\fP \fBfilesystem sync\fP\fI \fP + .PP + \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-][gkm]|max \fP +@@ -126,6 +128,11 @@ Set the subvolume of the filesystem \fI\fR which is mounted as + is returned by the \fBsubvolume list\fR command. + .TP + ++\fBsubvolume get-default\fR\fI \fR ++Get the default subvolume of the filesystem \fI\fR. The output format ++is similar to \fBsubvolume list\fR command. ++.TP ++ + \fBfilesystem defragment\fP -c[zlib|lzo] [-l \fIlen\fR] [-s \fIstart\fR] [-t \fIsize\fR] -[vf] <\fIfile\fR>|<\fIdir\fR> [<\fIfile\fR>|<\fIdir\fR>...] + + Defragment file data and/or directory metadata. To defragment all files in a +-- +1.7.0.4 diff --git a/btrfsprogs.changes b/btrfsprogs.changes index 97716e8..c655cda 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Jul 28 19:10:08 CEST 2011 - dsterba@suse.cz + +- add option -p to print parent subvolume +- add subvolume 'get-default' subsubcommand + ------------------------------------------------------------------- Wed Jul 20 19:12:46 CEST 2011 - dsterba@suse.cz diff --git a/btrfsprogs.spec b/btrfsprogs.spec index 5d0392d..d81b27d 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -71,6 +71,8 @@ Patch39: 0123-mkfs.btrfs-fix-memory-leak-caused-by-scandir-calls.patch Patch40: 0124-mkfs.btrfs-fix-error-text-in-r-mode.patch Patch41: 0125-btrfs-map-logical-segfaults-when-no-output-file-is-g.patch Patch42: 0127-mkfs.btrfs-Fix-compilation-errors-with-gcc-4.6.patch +Patch43: 0130-print-parent-ID-in-btrfs-suvolume-list.patch +Patch44: 0131-update-manpage-entries-for-btrfs-subvolume-list.patch # git: scrub, fixes, improvements Patch50: 0216-commands-added.patch @@ -83,6 +85,9 @@ Patch56: 0231-btrfs-progs-Improvement-for-making-btrfs-image-from-.patch Patch57: ignore-deleted-loopmounts.diff +# other patches not in git trees +Patch500: 0500-btrfs-progs-get-default-subvolume.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel # for /bin/true @@ -135,6 +140,8 @@ Utilities needed to create and maintain btrfs file systems under Linux. %patch40 -p1 %patch41 -p1 %patch42 -p1 +%patch43 -p1 +%patch44 -p1 %patch50 -p1 %patch51 -p1 %patch52 -p1 @@ -144,6 +151,8 @@ Utilities needed to create and maintain btrfs file systems under Linux. %patch56 -p1 %patch57 -p1 +%patch500 -p1 + %build make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert