From 0dcfa3b8270f38edacee1c62f308129c36073d0c Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 24 Mar 2008 15:05:44 -0400 Subject: Walk all block devices looking for btrfs --- Makefile | 23 +++---- btrfsctl.c | 15 ++++- ctree.h | 5 +- disk-io.c | 50 +++++++++------ disk-io.h | 4 +- extent-tree.c | 4 -- kerncompat.h | 2 + mkfs.c | 8 ++- utils.c | 123 +++++++++++++++++++++++++++++++++++++ utils.h | 4 ++ volumes.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ volumes.h | 24 ++++++++ 12 files changed, 393 insertions(+), 61 deletions(-) diff --git a/Makefile b/Makefile index ff7ddada..f74aafd8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS = -g -Werror objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ root-tree.o dir-item.o hash.o file-item.o inode-item.o \ inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \ - volumes.o + volumes.o utils.o # CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ -Wuninitialized -Wshadow -Wundef @@ -13,6 +13,7 @@ DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@ INSTALL= install prefix ?= /usr/local bindir = $(prefix)/bin +LIBS=-luuid progs = btrfsctl btrfsck mkfs.btrfs debug-tree @@ -30,26 +31,26 @@ endif all: $(progs) -btrfsctl: btrfsctl.o - gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(LDFLAGS) +btrfsctl: $(objects) btrfsctl.o + gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS) btrfsck: $(objects) btrfsck.o bit-radix.o - gcc $(CFLAGS) -o btrfsck btrfsck.o $(objects) bit-radix.o $(LDFLAGS) + gcc $(CFLAGS) -o btrfsck btrfsck.o $(objects) bit-radix.o $(LDFLAGS) $(LIBS) -mkfs.btrfs: $(objects) mkfs.o utils.o - gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o utils.o -luuid $(LDFLAGS) +mkfs.btrfs: $(objects) mkfs.o + gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o $(LDFLAGS) $(LIBS) debug-tree: $(objects) debug-tree.o - gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o -luuid $(LDFLAGS) + gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o $(LDFLAGS) $(LIBS) dir-test: $(objects) dir-test.o - gcc $(CFLAGS) -o dir-test $(objects) dir-test.o $(LDFLAGS) + gcc $(CFLAGS) -o dir-test $(objects) dir-test.o $(LDFLAGS) $(LIBS) quick-test: $(objects) quick-test.o - gcc $(CFLAGS) -o quick-test $(objects) quick-test.o $(LDFLAGS) + gcc $(CFLAGS) -o quick-test $(objects) quick-test.o $(LDFLAGS) $(LIBS) -convert: $(objects) convert.o utils.o - gcc $(CFLAGS) -o btrfs-convert $(objects) convert.o utils.o -luuid -lext2fs $(LDFLAGS) +convert: $(objects) convert.o + gcc $(CFLAGS) -o btrfs-convert $(objects) convert.o -lext2fs $(LDFLAGS) $(LIBS) clean : rm -f $(progs) cscope.out *.o .*.d btrfs-convert diff --git a/btrfsctl.c b/btrfsctl.c index 1518a13e..ae0dd654 100644 --- a/btrfsctl.c +++ b/btrfsctl.c @@ -29,6 +29,9 @@ #include #include #include "kerncompat.h" +#include "ctree.h" +#include "transaction.h" +#include "utils.h" #ifdef __CHECKER__ #define BLKGETSIZE64 0 @@ -47,7 +50,8 @@ void print_usage(void) printf("\t-s snap_name existing_subvol creates a new snapshot\n"); printf("\t-s snap_name tree_root creates a new subvolume\n"); printf("\t-r [+-]size[gkm] resize the FS\n"); - printf("\t-a device scans the device for a Btrfs filesystem\n"); + printf("\t-A device scans the device for a Btrfs filesystem\n"); + printf("\t-a scans all devices for a Btrfs filesystems\n"); exit(1); } @@ -64,6 +68,11 @@ int main(int ac, char **av) unsigned long command = 0; int len; + if (ac == 2 && strcmp(av[1], "-a") == 0) { + fprintf(stderr, "Scanning for Btrfs filesystems\n"); + btrfs_scan_one_dir("/dev", 1); + exit(0); + } for (i = 1; i < ac - 1; i++) { if (strcmp(av[i], "-s") == 0) { if (i + 1 >= ac - 1) { @@ -89,9 +98,9 @@ int main(int ac, char **av) print_usage(); } command = BTRFS_IOC_DEFRAG; - } else if (strcmp(av[i], "-a") == 0) { + } else if (strcmp(av[i], "-A") == 0) { if (i >= ac - 1) { - fprintf(stderr, "-a requires an arg\n"); + fprintf(stderr, "-A requires an arg\n"); print_usage(); } command = BTRFS_IOC_SCAN_DEV; diff --git a/ctree.h b/ctree.h index 55d2961d..5ce7df03 100644 --- a/ctree.h +++ b/ctree.h @@ -27,7 +27,7 @@ struct btrfs_root; struct btrfs_trans_handle; -#define BTRFS_MAGIC "_B4RfS_M" +#define BTRFS_MAGIC "_B5RfS_M" #define BTRFS_MAX_LEVEL 8 @@ -437,6 +437,7 @@ struct btrfs_extent_ops { }; struct btrfs_device; +struct btrfs_fs_devices; struct btrfs_fs_info { u8 fsid[BTRFS_FSID_SIZE]; struct btrfs_root *fs_root; @@ -466,7 +467,7 @@ struct btrfs_fs_info { struct btrfs_extent_ops *extent_ops; struct list_head dirty_cowonly_roots; - struct list_head devices; + struct btrfs_fs_devices *fs_devices; struct list_head space_info; int fp; int force_system_allocs; diff --git a/disk-io.c b/disk-io.c index ce801bf1..1afe5a6e 100644 --- a/disk-io.c +++ b/disk-io.c @@ -31,11 +31,7 @@ #include "volumes.h" #include "transaction.h" #include "crc32c.h" - -int btrfs_open_device(struct btrfs_device *dev) -{ - return 0; -} +#include "utils.h" int btrfs_map_bh_to_logical(struct btrfs_root *root, struct extent_buffer *buf, u64 logical) @@ -394,7 +390,7 @@ insert: return root; } -struct btrfs_root *open_ctree(char *filename, u64 sb_bytenr) +struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr) { int fp; @@ -402,10 +398,10 @@ struct btrfs_root *open_ctree(char *filename, u64 sb_bytenr) if (fp < 0) { return NULL; } - return open_ctree_fd(fp, sb_bytenr); + return open_ctree_fd(fp, filename, sb_bytenr); } -struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) +struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr) { u32 sectorsize; u32 nodesize; @@ -420,11 +416,28 @@ struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); int ret; struct btrfs_super_block *disk_super; + struct btrfs_fs_devices *fs_devices = NULL; + u64 total_devs; if (sb_bytenr == 0) sb_bytenr = BTRFS_SUPER_INFO_OFFSET; - fs_info->fp = fp; + ret = btrfs_scan_one_device(fp, path, &fs_devices, + &total_devs, sb_bytenr); + + if (ret) { + fprintf(stderr, "No valid Btrfs found on %s\n", path); + return NULL; + } + fprintf(stderr, "found Btrfs on %s with %Lu devices\n", path, + total_devs); + + if (total_devs != 1) { + ret = btrfs_scan_for_fsid(fs_devices, total_devs, 1); + BUG_ON(ret); + } + + fs_info->fp = fs_devices->lowest_bdev; fs_info->running_transaction = NULL; fs_info->fs_root = root; fs_info->tree_root = tree_root; @@ -445,17 +458,20 @@ struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) cache_tree_init(&fs_info->mapping_tree.cache_tree); mutex_init(&fs_info->fs_mutex); + fs_info->fs_devices = fs_devices; INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); - INIT_LIST_HEAD(&fs_info->devices); INIT_LIST_HEAD(&fs_info->space_info); __setup_root(4096, 4096, 4096, 4096, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); + ret = btrfs_open_devices(fs_devices, O_RDWR); + BUG_ON(ret); + fs_info->sb_buffer = btrfs_find_create_tree_block(tree_root, sb_bytenr, 4096); BUG_ON(!fs_info->sb_buffer); - fs_info->sb_buffer->fd = fp; + fs_info->sb_buffer->fd = fs_devices->lowest_bdev; fs_info->sb_buffer->dev_bytenr = sb_bytenr; ret = read_extent_from_disk(fs_info->sb_buffer); BUG_ON(ret); @@ -484,7 +500,6 @@ struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) 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, @@ -492,11 +507,13 @@ struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr) __setup_root(nodesize, leafsize, sectorsize, stripesize, chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); + chunk_root->node = read_tree_block(chunk_root, btrfs_super_chunk_root(disk_super), blocksize); BUG_ON(!chunk_root->node); + ret = btrfs_read_chunk_tree(chunk_root); BUG_ON(ret); @@ -557,13 +574,12 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) struct list_head *next; struct btrfs_device *device; - list = &fs_info->devices; - while(!list_empty(list)) { - next = list->next; - list_del(next); + return 0; + + list = &fs_info->fs_devices->devices; + list_for_each(next, list) { device = list_entry(next, struct btrfs_device, dev_list); // close(device->fd); - kfree(device); } return 0; } diff --git a/disk-io.h b/disk-io.h index a4572841..f680721a 100644 --- a/disk-io.h +++ b/disk-io.h @@ -29,8 +29,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize); int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf); -struct btrfs_root *open_ctree(char *filename, u64 sb_bytenr); -struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr); +struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr); +struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr); int close_ctree(struct btrfs_root *root); int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root); diff --git a/extent-tree.c b/extent-tree.c index ec1a37ad..3b5d2b6e 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -356,10 +356,6 @@ again: found_group = cache; goto found; } - if (full_search) { - printk("failed on cache %Lu used %Lu total %Lu\n", - cache->key.objectid, used, cache->key.offset); - } cond_resched(); } if (!full_search) { diff --git a/kerncompat.h b/kerncompat.h index 8536832d..c7aee684 100644 --- a/kerncompat.h +++ b/kerncompat.h @@ -189,6 +189,8 @@ static inline long IS_ERR(const void *ptr) * kmalloc/kfree */ #define kmalloc(x, y) malloc(x) +#define kzalloc(x, y) calloc(1, x) +#define kstrdup(x, y) strdup(x) #define kfree(x) free(x) #define BUG_ON(c) do { if (c) abort(); } while (0) diff --git a/mkfs.c b/mkfs.c index 6de35cc6..49f73083 100644 --- a/mkfs.c +++ b/mkfs.c @@ -59,7 +59,7 @@ static u64 parse_size(char *s) return atol(s) * mult; } -static int make_root_dir(int fd) { +static int make_root_dir(int fd, const char *device_name) { struct btrfs_root *root; struct btrfs_trans_handle *trans; struct btrfs_key location; @@ -68,7 +68,7 @@ static int make_root_dir(int fd) { u64 chunk_size = 0; int ret; - root = open_ctree_fd(fd, 0); + root = open_ctree_fd(fd, device_name, 0); if (!root) { fprintf(stderr, "ctree init failed\n"); @@ -217,7 +217,7 @@ int main(int ac, char **av) fprintf(stderr, "error during mkfs %d\n", ret); exit(1); } - ret = make_root_dir(fd); + ret = make_root_dir(fd, file); if (ret) { fprintf(stderr, "failed to setup the root directory\n"); exit(1); @@ -229,6 +229,7 @@ int main(int ac, char **av) if (ac == 0) goto done; + btrfs_register_one_device(file); root = open_ctree(file, 0); if (!root) { @@ -255,6 +256,7 @@ int main(int ac, char **av) sectorsize, sectorsize, sectorsize); BUG_ON(ret); close(fd); + btrfs_register_one_device(file); } btrfs_commit_transaction(trans, root); ret = close_ctree(root); diff --git a/utils.c b/utils.c index 80d1d036..0a067e6b 100644 --- a/utils.c +++ b/utils.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "kerncompat.h" @@ -37,6 +38,7 @@ #include "crc32c.h" #include "utils.h" #include "volumes.h" +#include "ioctl.h" #ifdef __CHECKER__ #define BLKGETSIZE64 0 @@ -522,3 +524,124 @@ int btrfs_make_root_dir(struct btrfs_trans_handle *trans, error: return ret; } + +struct pending_dir { + struct list_head list; + char name[256]; +}; + +int btrfs_register_one_device(char *fname) +{ + struct btrfs_ioctl_vol_args args; + int fd; + int ret; + + fd = open("/dev/btrfs-control", O_RDONLY); + if (fd < 0) + return -EINVAL; + strcpy(args.name, fname); + ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args); + close(fd); + return ret; +} + +int btrfs_scan_one_dir(char *dirname, int run_ioctl) +{ + DIR *dirp; + struct dirent *dirent; + struct pending_dir *pending; + struct stat st; + int ret; + int fd; + int dirname_len; + int pathlen; + char *fullpath; + struct list_head pending_list; + struct btrfs_fs_devices *tmp_devices; + u64 num_devices; + + INIT_LIST_HEAD(&pending_list); + + pending = malloc(sizeof(*pending)); + if (!pending) + return -ENOMEM; + strcpy(pending->name, dirname); + +again: + dirname_len = strlen(pending->name); + pathlen = 1024; + fullpath = malloc(pathlen); + dirname = pending->name; + + if (!fullpath) { + ret = -ENOMEM; + goto fail; + } + dirp = opendir(dirname); + if (!dirp) { + fprintf(stderr, "Unable to open /sys/block for scanning\n"); + return -ENOENT; + } + while(1) { + dirent = readdir(dirp); + if (!dirent) + break; + if (dirent->d_name[0] == '.') + continue; + if (dirname_len + strlen(dirent->d_name) + 2 > pathlen) { + ret = -EFAULT; + goto fail; + } + snprintf(fullpath, pathlen, "%s/%s", dirname, dirent->d_name); + ret = lstat(fullpath, &st); + if (ret < 0) { + fprintf(stderr, "failed to stat %s\n", fullpath); + continue; + } + if (S_ISLNK(st.st_mode)) + continue; + if (S_ISDIR(st.st_mode)) { + struct pending_dir *next = malloc(sizeof(*next)); + if (!next) { + ret = -ENOMEM; + goto fail; + } + strcpy(next->name, fullpath); + list_add_tail(&next->list, &pending_list); + } + if (!S_ISBLK(st.st_mode)) { + continue; + } + fd = open(fullpath, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "failed to read %s\n", fullpath); + continue; + } + ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices, + &num_devices, + BTRFS_SUPER_INFO_OFFSET); + if (ret == 0 && run_ioctl > 0) { + btrfs_register_one_device(fullpath); + } + close(fd); + } + if (!list_empty(&pending_list)) { + free(pending); + pending = list_entry(pending_list.next, struct pending_dir, + list); + list_del(&pending->list); + closedir(dirp); + goto again; + } + ret = 0; +fail: + free(pending); + closedir(dirp); + return ret; +} + +int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 total_devs, + int run_ioctls) +{ + return btrfs_scan_one_dir("/dev", run_ioctls); +} diff --git a/utils.h b/utils.h index 28e71e3d..eacfaacc 100644 --- a/utils.h +++ b/utils.h @@ -31,4 +31,8 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, struct btrfs_root *root, int fd, u64 block_count, u32 io_width, u32 io_align, u32 sectorsize); +int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 total_devs, + int run_ioctls); +int btrfs_register_one_device(char *fname); +int btrfs_scan_one_dir(char *dirname, int run_ioctl); #endif diff --git a/volumes.c b/volumes.c index 59664b4d..f68bbeae 100644 --- a/volumes.c +++ b/volumes.c @@ -15,6 +15,15 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ +#define _XOPEN_SOURCE 600 +#define __USE_XOPEN2K +#include +#include +#include +#include +#include +#include +#include #include "ctree.h" #include "disk-io.h" #include "transaction.h" @@ -26,6 +35,160 @@ struct map_lookup { struct btrfs_device *dev; u64 physical; }; +static LIST_HEAD(fs_uuids); + +static struct btrfs_device *__find_device(struct list_head *head, u64 devid) +{ + struct btrfs_device *dev; + struct list_head *cur; + + list_for_each(cur, head) { + dev = list_entry(cur, struct btrfs_device, dev_list); + if (dev->devid == devid) + return dev; + } + return NULL; +} + +static struct btrfs_fs_devices *find_fsid(u8 *fsid) +{ + struct list_head *cur; + struct btrfs_fs_devices *fs_devices; + + list_for_each(cur, &fs_uuids) { + fs_devices = list_entry(cur, struct btrfs_fs_devices, list); + if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0) + return fs_devices; + } + return NULL; +} + +static int device_list_add(const char *path, + struct btrfs_super_block *disk_super, + u64 devid, struct btrfs_fs_devices **fs_devices_ret) +{ + struct btrfs_device *device; + struct btrfs_fs_devices *fs_devices; + u64 found_transid = btrfs_super_generation(disk_super); + + fs_devices = find_fsid(disk_super->fsid); + if (!fs_devices) { + fs_devices = kmalloc(sizeof(*fs_devices), GFP_NOFS); + if (!fs_devices) + return -ENOMEM; + INIT_LIST_HEAD(&fs_devices->devices); + list_add(&fs_devices->list, &fs_uuids); + memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE); + fs_devices->latest_devid = devid; + fs_devices->latest_trans = found_transid; + fs_devices->lowest_devid = (u64)-1; + device = NULL; + } else { + device = __find_device(&fs_devices->devices, devid); + } + if (!device) { + device = kzalloc(sizeof(*device), GFP_NOFS); + if (!device) { + /* we can safely leave the fs_devices entry around */ + return -ENOMEM; + } + device->devid = devid; + device->name = kstrdup(path, GFP_NOFS); + if (!device->name) { + kfree(device); + return -ENOMEM; + } + list_add(&device->dev_list, &fs_devices->devices); + } + + if (found_transid > fs_devices->latest_trans) { + fs_devices->latest_devid = devid; + fs_devices->latest_trans = found_transid; + } + if (fs_devices->lowest_devid > devid) { + fs_devices->lowest_devid = devid; + printk("lowest devid now %Lu\n", devid); + } + *fs_devices_ret = fs_devices; + return 0; +} + +int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) +{ + struct list_head *head = &fs_devices->devices; + struct list_head *cur; + struct btrfs_device *device; + + list_for_each(cur, head) { + device = list_entry(cur, struct btrfs_device, dev_list); + device->fd = 0; + } + return 0; +} + +int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags) +{ + int fd; + struct list_head *head = &fs_devices->devices; + struct list_head *cur; + struct btrfs_device *device; + int ret; + + list_for_each(cur, head) { + device = list_entry(cur, struct btrfs_device, dev_list); + fd = open(device->name, flags); +printk("opening %s devid %Lu fd %d\n", device->name, device->devid, fd); + if (fd < 0) { + ret = -errno; + goto fail; + } + if (device->devid == fs_devices->latest_devid) + fs_devices->latest_bdev = fd; + if (device->devid == fs_devices->lowest_devid) + fs_devices->lowest_bdev = fd; + device->fd = fd; + } + return 0; +fail: + btrfs_close_devices(fs_devices); + return ret; +} + +int btrfs_scan_one_device(int fd, const char *path, + struct btrfs_fs_devices **fs_devices_ret, + u64 *total_devs, u64 super_offset) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret; + u64 devid; + + buf = malloc(4096); + if (!buf) { + ret = -ENOMEM; + goto error; + } + ret = pread(fd, buf, 4096, super_offset); + if (ret != 4096) { + ret = -EIO; + goto error; + } + disk_super = (struct btrfs_super_block *)buf; + if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, + sizeof(disk_super->magic))) { + ret = -ENOENT; + goto error_brelse; + } + devid = le64_to_cpu(disk_super->dev_item.devid); + *total_devs = btrfs_super_num_devices(disk_super); + printk("found device %Lu on %s\n", devid, path); + ret = device_list_add(path, disk_super, devid, fs_devices_ret); + +error_brelse: + free(buf); +error: + return ret; +} /* * this uses a pretty simple search, the expectation is that it is @@ -301,6 +464,7 @@ out: btrfs_free_path(path); return ret; } + int btrfs_update_device(struct btrfs_trans_handle *trans, struct btrfs_device *device) { @@ -381,11 +545,11 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, struct btrfs_device *device = NULL; struct btrfs_chunk *chunk; struct list_head private_devs; - struct list_head *dev_list = &extent_root->fs_info->devices; + struct list_head *dev_list = &extent_root->fs_info->fs_devices->devices; struct list_head *cur; struct map_lookup *map; u64 physical; - u64 calc_size = 1024 * 1024 * 1024; + u64 calc_size = 128 * 1024 * 1024; u64 avail; u64 max_avail = 0; int num_stripes = 1; @@ -446,7 +610,7 @@ again: key.objectid, calc_size, &dev_offset); BUG_ON(ret); - +printk("alloc chunk size %Lu from dev %Lu\n", calc_size, device->devid); device->bytes_used += calc_size; ret = btrfs_update_device(trans, device); BUG_ON(ret); @@ -523,17 +687,9 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid) { - struct btrfs_device *dev; - struct list_head *cur = root->fs_info->devices.next; - struct list_head *head = &root->fs_info->devices; + struct list_head *head = &root->fs_info->fs_devices->devices; - while(cur != head) { - dev = list_entry(cur, struct btrfs_device, dev_list); - if (dev->devid == devid) - return dev; - cur = cur->next; - } - return NULL; + return __find_device(head, devid); } static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, @@ -565,6 +721,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, map->ce.size = length; map->physical = btrfs_stripe_offset_nr(leaf, chunk, 0); + devid = btrfs_stripe_devid_nr(leaf, chunk, 0); map->dev = btrfs_find_device(root, devid); @@ -609,19 +766,16 @@ static int read_one_dev(struct btrfs_root *root, devid = btrfs_device_id(leaf, dev_item); device = btrfs_find_device(root, devid); if (!device) { + printk("warning devid %Lu not found already\n", devid); device = kmalloc(sizeof(*device), GFP_NOFS); if (!device) return -ENOMEM; - list_add(&device->dev_list, &root->fs_info->devices); + list_add(&device->dev_list, + &root->fs_info->fs_devices->devices); } fill_device_from_item(leaf, dev_item, device); device->dev_root = root->fs_info->dev_root; - device->fd = root->fs_info->fp; - ret = btrfs_open_device(device); - if (ret) { - kfree(device); - } return ret; } diff --git a/volumes.h b/volumes.h index c585b15d..ae9e7bb7 100644 --- a/volumes.h +++ b/volumes.h @@ -24,6 +24,8 @@ struct btrfs_device { int fd; + char *name; + /* the internal btrfs device id */ u64 devid; @@ -49,6 +51,19 @@ struct btrfs_device { u8 uuid[BTRFS_DEV_UUID_SIZE]; }; +struct btrfs_fs_devices { + u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ + + /* the device with this id has the most recent coyp of the super */ + u64 latest_devid; + u64 latest_trans; + u64 lowest_devid; + int latest_bdev; + int lowest_bdev; + struct list_head devices; + struct list_head list; +}; + int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, u64 owner, u64 num_bytes, u64 *start); @@ -64,4 +79,13 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf); int btrfs_add_device(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_device *device); +int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, + int flags); +int btrfs_close_devices(struct btrfs_fs_devices *fs_devices); +int btrfs_add_device(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_device *device); +int btrfs_scan_one_device(int fd, const char *path, + struct btrfs_fs_devices **fs_devices_ret, + u64 *total_devs, u64 super_offset); #endif -- cgit v1.2.3