Btrfs-progs: introduce '-r' option to print max referenced size of qgroups
[platform/upstream/btrfs-progs.git] / cmds-chunk.c
index 6ada328..4c2f3ed 100644 (file)
@@ -188,7 +188,8 @@ static struct btrfs_chunk *create_chunk_item(struct chunk_record *record)
        return ret;
 }
 
-void init_recover_control(struct recover_control *rc, int verbose, int yes)
+static void init_recover_control(struct recover_control *rc, int verbose,
+               int yes)
 {
        memset(rc, 0, sizeof(struct recover_control));
        cache_tree_init(&rc->chunk);
@@ -204,7 +205,7 @@ void init_recover_control(struct recover_control *rc, int verbose, int yes)
        rc->yes = yes;
 }
 
-void free_recover_control(struct recover_control *rc)
+static void free_recover_control(struct recover_control *rc)
 {
        free_block_group_tree(&rc->bg);
        free_chunk_cache_tree(&rc->chunk);
@@ -582,14 +583,14 @@ static int check_chunk_by_metadata(struct recover_control *rc,
                if (ret < 0) {
                        fprintf(stderr, "Search device extent failed(%d)\n",
                                ret);
-                       btrfs_release_path(root, &path);
+                       btrfs_release_path(&path);
                        return ret;
                } else if (ret > 0) {
                        if (rc->verbose)
                                fprintf(stderr,
                                        "No device extent[%llu, %llu]\n",
                                        stripe->devid, stripe->offset);
-                       btrfs_release_path(root, &path);
+                       btrfs_release_path(&path);
                        return -ENOENT;
                }
                l = path.nodes[0];
@@ -604,10 +605,10 @@ static int check_chunk_by_metadata(struct recover_control *rc,
                                                                dev_extent),
                                        btrfs_dev_extent_length(l, dev_extent),
                                        chunk->offset, chunk->length);
-                       btrfs_release_path(root, &path);
+                       btrfs_release_path(&path);
                        return -ENOENT;
                }
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
        }
 
 bg_check:
@@ -619,13 +620,13 @@ bg_check:
                                0, 0);
        if (ret < 0) {
                fprintf(stderr, "Search block group failed(%d)\n", ret);
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
                return ret;
        } else if (ret > 0) {
                if (rc->verbose)
                        fprintf(stderr, "No block group[%llu, %llu]\n",
                                key.objectid, key.offset);
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
                return -ENOENT;
        }
 
@@ -638,10 +639,10 @@ bg_check:
                                "Chunk[%llu, %llu]'s type(%llu) is differemt with Block Group's type(%llu)\n",
                                chunk->offset, chunk->length, chunk->type_flags,
                                btrfs_disk_block_group_flags(l, bg_ptr));
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
                return -ENOENT;
        }
-       btrfs_release_path(root, &path);
+       btrfs_release_path(&path);
        return 0;
 }
 
@@ -743,8 +744,7 @@ static int scan_one_device(struct recover_control *rc, int fd,
                        break;
 
                if (memcmp_extent_buffer(buf, rc->fs_devices->fsid,
-                                        (unsigned long)btrfs_header_fsid(buf),
-                                        BTRFS_FSID_SIZE)) {
+                                        btrfs_header_fsid(), BTRFS_FSID_SIZE)) {
                        bytenr += rc->sectorsize;
                        continue;
                }
@@ -793,13 +793,15 @@ static int scan_devices(struct recover_control *rc)
        int ret = 0;
        int fd;
        struct btrfs_device *dev;
+       int e;
 
        list_for_each_entry(dev, &rc->fs_devices->devices, dev_list) {
                fd = open(dev->name, O_RDONLY);
                if (fd < 0) {
+                       e = errno;
                        fprintf(stderr, "Failed to open device %s\n",
                                dev->name);
-                       return -1;
+                       return -e;
                }
                ret = scan_one_device(rc, fd, dev);
                close(fd);
@@ -915,7 +917,7 @@ again:
                btrfs_item_key_to_cpu(leaf, &key, 0);
                if (key.objectid >= end)
                        goto err;
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
                goto again;
        }
 
@@ -960,11 +962,11 @@ again:
                        key.type = BTRFS_EXTENT_ITEM_KEY;
                        key.offset = 0;
                }
-               btrfs_release_path(root, &path);
+               btrfs_release_path(&path);
                goto again;
        }
 err:
-       btrfs_release_path(root, &path);
+       btrfs_release_path(&path);
        return ret;
 }
 
@@ -1030,9 +1032,9 @@ static int __rebuild_chunk_root(struct btrfs_trans_handle *trans,
                if (min_devid > dev->devid)
                        min_devid = dev->devid;
        }
