2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
21 #include <sys/ioctl.h>
27 #include <uuid/uuid.h>
29 #include "kerncompat.h"
36 #include "btrfs-list.h"
39 static const char * const subvolume_cmd_group_usage[] = {
40 "btrfs subvolume <command> <args>",
45 * test if path is a directory
46 * this function return
47 * 0-> path exists but it is not a directory
48 * 1-> path exists and it is a directory
49 * -1 -> path is unaccessible
51 static int test_isdir(char *path)
56 res = stat(path, &st);
60 return S_ISDIR(st.st_mode);
63 static const char * const cmd_subvol_create_usage[] = {
64 "btrfs subvolume create [-i <qgroupid>] [<dest>/]<name>",
66 "Create a subvolume <name> in <dest>. If <dest> is not given",
67 "subvolume <name> will be created in the current directory.",
69 "-i <qgroupid> add the newly created subvolume to a qgroup. This",
70 " option can be given multiple times.",
74 static int cmd_subvol_create(int argc, char **argv)
83 struct btrfs_qgroup_inherit *inherit = NULL;
84 DIR *dirstream = NULL;
88 int c = getopt(argc, argv, "c:i:");
94 res = qgroup_inherit_add_copy(&inherit, optarg, 0);
101 res = qgroup_inherit_add_group(&inherit, optarg);
108 usage(cmd_subvol_create_usage);
112 if (check_argc_exact(argc - optind, 1))
113 usage(cmd_subvol_create_usage);
117 retval = 1; /* failure */
118 res = test_isdir(dst);
120 fprintf(stderr, "ERROR: '%s' exists\n", dst);
124 dupname = strdup(dst);
125 newname = basename(dupname);
126 dupdir = strdup(dst);
127 dstdir = dirname(dupdir);
129 if (!strcmp(newname, ".") || !strcmp(newname, "..") ||
130 strchr(newname, '/') ){
131 fprintf(stderr, "ERROR: uncorrect subvolume name ('%s')\n",
136 len = strlen(newname);
137 if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
138 fprintf(stderr, "ERROR: subvolume name too long ('%s)\n",
143 fddst = open_file_or_dir(dstdir, &dirstream);
145 fprintf(stderr, "ERROR: can't access '%s'\n", dstdir);
149 printf("Create subvolume '%s/%s'\n", dstdir, newname);
151 struct btrfs_ioctl_vol_args_v2 args;
153 memset(&args, 0, sizeof(args));
154 strncpy_null(args.name, newname);
155 args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
156 args.size = qgroup_inherit_size(inherit);
157 args.qgroup_inherit = inherit;
159 res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE_V2, &args);
161 struct btrfs_ioctl_vol_args args;
163 memset(&args, 0, sizeof(args));
164 strncpy_null(args.name, newname);
166 res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
170 fprintf(stderr, "ERROR: cannot create subvolume - %s\n",
175 retval = 0; /* success */
177 close_file_or_dir(fddst, dirstream);
186 * test if path is a subvolume:
187 * this function return
188 * 0-> path exists but it is not a subvolume
189 * 1-> path exists and it is a subvolume
190 * -1 -> path is unaccessible
192 int test_issubvolume(char *path)
197 res = stat(path, &st);
201 return (st.st_ino == 256) && S_ISDIR(st.st_mode);
204 static int wait_for_commit(int fd)
208 ret = ioctl(fd, BTRFS_IOC_START_SYNC, NULL);
211 return ioctl(fd, BTRFS_IOC_WAIT_SYNC, NULL);
214 static const char * const cmd_subvol_delete_usage[] = {
215 "btrfs subvolume delete [options] <subvolume> [<subvolume>...]",
216 "Delete subvolume(s)",
217 "Delete subvolumes from the filesystem. The corresponding directory",
218 "is removed instantly but the data blocks are removed later.",
219 "The deletion does not involve full commit by default due to",
220 "performance reasons (as a consequence, the subvolume may appear again",
221 "after a crash). Use one of the --commit options to wait until the",
222 "operation is safely stored on the media.",
224 "-c|--commit-after wait for transaction commit at the end of the operation",
225 "-C|--commit-each wait for transaction commit after deleting each subvolume",
229 static int cmd_subvol_delete(int argc, char **argv)
231 int res, len, e, ret = 0;
234 struct btrfs_ioctl_vol_args args;
235 char *dname, *vname, *cpath;
236 char *dupdname = NULL;
237 char *dupvname = NULL;
239 DIR *dirstream = NULL;
241 struct option long_options[] = {
242 {"commit-after", no_argument, NULL, 'c'}, /* sync mode 1 */
243 {"commit-each", no_argument, NULL, 'C'}, /* sync mode 2 */
251 c = getopt_long(argc, argv, "cC", long_options, NULL);
263 usage(cmd_subvol_delete_usage);
267 if (check_argc_min(argc - optind, 1))
268 usage(cmd_subvol_delete_usage);
270 printf("Transaction commit: %s\n",
271 !sync_mode ? "none (default)" :
272 sync_mode == 1 ? "at the end" : "after each");
279 res = test_issubvolume(path);
281 fprintf(stderr, "ERROR: error accessing '%s'\n", path);
286 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", path);
291 cpath = realpath(path, NULL);
294 fprintf(stderr, "ERROR: finding real path for '%s': %s\n",
295 path, strerror(errno));
298 dupdname = strdup(cpath);
299 dname = dirname(dupdname);
300 dupvname = strdup(cpath);
301 vname = basename(dupvname);
304 if (!strcmp(vname, ".") || !strcmp(vname, "..") ||
305 strchr(vname, '/')) {
306 fprintf(stderr, "ERROR: incorrect subvolume name ('%s')\n",
313 if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
314 fprintf(stderr, "ERROR: snapshot name too long ('%s)\n",
320 fd = open_file_or_dir(dname, &dirstream);
322 fprintf(stderr, "ERROR: can't access '%s'\n", dname);
327 printf("Delete subvolume '%s/%s'\n", dname, vname);
328 strncpy_null(args.name, vname);
329 res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
333 fprintf( stderr, "ERROR: cannot delete '%s/%s' - %s\n",
334 dname, vname, strerror(e));
339 if (sync_mode == 1) {
340 res = wait_for_commit(fd);
343 "ERROR: unable to wait for commit after '%s': %s\n",
344 path, strerror(errno));
356 close_file_or_dir(fd, dirstream);
357 /* avoid double free */
363 if (sync_mode == 2 && fd != -1) {
364 res = wait_for_commit(fd);
367 "ERROR: unable to do final sync: %s\n",
372 close_file_or_dir(fd, dirstream);
379 * - uppercase for filters and sort options
380 * - lowercase for enabling specific items in the output
382 static const char * const cmd_subvol_list_usage[] = {
383 "btrfs subvolume list [options] [-G [+|-]value] [-C [+|-]value] "
384 "[--sort=gen,ogen,rootid,path] <path>",
385 "List subvolumes (and snapshots)",
387 "-p print parent ID",
388 "-a print all the subvolumes in the filesystem and",
389 " distinguish absolute and relative path with respect",
390 " to the given <path>",
391 "-c print the ogeneration of the subvolume",
392 "-g print the generation of the subvolume",
393 "-o print only subvolumes bellow specified path",
394 "-u print the uuid of subvolumes (and snapshots)",
395 "-q print the parent uuid of the snapshots",
396 "-t print the result as a table",
397 "-s list snapshots only in the filesystem",
398 "-r list readonly subvolumes (including snapshots)",
399 "-d list deleted subvolumes that are not yet cleaned",
401 " filter the subvolumes by generation",
402 " (+value: >= value; -value: <= value; value: = value)",
404 " filter the subvolumes by ogeneration",
405 " (+value: >= value; -value: <= value; value: = value)",
406 "--sort=gen,ogen,rootid,path",
407 " list the subvolume in order of gen, ogen, rootid or path",
408 " you also can add '+' or '-' in front of each items.",
409 " (+:ascending, -:descending, ascending default)",
413 static int cmd_subvol_list(int argc, char **argv)
415 struct btrfs_list_filter_set *filter_set;
416 struct btrfs_list_comparer_set *comparer_set;
420 int ret = -1, uerr = 0;
423 int is_tab_result = 0;
425 int is_only_in_path = 0;
426 struct option long_options[] = {
427 {"sort", 1, NULL, 'S'},
430 DIR *dirstream = NULL;
432 filter_set = btrfs_list_alloc_filter_set();
433 comparer_set = btrfs_list_alloc_comparer_set();
437 c = getopt_long(argc, argv,
438 "acdgopqsurG:C:t", long_options, NULL);
444 btrfs_list_setup_print_column(BTRFS_LIST_PARENT);
450 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
453 btrfs_list_setup_filter(&filter_set,
454 BTRFS_LIST_FILTER_DELETED,
458 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
467 btrfs_list_setup_filter(&filter_set,
468 BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
470 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
471 btrfs_list_setup_print_column(BTRFS_LIST_OTIME);
474 btrfs_list_setup_print_column(BTRFS_LIST_UUID);
477 btrfs_list_setup_print_column(BTRFS_LIST_PUUID);
480 flags |= BTRFS_ROOT_SUBVOL_RDONLY;
483 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
484 ret = btrfs_list_parse_filter_string(optarg,
486 BTRFS_LIST_FILTER_GEN);
494 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
495 ret = btrfs_list_parse_filter_string(optarg,
497 BTRFS_LIST_FILTER_CGEN);
504 ret = btrfs_list_parse_sort_string(optarg,
519 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
522 if (check_argc_exact(argc - optind, 1)) {
527 subvol = argv[optind];
528 fd = open_file_or_dir(subvol, &dirstream);
531 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
535 ret = btrfs_list_get_path_rootid(fd, &top_id);
537 fprintf(stderr, "ERROR: can't get rootid for '%s'\n", subvol);
542 btrfs_list_setup_filter(&filter_set,
543 BTRFS_LIST_FILTER_FULL_PATH,
545 else if (is_only_in_path)
546 btrfs_list_setup_filter(&filter_set,
547 BTRFS_LIST_FILTER_TOPID_EQUAL,
550 /* by default we shall print the following columns*/
551 btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
552 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
553 btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
554 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
557 ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
558 BTRFS_LIST_LAYOUT_TABLE,
559 !is_list_all && !is_only_in_path, NULL);
561 ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
562 BTRFS_LIST_LAYOUT_DEFAULT,
563 !is_list_all && !is_only_in_path, NULL);
566 close_file_or_dir(fd, dirstream);
568 btrfs_list_free_filter_set(filter_set);
570 btrfs_list_free_comparer_set(comparer_set);
572 usage(cmd_subvol_list_usage);
576 static const char * const cmd_snapshot_usage[] = {
577 "btrfs subvolume snapshot [-r] <source> <dest>|[<dest>/]<name>",
578 "btrfs subvolume snapshot [-r] [-i <qgroupid>] <source> <dest>|[<dest>/]<name>",
579 "Create a snapshot of the subvolume",
580 "Create a writable/readonly snapshot of the subvolume <source> with",
581 "the name <name> in the <dest> directory. If only <dest> is given,",
582 "the subvolume will be named the basename of <source>.",
584 "-r create a readonly snapshot",
585 "-i <qgroupid> add the newly created snapshot to a qgroup. This",
586 " option can be given multiple times.",
590 static int cmd_snapshot(int argc, char **argv)
594 int fd = -1, fddst = -1;
595 int len, readonly = 0;
596 char *dupname = NULL;
600 struct btrfs_ioctl_vol_args_v2 args;
601 struct btrfs_qgroup_inherit *inherit = NULL;
602 DIR *dirstream1 = NULL, *dirstream2 = NULL;
605 memset(&args, 0, sizeof(args));
607 int c = getopt(argc, argv, "c:i:r");
613 res = qgroup_inherit_add_copy(&inherit, optarg, 0);
620 res = qgroup_inherit_add_group(&inherit, optarg);
630 res = qgroup_inherit_add_copy(&inherit, optarg, 1);
637 usage(cmd_snapshot_usage);
641 if (check_argc_exact(argc - optind, 2))
642 usage(cmd_snapshot_usage);
644 subvol = argv[optind];
645 dst = argv[optind + 1];
647 retval = 1; /* failure */
648 res = test_issubvolume(subvol);
650 fprintf(stderr, "ERROR: error accessing '%s'\n", subvol);
654 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol);
658 res = test_isdir(dst);
660 fprintf(stderr, "ERROR: '%s' exists and it is not a directory\n", dst);
665 dupname = strdup(subvol);
666 newname = basename(dupname);
669 dupname = strdup(dst);
670 newname = basename(dupname);
671 dupdir = strdup(dst);
672 dstdir = dirname(dupdir);
675 if (!strcmp(newname, ".") || !strcmp(newname, "..") ||
676 strchr(newname, '/') ){
677 fprintf(stderr, "ERROR: incorrect snapshot name ('%s')\n",
682 len = strlen(newname);
683 if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
684 fprintf(stderr, "ERROR: snapshot name too long ('%s)\n",
689 fddst = open_file_or_dir(dstdir, &dirstream1);
691 fprintf(stderr, "ERROR: can't access '%s'\n", dstdir);
695 fd = open_file_or_dir(subvol, &dirstream2);
697 fprintf(stderr, "ERROR: can't access '%s'\n", dstdir);
702 args.flags |= BTRFS_SUBVOL_RDONLY;
703 printf("Create a readonly snapshot of '%s' in '%s/%s'\n",
704 subvol, dstdir, newname);
706 printf("Create a snapshot of '%s' in '%s/%s'\n",
707 subvol, dstdir, newname);
712 args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
713 args.size = qgroup_inherit_size(inherit);
714 args.qgroup_inherit = inherit;
716 strncpy_null(args.name, newname);
718 res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
721 fprintf( stderr, "ERROR: cannot snapshot '%s' - %s\n",
722 subvol, strerror(errno));
726 retval = 0; /* success */
729 close_file_or_dir(fddst, dirstream1);
730 close_file_or_dir(fd, dirstream2);
738 static const char * const cmd_subvol_get_default_usage[] = {
739 "btrfs subvolume get-default <path>",
740 "Get the default subvolume of a filesystem",
744 static int cmd_subvol_get_default(int argc, char **argv)
749 struct btrfs_list_filter_set *filter_set;
751 DIR *dirstream = NULL;
753 if (check_argc_exact(argc, 2))
754 usage(cmd_subvol_get_default_usage);
757 fd = open_file_or_dir(subvol, &dirstream);
759 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
763 ret = btrfs_list_get_default_subvolume(fd, &default_id);
765 fprintf(stderr, "ERROR: can't perform the search - %s\n",
771 if (default_id == 0) {
772 fprintf(stderr, "ERROR: 'default' dir item not found\n");
776 /* no need to resolve roots if FS_TREE is default */
777 if (default_id == BTRFS_FS_TREE_OBJECTID) {
778 printf("ID 5 (FS_TREE)\n");
783 filter_set = btrfs_list_alloc_filter_set();
784 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID,
787 /* by default we shall print the following columns*/
788 btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
789 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
790 btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
791 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
793 ret = btrfs_list_subvols_print(fd, filter_set, NULL,
794 BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL);
797 btrfs_list_free_filter_set(filter_set);
799 close_file_or_dir(fd, dirstream);
803 static const char * const cmd_subvol_set_default_usage[] = {
804 "btrfs subvolume set-default <subvolid> <path>",
805 "Set the default subvolume of a filesystem",
809 static int cmd_subvol_set_default(int argc, char **argv)
815 DIR *dirstream = NULL;
817 if (check_argc_exact(argc, 3))
818 usage(cmd_subvol_set_default_usage);
823 objectid = (unsigned long long)strtoll(subvolid, NULL, 0);
824 if (errno == ERANGE) {
825 fprintf(stderr, "ERROR: invalid tree id (%s)\n", subvolid);
829 fd = open_file_or_dir(path, &dirstream);
831 fprintf(stderr, "ERROR: can't access '%s'\n", path);
835 ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid);
837 close_file_or_dir(fd, dirstream);
839 fprintf(stderr, "ERROR: unable to set a new default subvolume - %s\n",
846 static const char * const cmd_find_new_usage[] = {
847 "btrfs subvolume find-new <path> <lastgen>",
848 "List the recently modified files in a filesystem",
852 static int cmd_find_new(int argc, char **argv)
858 DIR *dirstream = NULL;
860 if (check_argc_exact(argc, 3))
861 usage(cmd_find_new_usage);
864 last_gen = atoll(argv[2]);
866 ret = test_issubvolume(subvol);
868 fprintf(stderr, "ERROR: error accessing '%s'\n", subvol);
872 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol);
876 fd = open_file_or_dir(subvol, &dirstream);
878 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
882 ret = ioctl(fd, BTRFS_IOC_SYNC);
884 fprintf(stderr, "ERROR: unable to fs-syncing '%s' - %s\n",
885 subvol, strerror(errno));
886 close_file_or_dir(fd, dirstream);
890 ret = btrfs_list_find_updated_files(fd, 0, last_gen);
891 close_file_or_dir(fd, dirstream);
895 static const char * const cmd_subvol_show_usage[] = {
896 "btrfs subvolume show <subvol-path>",
897 "Show more information of the subvolume",
901 static int cmd_subvol_show(int argc, char **argv)
903 struct root_info get_ri;
904 struct btrfs_list_filter_set *filter_set;
906 char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
907 char *fullpath = NULL, *svpath = NULL, *mnt = NULL;
908 char raw_prefix[] = "\t\t\t\t";
910 int fd = -1, mntfd = -1;
912 DIR *dirstream1 = NULL, *dirstream2 = NULL;
914 if (check_argc_exact(argc, 2))
915 usage(cmd_subvol_show_usage);
917 fullpath = realpath(argv[1], NULL);
919 fprintf(stderr, "ERROR: finding real path for '%s', %s\n",
920 argv[1], strerror(errno));
924 ret = test_issubvolume(fullpath);
926 fprintf(stderr, "ERROR: error accessing '%s'\n", fullpath);
930 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", fullpath);
934 ret = find_mount_root(fullpath, &mnt);
936 fprintf(stderr, "ERROR: find_mount_root failed on %s: "
937 "%s\n", fullpath, strerror(-ret));
941 svpath = get_subvol_name(mnt, fullpath);
943 fd = open_file_or_dir(fullpath, &dirstream1);
945 fprintf(stderr, "ERROR: can't access '%s'\n", fullpath);
949 ret = btrfs_list_get_path_rootid(fd, &sv_id);
951 fprintf(stderr, "ERROR: can't get rootid for '%s'\n",
956 mntfd = open_file_or_dir(mnt, &dirstream2);
958 fprintf(stderr, "ERROR: can't access '%s'\n", mnt);
962 ret = btrfs_list_get_path_rootid(mntfd, &mntid);
964 fprintf(stderr, "ERROR: can't get rootid for '%s'\n", mnt);
968 if (sv_id == BTRFS_FS_TREE_OBJECTID) {
969 printf("%s is btrfs root\n", fullpath);
973 memset(&get_ri, 0, sizeof(get_ri));
974 get_ri.root_id = sv_id;
976 if (btrfs_get_subvol(mntfd, &get_ri)) {
977 fprintf(stderr, "ERROR: can't find '%s'\n",
984 printf("%s\n", fullpath);
985 printf("\tName: \t\t\t%s\n", get_ri.name);
987 if (uuid_is_null(get_ri.uuid))
988 strcpy(uuidparse, "-");
990 uuid_unparse(get_ri.uuid, uuidparse);
991 printf("\tuuid: \t\t\t%s\n", uuidparse);
993 if (uuid_is_null(get_ri.puuid))
994 strcpy(uuidparse, "-");
996 uuid_unparse(get_ri.puuid, uuidparse);
997 printf("\tParent uuid: \t\t%s\n", uuidparse);
1002 localtime_r(&get_ri.otime, &tm);
1003 strftime(tstr, 256, "%Y-%m-%d %X", &tm);
1006 printf("\tCreation time: \t\t%s\n", tstr);
1008 printf("\tObject ID: \t\t%llu\n", get_ri.root_id);
1009 printf("\tGeneration (Gen): \t%llu\n", get_ri.gen);
1010 printf("\tGen at creation: \t%llu\n", get_ri.ogen);
1011 printf("\tParent: \t\t%llu\n", get_ri.ref_tree);
1012 printf("\tTop Level: \t\t%llu\n", get_ri.top_id);
1014 if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY)
1015 printf("\tFlags: \t\t\treadonly\n");
1017 printf("\tFlags: \t\t\t-\n");
1019 /* print the snapshots of the given subvol if any*/
1020 printf("\tSnapshot(s):\n");
1021 filter_set = btrfs_list_alloc_filter_set();
1022 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT,
1023 (u64)(unsigned long)get_ri.uuid);
1024 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
1025 btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
1031 free(get_ri.full_path);
1032 btrfs_list_free_filter_set(filter_set);
1035 close_file_or_dir(fd, dirstream1);
1036 close_file_or_dir(mntfd, dirstream2);
1042 const struct cmd_group subvolume_cmd_group = {
1043 subvolume_cmd_group_usage, NULL, {
1044 { "create", cmd_subvol_create, cmd_subvol_create_usage, NULL, 0 },
1045 { "delete", cmd_subvol_delete, cmd_subvol_delete_usage, NULL, 0 },
1046 { "list", cmd_subvol_list, cmd_subvol_list_usage, NULL, 0 },
1047 { "snapshot", cmd_snapshot, cmd_snapshot_usage, NULL, 0 },
1048 { "get-default", cmd_subvol_get_default,
1049 cmd_subvol_get_default_usage, NULL, 0 },
1050 { "set-default", cmd_subvol_set_default,
1051 cmd_subvol_set_default_usage, NULL, 0 },
1052 { "find-new", cmd_find_new, cmd_find_new_usage, NULL, 0 },
1053 { "show", cmd_subvol_show, cmd_subvol_show_usage, NULL, 0 },
1058 int cmd_subvolume(int argc, char **argv)
1060 return handle_command_group(&subvolume_cmd_group, argc, argv);