From 1f3ba6a3f9440a40108273dbbe4f37306be8d9ad Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 24 Mar 2008 15:04:37 -0400 Subject: Btrfsck updates for multi-device filesystems --- btrfsck.c | 24 +++++++++++++++------ ctree.h | 38 +++++++++------------------------ disk-io.c | 8 +++---- print-tree.c | 15 ++------------ utils.c | 68 ++++++++++++++++++++++++++++++------------------------------ volumes.c | 63 ++++++++++++++----------------------------------------- volumes.h | 13 +----------- 7 files changed, 85 insertions(+), 144 deletions(-) diff --git a/btrfsck.c b/btrfsck.c index a3f803e9..aa2256ea 100644 --- a/btrfsck.c +++ b/btrfsck.c @@ -119,15 +119,23 @@ static int check_leaf(struct btrfs_root *root, for (i = 0; nritems > 1 && i < nritems - 2; i++) { btrfs_item_key(buf, &key, i); btrfs_item_key_to_cpu(buf, &cpukey, i + 1); - if (btrfs_comp_keys(&key, &cpukey) >= 0) + if (btrfs_comp_keys(&key, &cpukey) >= 0) { + fprintf(stderr, "bad key ordering %d %d\n", i, i+1); return 1; + } if (btrfs_item_offset_nr(buf, i) != - btrfs_item_end_nr(buf, i + 1)) + btrfs_item_end_nr(buf, i + 1)) { + fprintf(stderr, "incorrect offsets %u %u\n", + btrfs_item_offset_nr(buf, i), + btrfs_item_end_nr(buf, i + 1)); + return 1; + } + if (i == 0 && btrfs_item_end_nr(buf, i) != + BTRFS_LEAF_DATA_SIZE(root)) { + fprintf(stderr, "bad item end %u wanted %lu\n", + btrfs_item_end_nr(buf, i), + BTRFS_LEAF_DATA_SIZE(root)); return 1; - if (i == 0) { - if (btrfs_item_end_nr(buf, i) != - BTRFS_LEAF_DATA_SIZE(root)) - return 1; } } return 0; @@ -755,6 +763,10 @@ int main(int ac, char **av) { &extent_cache, &pending, &seen, &reada, &nodes, root->fs_info->tree_root->root_key.objectid); + add_root_to_pending(root->fs_info->chunk_root->node, bits, bits_nr, + &extent_cache, &pending, &seen, &reada, &nodes, + root->fs_info->chunk_root->root_key.objectid); + btrfs_init_path(&path); key.offset = 0; key.objectid = 0; diff --git a/ctree.h b/ctree.h index 7e305233..a8c1b5fa 100644 --- a/ctree.h +++ b/ctree.h @@ -37,24 +37,23 @@ struct btrfs_trans_handle; /* stores information about which extents are in use, and reference counts */ #define BTRFS_EXTENT_TREE_OBJECTID 2ULL -/* one per subvolume, storing files and directories */ -#define BTRFS_FS_TREE_OBJECTID 3ULL - -/* directory objectid inside the root tree */ -#define BTRFS_ROOT_TREE_DIR_OBJECTID 4ULL - - /* * chunk tree stores translations from logical -> physical block numbering * the super block points to the chunk tree */ -#define BTRFS_CHUNK_TREE_OBJECTID 5ULL +#define BTRFS_CHUNK_TREE_OBJECTID 3ULL /* * stores information about which areas of a given device are in use. * one per device. The tree of tree roots points to the device tree */ -#define BTRFS_DEV_TREE_OBJECTID 6ULL +#define BTRFS_DEV_TREE_OBJECTID 4ULL + +/* one per subvolume, storing files and directories */ +#define BTRFS_FS_TREE_OBJECTID 5ULL + +/* directory objectid inside the root tree */ +#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL /* * All files have objectids higher than this. @@ -141,21 +140,11 @@ struct btrfs_dev_item { /* minimal io size for this device */ __le32 sector_size; - /* the kernel device number */ - __le64 rdev; - /* type and info about this device */ __le64 type; - /* partition number, 0 for whole dev */ - __le32 partition; - - /* length of the name data at the end of the item */ - __le16 name_len; - - /* physical drive uuid (or lvm uuid) */ + /* btrfs generated uuid for this device */ u8 uuid[BTRFS_DEV_UUID_SIZE]; - /* name goes here */ } __attribute__ ((__packed__)); struct btrfs_stripe { @@ -245,6 +234,7 @@ struct btrfs_super_block { __le32 sys_chunk_array_size; u8 root_level; u8 chunk_root_level; + struct btrfs_dev_item dev_item; u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; } __attribute__ ((__packed__)); @@ -639,20 +629,12 @@ BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32); BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32); BTRFS_SETGET_FUNCS(device_sector_size, struct btrfs_dev_item, sector_size, 32); BTRFS_SETGET_FUNCS(device_id, struct btrfs_dev_item, devid, 64); -BTRFS_SETGET_FUNCS(device_rdev, struct btrfs_dev_item, rdev, 64); -BTRFS_SETGET_FUNCS(device_partition, struct btrfs_dev_item, partition, 32); -BTRFS_SETGET_FUNCS(device_name_len, struct btrfs_dev_item, name_len, 16); static inline char *btrfs_device_uuid(struct btrfs_dev_item *d) { return (char *)d + offsetof(struct btrfs_dev_item, uuid); } -static inline char *btrfs_device_name(struct btrfs_dev_item *d) -{ - return (char *)(d + 1); -} - BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64); BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64); BTRFS_SETGET_FUNCS(chunk_io_align, struct btrfs_chunk, io_align, 32); diff --git a/disk-io.c b/disk-io.c index c00a0f6e..ce801bf1 100644 --- a/disk-io.c +++ b/disk-io.c @@ -34,8 +34,6 @@ int btrfs_open_device(struct btrfs_device *dev) { - dev->fd = open(dev->name, O_RDWR, 0600); - BUG_ON(dev->fd < 0); return 0; } @@ -484,6 +482,9 @@ struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) tree_root->sectorsize = sectorsize; tree_root->stripesize = stripesize; + ret = btrfs_read_super_device(tree_root, fs_info->sb_buffer); + BUG_ON(ret); + ret = btrfs_read_sys_array(tree_root); BUG_ON(ret); blocksize = btrfs_level_size(tree_root, @@ -561,8 +562,7 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) next = list->next; list_del(next); device = list_entry(next, struct btrfs_device, dev_list); - kfree(device->name); - close(device->fd); + // close(device->fd); kfree(device); } return 0; diff --git a/print-tree.c b/print-tree.c index ec99b8ca..6a4d0f11 100644 --- a/print-tree.c +++ b/print-tree.c @@ -92,22 +92,11 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk) static void print_dev_item(struct extent_buffer *eb, struct btrfs_dev_item *dev_item) { - char *name; - int name_len; - - name_len = btrfs_device_name_len(eb, dev_item); - name = kmalloc(name_len, GFP_NOFS); - if (name) { - read_extent_buffer(eb, name, - (unsigned long)btrfs_device_name(dev_item), - name_len); - } - printf("\t\tdev item name %.*s devid %llu " - "total_bytes %llu bytes used %Lu\n", name_len, name, + printf("\t\tdev item devid %llu " + "total_bytes %llu bytes used %Lu\n", (unsigned long long)btrfs_device_id(eb, dev_item), (unsigned long long)btrfs_device_total_bytes(eb, dev_item), (unsigned long long)btrfs_device_bytes_used(eb, dev_item)); - kfree(name); } void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) { diff --git a/utils.c b/utils.c index f04e9c5a..bb8f9442 100644 --- a/utils.c +++ b/utils.c @@ -112,38 +112,49 @@ int make_btrfs(int fd, char *device_name, memset(&disk_key, 0, sizeof(disk_key)); btrfs_set_disk_key_type(&disk_key, BTRFS_ROOT_ITEM_KEY); btrfs_set_disk_key_offset(&disk_key, 0); + nritems = 0; itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(root_item); btrfs_set_root_bytenr(&root_item, blocks[2]); btrfs_set_disk_key_objectid(&disk_key, BTRFS_EXTENT_TREE_OBJECTID); - btrfs_set_item_key(buf, &disk_key, 0); - btrfs_set_item_offset(buf, btrfs_item_nr(buf, 0), itemoff); - btrfs_set_item_size(buf, btrfs_item_nr(buf, 0), sizeof(root_item)); - write_extent_buffer(buf, &root_item, btrfs_item_ptr_offset(buf, 0), + btrfs_set_item_key(buf, &disk_key, nritems); + btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff); + btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), sizeof(root_item)); + write_extent_buffer(buf, &root_item, btrfs_item_ptr_offset(buf, + nritems), sizeof(root_item)); + nritems++; itemoff = itemoff - sizeof(root_item); - btrfs_set_root_bytenr(&root_item, blocks[5]); - btrfs_set_disk_key_objectid(&disk_key, BTRFS_FS_TREE_OBJECTID); - btrfs_set_item_key(buf, &disk_key, 1); - btrfs_set_item_offset(buf, btrfs_item_nr(buf, 1), itemoff); - btrfs_set_item_size(buf, btrfs_item_nr(buf, 1), sizeof(root_item)); - write_extent_buffer(buf, &root_item, btrfs_item_ptr_offset(buf, 1), + btrfs_set_root_bytenr(&root_item, blocks[4]); + btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_TREE_OBJECTID); + btrfs_set_item_key(buf, &disk_key, nritems); + btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff); + btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), sizeof(root_item)); + write_extent_buffer(buf, &root_item, + btrfs_item_ptr_offset(buf, nritems), + sizeof(root_item)); + nritems++; itemoff = itemoff - sizeof(root_item); - btrfs_set_root_bytenr(&root_item, blocks[4]); - btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_TREE_OBJECTID); - btrfs_set_item_key(buf, &disk_key, 2); - btrfs_set_item_offset(buf, btrfs_item_nr(buf, 2), itemoff); - btrfs_set_item_size(buf, btrfs_item_nr(buf, 2), sizeof(root_item)); - write_extent_buffer(buf, &root_item, btrfs_item_ptr_offset(buf, 2), + btrfs_set_root_bytenr(&root_item, blocks[5]); + btrfs_set_disk_key_objectid(&disk_key, BTRFS_FS_TREE_OBJECTID); + btrfs_set_item_key(buf, &disk_key, nritems); + btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff); + btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), + sizeof(root_item)); + write_extent_buffer(buf, &root_item, + btrfs_item_ptr_offset(buf, nritems), sizeof(root_item)); + nritems++; + ret = pwrite(fd, buf->data, leafsize, blocks[1]); BUG_ON(ret != leafsize); /* create the items for the extent tree */ + nritems = 0; itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(struct btrfs_extent_item); btrfs_set_disk_key_objectid(&disk_key, 0); @@ -241,6 +252,7 @@ int make_btrfs(int fd, char *device_name, read_extent_buffer(buf, ptr, (unsigned long)chunk, item_size); array_size += item_size; ptr += item_size; + btrfs_set_super_sys_array_size(&super, array_size); /* then device 1 (there is no device 0) */ nritems++; @@ -261,28 +273,16 @@ int make_btrfs(int fd, char *device_name, btrfs_set_device_io_align(buf, dev_item, sectorsize); btrfs_set_device_io_width(buf, dev_item, sectorsize); btrfs_set_device_sector_size(buf, dev_item, sectorsize); - btrfs_set_device_rdev(buf, dev_item, 0); btrfs_set_device_type(buf, dev_item, 0); - btrfs_set_device_partition(buf, dev_item, 0); - btrfs_set_device_name_len(buf, dev_item, strlen(device_name)); nritems++; - memset_extent_buffer(buf, 0, (unsigned long)btrfs_device_uuid(dev_item), - BTRFS_DEV_UUID_SIZE); - write_extent_buffer(buf, device_name, - (unsigned long)btrfs_device_name(dev_item), - strlen(device_name)); + uuid_generate(super.dev_item.uuid); - /* copy the device item and key into the system array */ - memcpy(ptr, &disk_key, sizeof(disk_key)); - ptr += sizeof(disk_key); - array_size += sizeof(disk_key); - - read_extent_buffer(buf, ptr, (unsigned long)dev_item, item_size); - array_size += item_size; - ptr += item_size; - - btrfs_set_super_sys_array_size(&super, array_size); + write_extent_buffer(buf, super.dev_item.uuid, + (unsigned long)btrfs_device_uuid(dev_item), + BTRFS_DEV_UUID_SIZE); + read_extent_buffer(buf, &super.dev_item, (unsigned long)dev_item, + sizeof(*dev_item)); btrfs_set_header_bytenr(buf, blocks[3]); btrfs_set_header_owner(buf, BTRFS_CHUNK_TREE_OBJECTID); diff --git a/volumes.c b/volumes.c index 52a56f1e..6dc0eb1a 100644 --- a/volumes.c +++ b/volumes.c @@ -276,7 +276,7 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, key.offset = free_devid; ret = btrfs_insert_empty_item(trans, root, path, &key, - sizeof(*dev_item) + device->name_len); + sizeof(*dev_item)); if (ret) goto out; @@ -288,15 +288,9 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, btrfs_set_device_io_align(leaf, dev_item, device->io_align); btrfs_set_device_io_width(leaf, dev_item, device->io_width); btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); - btrfs_set_device_rdev(leaf, dev_item, device->rdev); - btrfs_set_device_partition(leaf, dev_item, device->partition); - btrfs_set_device_name_len(leaf, dev_item, device->name_len); btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); - ptr = (unsigned long)btrfs_device_name(dev_item); - write_extent_buffer(leaf, device->name, ptr, device->name_len); - ptr = (unsigned long)btrfs_device_uuid(dev_item); write_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); btrfs_mark_buffer_dirty(leaf); @@ -343,8 +337,6 @@ int btrfs_update_device(struct btrfs_trans_handle *trans, btrfs_set_device_io_align(leaf, dev_item, device->io_align); btrfs_set_device_io_width(leaf, dev_item, device->io_width); btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); - btrfs_set_device_rdev(leaf, dev_item, device->rdev); - btrfs_set_device_partition(leaf, dev_item, device->partition); btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); btrfs_mark_buffer_dirty(leaf); @@ -590,7 +582,6 @@ static int fill_device_from_item(struct extent_buffer *leaf, struct btrfs_device *device) { unsigned long ptr; - char *name; device->devid = btrfs_device_id(leaf, dev_item); device->total_bytes = btrfs_device_total_bytes(leaf, dev_item); @@ -599,24 +590,14 @@ static int fill_device_from_item(struct extent_buffer *leaf, device->io_align = btrfs_device_io_align(leaf, dev_item); device->io_width = btrfs_device_io_width(leaf, dev_item); device->sector_size = btrfs_device_sector_size(leaf, dev_item); - device->rdev = btrfs_device_rdev(leaf, dev_item); - device->partition = btrfs_device_partition(leaf, dev_item); - device->name_len = btrfs_device_name_len(leaf, dev_item); ptr = (unsigned long)btrfs_device_uuid(dev_item); read_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); - name = kmalloc(device->name_len + 1, GFP_NOFS); - if (!name) - return -ENOMEM; - device->name = name; - ptr = (unsigned long)btrfs_device_name(dev_item); - read_extent_buffer(leaf, name, ptr, device->name_len); - name[device->name_len] = '\0'; return 0; } -static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key, +static int read_one_dev(struct btrfs_root *root, struct extent_buffer *leaf, struct btrfs_dev_item *dev_item) { @@ -635,8 +616,7 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key, fill_device_from_item(leaf, dev_item, device); device->dev_root = root->fs_info->dev_root; - device->fd = 0; - memcpy(&device->dev_key, key, sizeof(*key)); + device->fd = root->fs_info->fp; ret = btrfs_open_device(device); if (ret) { kfree(device); @@ -644,12 +624,20 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key, return ret; } +int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf) +{ + struct btrfs_dev_item *dev_item; + + dev_item = (struct btrfs_dev_item *)offsetof(struct btrfs_super_block, + dev_item); + return read_one_dev(root, buf, dev_item); +} + int btrfs_read_sys_array(struct btrfs_root *root) { struct btrfs_super_block *super_copy = &root->fs_info->super_copy; struct extent_buffer *sb = root->fs_info->sb_buffer; struct btrfs_disk_key *disk_key; - struct btrfs_dev_item *dev_item; struct btrfs_chunk *chunk; struct btrfs_key key; u32 num_stripes; @@ -659,7 +647,6 @@ int btrfs_read_sys_array(struct btrfs_root *root) unsigned long sb_ptr; u32 cur; int ret; - int dev_only = 1; array_size = btrfs_super_sys_array_size(super_copy); @@ -668,7 +655,6 @@ int btrfs_read_sys_array(struct btrfs_root *root) * once for all of the chunks. This way there are device * structs filled in for every chunk */ -again: ptr = super_copy->sys_chunk_array; sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array); cur = 0; @@ -682,22 +668,10 @@ again: sb_ptr += len; cur += len; - if (key.objectid == BTRFS_DEV_ITEMS_OBJECTID && - key.type == BTRFS_DEV_ITEM_KEY) { - dev_item = (struct btrfs_dev_item *)sb_ptr; - if (dev_only) { - ret = read_one_dev(root, &key, sb, dev_item); - BUG_ON(ret); - } - len = sizeof(*dev_item); - len += btrfs_device_name_len(sb, dev_item); - } else if (key.type == BTRFS_CHUNK_ITEM_KEY) { - + if (key.type == BTRFS_CHUNK_ITEM_KEY) { chunk = (struct btrfs_chunk *)sb_ptr; - if (!dev_only) { - ret = read_one_chunk(root, &key, sb, chunk); - BUG_ON(ret); - } + ret = read_one_chunk(root, &key, sb, chunk); + BUG_ON(ret); num_stripes = btrfs_chunk_num_stripes(sb, chunk); len = btrfs_chunk_item_size(num_stripes); } else { @@ -707,10 +681,6 @@ again: sb_ptr += len; cur += len; } - if (dev_only == 1) { - dev_only = 0; - goto again; - } return 0; } @@ -757,8 +727,7 @@ again: struct btrfs_dev_item *dev_item; dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); - ret = read_one_dev(root, &found_key, leaf, - dev_item); + ret = read_one_dev(root, leaf, dev_item); BUG_ON(ret); } } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) { diff --git a/volumes.h b/volumes.h index 465bc771..760f2cde 100644 --- a/volumes.h +++ b/volumes.h @@ -21,7 +21,6 @@ struct btrfs_device { struct list_head dev_list; struct btrfs_root *dev_root; - struct btrfs_key dev_key; int fd; @@ -43,22 +42,11 @@ struct btrfs_device { /* minimal io size for this device */ u32 sector_size; - /* the kernel device number */ - u64 rdev; - /* type and info about this device */ u64 type; - /* partition number, 0 for whole dev */ - int partition; - - /* length of the name data at the end of the item */ - int name_len; - /* physical drive uuid (or lvm uuid) */ u8 uuid[BTRFS_DEV_UUID_SIZE]; - - char *name; }; int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, @@ -72,4 +60,5 @@ int btrfs_read_chunk_tree(struct btrfs_root *root); int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root, u64 *start, u64 *num_bytes, u64 type); +int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf); #endif -- cgit v1.2.3