-       disk_key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
-       disk_key.type = BTRFS_DEV_ITEM_KEY;
-       disk_key.offset = min_devid;
+       btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_ITEMS_OBJECTID);
+       btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_ITEM_KEY);
+       btrfs_set_disk_key_offset(&disk_key, min_devid);
 
        cow = btrfs_alloc_free_block(trans, root, root->sectorsize,
                                     BTRFS_CHUNK_TREE_OBJECTID,
@@ -1044,8 +1046,7 @@ static int __rebuild_chunk_root(struct btrfs_trans_handle *trans,
        btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV);
        btrfs_set_header_owner(cow, BTRFS_CHUNK_TREE_OBJECTID);
        write_extent_buffer(cow, root->fs_info->fsid,
-                       (unsigned long)btrfs_header_fsid(cow),
-                       BTRFS_FSID_SIZE);
+                       btrfs_header_fsid(), BTRFS_FSID_SIZE);
 
        write_extent_buffer(cow, root->fs_info->chunk_tree_uuid,
                        (unsigned long)btrfs_header_chunk_tree_uuid(cow),
@@ -1116,7 +1117,7 @@ static int __rebuild_chunk_items(struct btrfs_trans_handle *trans,
                key.offset = chunk_rec->offset;
 
                ret = btrfs_insert_item(trans, chunk_root, &key, chunk,
-                               btrfs_chunk_item_size(chunk->num_stripes));
+                               btrfs_chunk_item_size(chunk_rec->num_stripes));
                free(chunk);
                if (ret)
                        return ret;
@@ -1307,58 +1308,22 @@ fail_close_fd:
        return ret;
 }
 
-static int ask_user(char *question, int defval)
+/*
+ * This reads a line from the stdin and only returns non-zero if the
+ * first whitespace delimited token is a case insensitive match with yes
+ * or y.
+ */
+static int ask_user(char *question)
 {
-       char answer[5];
-       char *defstr;
-       int i;
-
-       if (defval == 1)
-               defstr = "[Y/n]";
-       else if (defval == 0)
-               defstr = "[y/N]";
-       else if (defval == -1)
-               defstr = "[y/n]";
-       else
-               BUG_ON(1);
-again:
-       printf("%s%s? ", question, defstr);
-
-       i = 0;
-       while (i < 4 && scanf("%c", &answer[i])) {
-               if (answer[i] == '\n') {
-                       answer[i] = '\0';
-                       break;
-               } else if (answer[i] == ' '){
-                       answer[i] = '\0';
-                       if (i == 0)
-                               continue;
-                       else
-                               break;
-               } else if (answer[i] >= 'A' && answer[i] <= 'Z') {
-                       answer[i] += 'a' - 'A';
-               }
-               i++;
-       }
-       answer[5] = '\0';
-       __fpurge(stdin);
-
-       if (strlen(answer) == 0) {
-               if (defval != -1)
-                       return defval;
-               else
-                       goto again;
-       }
-
-       if (!strcmp(answer, "yes") ||
-           !strcmp(answer, "y"))
-               return 1;
+       char buf[30] = {0,};
+       char *saveptr = NULL;
+       char *answer;
 
-       if (!strcmp(answer, "no") ||
-           !strcmp(answer, "n"))
-               return 0;
+       printf("%s [y/N]: ", question);
 
-       goto again;
+       return fgets(buf, sizeof(buf) - 1, stdin) &&
+              (answer = strtok_r(buf, " \t\n\r", &saveptr)) &&
+              (!strcasecmp(answer, "yes") || !strcasecmp(answer, "y"));
 }
 
 static int btrfs_get_device_extents(u64 chunk_object,
@@ -1752,8 +1717,7 @@ static int btrfs_recover_chunk_tree(char *path, int verbose, int yes)
        }
 
        if (!rc.yes) {
-               ret = ask_user("We are going to rebuild the chunk tree on disk, it might destroy the old metadata on the disk, Are you sure",
-                              0);
+               ret = ask_user("We are going to rebuild the chunk tree on disk, it might destroy the old metadata on the disk, Are you sure?");
                if (!ret) {
                        ret = BTRFS_CHUNK_TREE_REBUILD_ABORTED;
                        goto fail_close_ctree;
@@ -1779,8 +1743,8 @@ fail_rc:
 }
 
 const char * const cmd_chunk_recover_usage[] = {
-       "btrfs chunk-recover [options] <device>",
-       "Recover the chunk tree by scaning the devices one by one.",
+       "btrfs rescue chunk-recover [options] <device>",
+       "Recover the chunk tree by scanning the devices one by one.",
        "",
        "-y     Assume an answer of `yes' to all questions",
        "-v     Verbose mode",
@@ -1821,7 +1785,7 @@ int cmd_chunk_recover(int argc, char *argv[])
        ret = check_mounted(file);
        if (ret) {
                fprintf(stderr, "the device is busy\n");
-               return ret;
+               goto out;
        }
 
        ret = btrfs_recover_chunk_tree(file, verbose, yes);
@@ -1833,5 +1797,6 @@ int cmd_chunk_recover(int argc, char *argv[])
        } else {
                fprintf(stdout, "Fail to recover the chunk tree.\n");
        }
-       return ret;
+out:
+       return !!ret;
 }