btrfs-progs: docs: enhance documentation of 'btrfs device ready'
[platform/upstream/btrfs-progs.git] / cmds-subvolume.c
index 2319684..666f6e0 100644 (file)
@@ -37,6 +37,7 @@
 #include "utils.h"
 #include "btrfs-list.h"
 #include "utils.h"
+#include "help.h"
 
 static int is_subvolume_cleaned(int fd, u64 subvolid)
 {
@@ -127,9 +128,8 @@ static int cmd_subvol_create(int argc, char **argv)
        struct btrfs_qgroup_inherit *inherit = NULL;
        DIR     *dirstream = NULL;
 
-       optind = 1;
        while (1) {
-               int c = getopt(argc, argv, "c:i:v");
+               int c = getopt(argc, argv, "c:i:");
                if (c < 0)
                        break;
 
@@ -246,6 +246,7 @@ static const char * const cmd_subvol_delete_usage[] = {
        "",
        "-c|--commit-after      wait for transaction commit at the end of the operation",
        "-C|--commit-each       wait for transaction commit after deleting each subvolume",
+       "-v|--verbose           verbose output of operations",
        NULL
 };
 
@@ -263,16 +264,16 @@ static int cmd_subvol_delete(int argc, char **argv)
        int verbose = 0;
        int commit_mode = 0;
 
-       optind = 1;
        while (1) {
                int c;
                static const struct option long_options[] = {
                        {"commit-after", no_argument, NULL, 'c'},  /* commit mode 1 */
                        {"commit-each", no_argument, NULL, 'C'},  /* commit mode 2 */
+                       {"verbose", no_argument, NULL, 'v'},
                        {NULL, 0, NULL, 0}
                };
 
-               c = getopt_long(argc, argv, "cC", long_options, NULL);
+               c = getopt_long(argc, argv, "cCv", long_options, NULL);
                if (c < 0)
                        break;
 
@@ -431,15 +432,14 @@ static int cmd_subvol_list(int argc, char **argv)
        u64 top_id;
        int ret = -1, uerr = 0;
        char *subvol;
-       int is_tab_result = 0;
        int is_list_all = 0;
        int is_only_in_path = 0;
        DIR *dirstream = NULL;
+       enum btrfs_list_layout layout = BTRFS_LIST_LAYOUT_DEFAULT;
 
        filter_set = btrfs_list_alloc_filter_set();
        comparer_set = btrfs_list_alloc_comparer_set();
 
-       optind = 1;
        while(1) {
                int c;
                static const struct option long_options[] = {
@@ -474,7 +474,7 @@ static int cmd_subvol_list(int argc, char **argv)
                        is_only_in_path = 1;
                        break;
                case 't':
-                       is_tab_result = 1;
+                       layout = BTRFS_LIST_LAYOUT_TABLE;
                        break;
                case 's':
                        btrfs_list_setup_filter(&filter_set,
@@ -531,10 +531,6 @@ static int cmd_subvol_list(int argc, char **argv)
                }
        }
 
-       if (flags)
-               btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
-                                       flags);
-
        if (check_argc_exact(argc - optind, 1)) {
                uerr = 1;
                goto out;
@@ -548,11 +544,13 @@ static int cmd_subvol_list(int argc, char **argv)
                goto out;
        }
 
+       if (flags)
+               btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
+                                       flags);
+
        ret = btrfs_list_get_path_rootid(fd, &top_id);
-       if (ret) {
-               error("can't get rootid for '%s'", subvol);
+       if (ret)
                goto out;
-       }
 
        if (is_list_all)
                btrfs_list_setup_filter(&filter_set,
@@ -569,21 +567,15 @@ static int cmd_subvol_list(int argc, char **argv)
        btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
        btrfs_list_setup_print_column(BTRFS_LIST_PATH);
 
-       if (is_tab_result)
-               ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
-                               BTRFS_LIST_LAYOUT_TABLE,
-                               !is_list_all && !is_only_in_path, NULL);
-       else
-               ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
-                               BTRFS_LIST_LAYOUT_DEFAULT,
-                               !is_list_all && !is_only_in_path, NULL);
+       ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
+                       layout, !is_list_all && !is_only_in_path, NULL);
 
 out:
        close_file_or_dir(fd, dirstream);
        if (filter_set)
