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);
360 if (sync_mode == 2 && fd != -1) {
361 res = wait_for_commit(fd);
364 "ERROR: unable to do final sync: %s\n",
369 close_file_or_dir(fd, dirstream);
376 * - uppercase for filters and sort options
377 * - lowercase for enabling specific items in the output
379 static const char * const cmd_subvol_list_usage[] = {
380 "btrfs subvolume list [options] [-G [+|-]value] [-C [+|-]value] "
381 "[--sort=gen,ogen,rootid,path] <path>",
382 "List subvolumes (and snapshots)",
384 "-p print parent ID",
385 "-a print all the subvolumes in the filesystem and",
386 " distinguish absolute and relative path with respect",
387 " to the given <path>",
388 "-c print the ogeneration of the subvolume",
389 "-g print the generation of the subvolume",
390 "-o print only subvolumes bellow specified path",
391 "-u print the uuid of subvolumes (and snapshots)",
392 "-q print the parent uuid of the snapshots",
393 "-t print the result as a table",
394 "-s list snapshots only in the filesystem",
395 "-r list readonly subvolumes (including snapshots)",
396 "-d list deleted subvolumes that are not yet cleaned",
398 " filter the subvolumes by generation",
399 " (+value: >= value; -value: <= value; value: = value)",
401 " filter the subvolumes by ogeneration",
402 " (+value: >= value; -value: <= value; value: = value)",
403 "--sort=gen,ogen,rootid,path",
404 " list the subvolume in order of gen, ogen, rootid or path",
405 " you also can add '+' or '-' in front of each items.",
406 " (+:ascending, -:descending, ascending default)",
410 static int cmd_subvol_list(int argc, char **argv)
412 struct btrfs_list_filter_set *filter_set;
413 struct btrfs_list_comparer_set *comparer_set;
417 int ret = -1, uerr = 0;
420 int is_tab_result = 0;
422 int is_only_in_path = 0;
423 struct option long_options[] = {
424 {"sort", 1, NULL, 'S'},
427 DIR *dirstream = NULL;
429 filter_set = btrfs_list_alloc_filter_set();
430 comparer_set = btrfs_list_alloc_comparer_set();
434 c = getopt_long(argc, argv,
435 "acdgopqsurG:C:t", long_options, NULL);
441 btrfs_list_setup_print_column(BTRFS_LIST_PARENT);
447 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
450 btrfs_list_setup_filter(&filter_set,
451 BTRFS_LIST_FILTER_DELETED,
455 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
464 btrfs_list_setup_filter(&filter_set,
465 BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
467 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
468 btrfs_list_setup_print_column(BTRFS_LIST_OTIME);
471 btrfs_list_setup_print_column(BTRFS_LIST_UUID);
474 btrfs_list_setup_print_column(BTRFS_LIST_PUUID);
477 flags |= BTRFS_ROOT_SUBVOL_RDONLY;
480 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
481 ret = btrfs_list_parse_filter_string(optarg,
483 BTRFS_LIST_FILTER_GEN);
491 btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
492 ret = btrfs_list_parse_filter_string(optarg,
494 BTRFS_LIST_FILTER_CGEN);
501 ret = btrfs_list_parse_sort_string(optarg,
516 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
519 if (check_argc_exact(argc - optind, 1)) {
524 subvol = argv[optind];
525 fd = open_file_or_dir(subvol, &dirstream);
528 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
532 ret = btrfs_list_get_path_rootid(fd, &top_id);
534 fprintf(stderr, "ERROR: can't get rootid for '%s'\n", subvol);
539 btrfs_list_setup_filter(&filter_set,
540 BTRFS_LIST_FILTER_FULL_PATH,
542 else if (is_only_in_path)
543 btrfs_list_setup_filter(&filter_set,
544 BTRFS_LIST_FILTER_TOPID_EQUAL,
547 /* by default we shall print the following columns*/
548 btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
549 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
550 btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
551 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
554 ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
555 BTRFS_LIST_LAYOUT_TABLE,
556 !is_list_all && !is_only_in_path, NULL);
558 ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
559 BTRFS_LIST_LAYOUT_DEFAULT,
560 !is_list_all && !is_only_in_path, NULL);
563 close_file_or_dir(fd, dirstream);
565 btrfs_list_free_filter_set(filter_set);
567 btrfs_list_free_comparer_set(comparer_set);
569 usage(cmd_subvol_list_usage);
573 static const char * const cmd_snapshot_usage[] = {
574 "btrfs subvolume snapshot [-r] <source> <dest>|[<dest>/]<name>",
575 "btrfs subvolume snapshot [-r] [-i <qgroupid>] <source> <dest>|[<dest>/]<name>",
576 "Create a snapshot of the subvolume",
577 "Create a writable/readonly snapshot of the subvolume <source> with",
578 "the name <name> in the <dest> directory. If only <dest> is given,",
579 "the subvolume will be named the basename of <source>.",
581 "-r create a readonly snapshot",
582 "-i <qgroupid> add the newly created snapshot to a qgroup. This",
583 " option can be given multiple times.",
587 static int cmd_snapshot(int argc, char **argv)
591 int fd = -1, fddst = -1;
592 int len, readonly = 0;
593 char *dupname = NULL;
597 struct btrfs_ioctl_vol_args_v2 args;
598 struct btrfs_qgroup_inherit *inherit = NULL;
599 DIR *dirstream1 = NULL, *dirstream2 = NULL;
602 memset(&args, 0, sizeof(args));
604 int c = getopt(argc, argv, "c:i:r");
610 res = qgroup_inherit_add_copy(&inherit, optarg, 0);
617 res = qgroup_inherit_add_group(&inherit, optarg);
627 res = qgroup_inherit_add_copy(&inherit, optarg, 1);
634 usage(cmd_snapshot_usage);
638 if (check_argc_exact(argc - optind, 2))
639 usage(cmd_snapshot_usage);
641 subvol = argv[optind];
642 dst = argv[optind + 1];
644 retval = 1; /* failure */
645 res = test_issubvolume(subvol);
647 fprintf(stderr, "ERROR: error accessing '%s'\n", subvol);
651 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol);
655 res = test_isdir(dst);
657 fprintf(stderr, "ERROR: '%s' exists and it is not a directory\n", dst);
662 dupname = strdup(subvol);
663 newname = basename(dupname);
666 dupname = strdup(dst);
667 newname = basename(dupname);
668 dupdir = strdup(dst);
669 dstdir = dirname(dupdir);
672 if (!strcmp(newname, ".") || !strcmp(newname, "..") ||
673 strchr(newname, '/') ){
674 fprintf(stderr, "ERROR: incorrect snapshot name ('%s')\n",
679 len = strlen(newname);
680 if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
681 fprintf(stderr, "ERROR: snapshot name too long ('%s)\n",
686 fddst = open_file_or_dir(dstdir, &dirstream1);
688 fprintf(stderr, "ERROR: can't access '%s'\n", dstdir);
692 fd = open_file_or_dir(subvol, &dirstream2);
694 fprintf(stderr, "ERROR: can't access '%s'\n", dstdir);
699 args.flags |= BTRFS_SUBVOL_RDONLY;
700 printf("Create a readonly snapshot of '%s' in '%s/%s'\n",
701 subvol, dstdir, newname);
703 printf("Create a snapshot of '%s' in '%s/%s'\n",
704 subvol, dstdir, newname);
709 args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
710 args.size = qgroup_inherit_size(inherit);
711 args.qgroup_inherit = inherit;
713 strncpy_null(args.name, newname);
715 res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
718 fprintf( stderr, "ERROR: cannot snapshot '%s' - %s\n",
719 subvol, strerror(errno));
723 retval = 0; /* success */
726 close_file_or_dir(fddst, dirstream1);
727 close_file_or_dir(fd, dirstream2);
735 static const char * const cmd_subvol_get_default_usage[] = {
736 "btrfs subvolume get-default <path>",
737 "Get the default subvolume of a filesystem",
741 static int cmd_subvol_get_default(int argc, char **argv)
746 struct btrfs_list_filter_set *filter_set;
748 DIR *dirstream = NULL;
750 if (check_argc_exact(argc, 2))
751 usage(cmd_subvol_get_default_usage);
754 fd = open_file_or_dir(subvol, &dirstream);
756 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
760 ret = btrfs_list_get_default_subvolume(fd, &default_id);
762 fprintf(stderr, "ERROR: can't perform the search - %s\n",
768 if (default_id == 0) {
769 fprintf(stderr, "ERROR: 'default' dir item not found\n");
773 /* no need to resolve roots if FS_TREE is default */
774 if (default_id == BTRFS_FS_TREE_OBJECTID) {
775 printf("ID 5 (FS_TREE)\n");
780 filter_set = btrfs_list_alloc_filter_set();
781 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID,
784 /* by default we shall print the following columns*/
785 btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
786 btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
787 btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
788 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
790 ret = btrfs_list_subvols_print(fd, filter_set, NULL,
791 BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL);
794 btrfs_list_free_filter_set(filter_set);
796 close_file_or_dir(fd, dirstream);
800 static const char * const cmd_subvol_set_default_usage[] = {
801 "btrfs subvolume set-default <subvolid> <path>",
802 "Set the default subvolume of a filesystem",
806 static int cmd_subvol_set_default(int argc, char **argv)
812 DIR *dirstream = NULL;
814 if (check_argc_exact(argc, 3))
815 usage(cmd_subvol_set_default_usage);
820 objectid = (unsigned long long)strtoll(subvolid, NULL, 0);
821 if (errno == ERANGE) {
822 fprintf(stderr, "ERROR: invalid tree id (%s)\n", subvolid);
826 fd = open_file_or_dir(path, &dirstream);
828 fprintf(stderr, "ERROR: can't access '%s'\n", path);
832 ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid);
834 close_file_or_dir(fd, dirstream);
836 fprintf(stderr, "ERROR: unable to set a new default subvolume - %s\n",
843 static const char * const cmd_find_new_usage[] = {
844 "btrfs subvolume find-new <path> <lastgen>",
845 "List the recently modified files in a filesystem",
849 static int cmd_find_new(int argc, char **argv)
855 DIR *dirstream = NULL;
857 if (check_argc_exact(argc, 3))
858 usage(cmd_find_new_usage);
861 last_gen = atoll(argv[2]);
863 ret = test_issubvolume(subvol);
865 fprintf(stderr, "ERROR: error accessing '%s'\n", subvol);
869 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol);
873 fd = open_file_or_dir(subvol, &dirstream);
875 fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
879 ret = ioctl(fd, BTRFS_IOC_SYNC);
881 fprintf(stderr, "ERROR: unable to fs-syncing '%s' - %s\n",
882 subvol, strerror(errno));
883 close_file_or_dir(fd, dirstream);
887 ret = btrfs_list_find_updated_files(fd, 0, last_gen);
888 close_file_or_dir(fd, dirstream);
892 static const char * const cmd_subvol_show_usage[] = {
893 "btrfs subvolume show <subvol-path>",
894 "Show more information of the subvolume",
898 static int cmd_subvol_show(int argc, char **argv)
900 struct root_info get_ri;
901 struct btrfs_list_filter_set *filter_set;
903 char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
904 char *fullpath = NULL, *svpath = NULL, *mnt = NULL;
905 char raw_prefix[] = "\t\t\t\t";
907 int fd = -1, mntfd = -1;
909 DIR *dirstream1 = NULL, *dirstream2 = NULL;
911 if (check_argc_exact(argc, 2))
912 usage(cmd_subvol_show_usage);
914 fullpath = realpath(argv[1], NULL);
916 fprintf(stderr, "ERROR: finding real path for '%s', %s\n",
917 argv[1], strerror(errno));
921 ret = test_issubvolume(fullpath);
923 fprintf(stderr, "ERROR: error accessing '%s'\n", fullpath);
927 fprintf(stderr, "ERROR: '%s' is not a subvolume\n", fullpath);
931 ret = find_mount_root(fullpath, &mnt);
933 fprintf(stderr, "ERROR: find_mount_root failed on %s: "
934 "%s\n", fullpath, strerror(-ret));
938 svpath = get_subvol_name(mnt, fullpath);
940 fd = open_file_or_dir(fullpath, &dirstream1);
942 fprintf(stderr, "ERROR: can't access '%s'\n", fullpath);
946 ret = btrfs_list_get_path_rootid(fd, &sv_id);
948 fprintf(stderr, "ERROR: can't get rootid for '%s'\n",
953 mntfd = open_file_or_dir(mnt, &dirstream2);
955 fprintf(stderr, "ERROR: can't access '%s'\n", mnt);
959 ret = btrfs_list_get_path_rootid(mntfd, &mntid);
961 fprintf(stderr, "ERROR: can't get rootid for '%s'\n", mnt);
965 if (sv_id == BTRFS_FS_TREE_OBJECTID) {
966 printf("%s is btrfs root\n", fullpath);
970 memset(&get_ri, 0, sizeof(get_ri));
971 get_ri.root_id = sv_id;
973 if (btrfs_get_subvol(mntfd, &get_ri)) {
974 fprintf(stderr, "ERROR: can't find '%s'\n",
981 printf("%s\n", fullpath);
982 printf("\tName: \t\t\t%s\n", get_ri.name);
984 if (uuid_is_null(get_ri.uuid))
985 strcpy(uuidparse, "-");
987 uuid_unparse(get_ri.uuid, uuidparse);
988 printf("\tuuid: \t\t\t%s\n", uuidparse);
990 if (uuid_is_null(get_ri.puuid))
991 strcpy(uuidparse, "-");
993 uuid_unparse(get_ri.puuid, uuidparse);
994 printf("\tParent uuid: \t\t%s\n", uuidparse);
999 localtime_r(&get_ri.otime, &tm);
1000 strftime(tstr, 256, "%Y-%m-%d %X", &tm);
1003 printf("\tCreation time: \t\t%s\n", tstr);
1005 printf("\tObject ID: \t\t%llu\n", get_ri.root_id);
1006 printf("\tGeneration (Gen): \t%llu\n", get_ri.gen);
1007 printf("\tGen at creation: \t%llu\n", get_ri.ogen);
1008 printf("\tParent: \t\t%llu\n", get_ri.ref_tree);
1009 printf("\tTop Level: \t\t%llu\n", get_ri.top_id);
1011 if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY)
1012 printf("\tFlags: \t\t\treadonly\n");
1014 printf("\tFlags: \t\t\t-\n");
1016 /* print the snapshots of the given subvol if any*/
1017 printf("\tSnapshot(s):\n");
1018 filter_set = btrfs_list_alloc_filter_set();
1019 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT,
1020 (u64)(unsigned long)get_ri.uuid);
1021 btrfs_list_setup_print_column(BTRFS_LIST_PATH);
1022 btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
1028 free(get_ri.full_path);
1029 btrfs_list_free_filter_set(filter_set);
1032 close_file_or_dir(fd, dirstream1);
1033 close_file_or_dir(mntfd, dirstream2);
1039 const struct cmd_group subvolume_cmd_group = {
1040 subvolume_cmd_group_usage, NULL, {
1041 { "create", cmd_subvol_create, cmd_subvol_create_usage, NULL, 0 },
1042 { "delete", cmd_subvol_delete, cmd_subvol_delete_usage, NULL, 0 },
1043 { "list", cmd_subvol_list, cmd_subvol_list_usage, NULL, 0 },
1044 { "snapshot", cmd_snapshot, cmd_snapshot_usage, NULL, 0 },
1045 { "get-default", cmd_subvol_get_default,
1046 cmd_subvol_get_default_usage, NULL, 0 },
1047 { "set-default", cmd_subvol_set_default,
1048 cmd_subvol_set_default_usage, NULL, 0 },
1049 { "find-new", cmd_find_new, cmd_find_new_usage, NULL, 0 },
1050 { "show", cmd_subvol_show, cmd_subvol_show_usage, NULL, 0 },
1055 int cmd_subvolume(int argc, char **argv)
1057 return handle_command_group(&subvolume_cmd_group, argc, argv);