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);
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);
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];
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:
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;
}
"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;
}
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;
}
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);
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;
}
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;
}
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,
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),
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;
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,
}
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;
}
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",
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);
} else {
fprintf(stdout, "Fail to recover the chunk tree.\n");
}
- return ret;
+out:
+ return !!ret;
}