-               btrfs_list_free_filter_set(filter_set);
+               free(filter_set);
        if (comparer_set)
-               btrfs_list_free_comparer_set(comparer_set);
+               free(comparer_set);
        if (uerr)
                usage(cmd_subvol_list_usage);
        return !!ret;
@@ -616,7 +608,6 @@ static int cmd_subvol_snapshot(int argc, char **argv)
        struct btrfs_qgroup_inherit *inherit = NULL;
        DIR *dirstream1 = NULL, *dirstream2 = NULL;
 
-       optind = 1;
        memset(&args, 0, sizeof(args));
        while (1) {
                int c = getopt(argc, argv, "c:i:r");
@@ -805,7 +796,7 @@ static int cmd_subvol_get_default(int argc, char **argv)
                BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL);
 
        if (filter_set)
-               btrfs_list_free_filter_set(filter_set);
+               free(filter_set);
 out:
        close_file_or_dir(fd, dirstream);
        return !!ret;
@@ -900,8 +891,13 @@ static int cmd_subvol_find_new(int argc, char **argv)
 }
 
 static const char * const cmd_subvol_show_usage[] = {
-       "btrfs subvolume show <subvol-path>",
-       "Show more information of the subvolume",
+       "btrfs subvolume show [options] <subvol-path>|<mnt>",
+       "Show more information about the subvolume",
+       "-r|--rootid   rootid of the subvolume",
+       "-u|--uuid     uuid of the subvolume",
+       "",
+       "If no option is specified, <subvol-path> will be shown, otherwise",
+       "the rootid or uuid are resolved relative to the <mnt> path.",
        NULL
 };
 
@@ -916,12 +912,46 @@ static int cmd_subvol_show(int argc, char **argv)
        int fd = -1;
        int ret = 1;
        DIR *dirstream1 = NULL;
+       int by_rootid = 0;
+       int by_uuid = 0;
+       u64 rootid_arg;
+       u8 uuid_arg[BTRFS_UUID_SIZE];
+
+       while (1) {
+               int c;
+               static const struct option long_options[] = {
+                       { "rootid", required_argument, NULL, 'r'},
+                       { "uuid", required_argument, NULL, 'u'},
+                       { NULL, 0, NULL, 0 }
+               };
+
+               c = getopt_long(argc, argv, "r:u:", long_options, NULL);
+               if (c < 0)
+                       break;
 
-       clean_args_no_options(argc, argv, cmd_subvol_show_usage);
+               switch (c) {
+               case 'r':
+                       rootid_arg = arg_strtou64(optarg);
+                       by_rootid = 1;
+                       break;
+               case 'u':
+                       uuid_parse(optarg, uuid_arg);
+                       by_uuid = 1;
+                       break;
+               default:
+                       usage(cmd_subvol_show_usage);
+               }
+       }
 
        if (check_argc_exact(argc - optind, 1))
                usage(cmd_subvol_show_usage);
 
+       if (by_rootid && by_uuid) {
+               error(
+               "options --rootid and --uuid cannot be used at the same time");
+               usage(cmd_subvol_show_usage);
+       }
+
        memset(&get_ri, 0, sizeof(get_ri));
        fullpath = realpath(argv[optind], NULL);
        if (!fullpath) {
@@ -930,27 +960,27 @@ static int cmd_subvol_show(int argc, char **argv)
                goto out;
        }
 
-       ret = get_subvol_info(fullpath, &get_ri);
-       if (ret == 2) {
-               /*
-                * Since the top level btrfs was given don't
-                * take that as error
-                */
-               printf("%s is toplevel subvolume\n", fullpath);
-               ret = 0;
-               goto out;
+       if (by_rootid) {
+               ret = get_subvol_info_by_rootid(fullpath, &get_ri, rootid_arg);
+       } else if (by_uuid) {
+               ret = get_subvol_info_by_uuid(fullpath, &get_ri, uuid_arg);
+       } else {
+               ret = get_subvol_info(fullpath, &get_ri);
        }
+
        if (ret) {
-               ret < 0 ?
-                       error("Failed to get subvol info %s: %s\n",
-                                                       fullpath, strerror(-ret)):
-                       error("Failed to get subvol info %s: %d\n",
-                                                       fullpath, ret);
+               if (ret < 0) {
+                       error("Failed to get subvol info %s: %s",
+                                       fullpath, strerror(-ret));
+               } else {
+                       error("Failed to get subvol info %s: %d",
+                                       fullpath, ret);
+               }
                return ret;
        }
 
        /* print the info */
-       printf("%s\n", fullpath);
+       printf("%s\n", get_ri.full_path);
        printf("\tName: \t\t\t%s\n", get_ri.name);
 
        if (uuid_is_null(get_ri.uuid))
@@ -1011,7 +1041,7 @@ out:
        free(get_ri.path);
        free(get_ri.name);
        free(get_ri.full_path);
-       btrfs_list_free_filter_set(filter_set);
+       free(filter_set);
 
        close_file_or_dir(fd, dirstream1);
        free(fullpath);
@@ -1142,7 +1172,8 @@ static int enumerate_dead_subvols(int fd, u64 **ids)
                        sh = (struct btrfs_ioctl_search_header*)(args.buf + off);
                        off += sizeof(*sh);
 
-                       if (sh->type == BTRFS_ORPHAN_ITEM_KEY) {
+                       if (btrfs_search_header_type(sh)
+                           == BTRFS_ORPHAN_ITEM_KEY) {
                                if (idx >= count) {
                                        u64 *newids;
 
@@ -1153,14 +1184,14 @@ static int enumerate_dead_subvols(int fd, u64 **ids)
                                                return -ENOMEM;
                                        *ids = newids;
                                }
-                               (*ids)[idx] = sh->offset;
+                               (*ids)[idx] = btrfs_search_header_offset(sh);
                                idx++;
                        }
-                       off += sh->len;
+                       off += btrfs_search_header_len(sh);
 
-                       sk->min_objectid = sh->objectid;
-                       sk->min_type = sh->type;
-                       sk->min_offset = sh->offset;
+                       sk->min_objectid = btrfs_search_header_objectid(sh);
+                       sk->min_type = btrfs_search_header_type(sh);
+                       sk->min_offset = btrfs_search_header_offset(sh);
                }
                if (sk->min_offset < (u64)-1)
                        sk->min_offset++;
@@ -1185,7 +1216,6 @@ static int cmd_subvol_sync(int argc, char **argv)
        int id_count;
        int sleep_interval = 1;
 
-       optind = 1;
        while (1) {
                int c = getopt(argc, argv, "s:");
 
@@ -1194,10 +1224,9 @@ static int cmd_subvol_sync(int argc, char **argv)
 
                switch (c) {
                case 's':
-                       sleep_interval = atoi(argv[optind]);
+                       sleep_interval = atoi(optarg);
                        if (sleep_interval < 1) {
-                               error("invalid sleep interval %s",
-                                       argv[optind]);
+                               error("invalid sleep interval %s", optarg);
                                ret = 1;
                                goto out;
                        }
@@ -1252,7 +1281,7 @@ static int cmd_subvol_sync(int argc, char **argv)
                        }
                        if (id < BTRFS_FIRST_FREE_OBJECTID
                                        || id > BTRFS_LAST_FREE_OBJECTID) {
-                               error("subvolume id %s out of range\n", arg);
+                               error("subvolume id %s out of range", arg);
                                ret = 1;
                                goto out;
                        }