From a62b7854de0f14ffc2e4571432215f8215ea7249 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 2 Jul 2019 00:42:23 +0200 Subject: [PATCH] btrfs-progs: utils: split device scanning functions to own file All helpers and data structures that are used for device registration. Signed-off-by: David Sterba --- Makefile | 2 +- cmds/device.c | 1 + cmds/filesystem.c | 1 + cmds/inspect-dump-tree.c | 1 + cmds/subvolume.c | 1 + common/device-scan.c | 408 +++++++++++++++++++++++++++++++++++++++ common/device-scan.h | 46 +++++ common/utils.c | 371 +---------------------------------- common/utils.h | 34 ---- disk-io.c | 1 + mkfs/main.c | 1 + 11 files changed, 462 insertions(+), 405 deletions(-) create mode 100644 common/device-scan.c create mode 100644 common/device-scan.h diff --git a/Makefile b/Makefile index e810383f..3ed445e7 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ objects = ctree.o disk-io.o kernel-lib/radix-tree.o extent-tree.o print-tree.o \ inode.o file.o find-root.o free-space-tree.o common/help.o send-dump.o \ common/fsfeatures.o kernel-lib/tables.o kernel-lib/raid56.o transaction.o \ delayed-ref.o common/format-output.o common/path-utils.o \ - common/device-utils.o + common/device-utils.o common/device-scan.o cmds_objects = cmds/subvolume.o cmds/filesystem.o cmds/device.o cmds/scrub.o \ cmds/inspect.o cmds/balance.o cmds/send.o cmds/receive.o \ cmds/quota.o cmds/qgroup.o cmds/replace.o check/main.o \ diff --git a/cmds/device.c b/cmds/device.c index b364ff80..24158308 100644 --- a/cmds/device.c +++ b/cmds/device.c @@ -35,6 +35,7 @@ #include "common/help.h" #include "common/path-utils.h" #include "common/device-utils.h" +#include "common/device-scan.h" #include "mkfs/common.h" static const char * const device_cmd_group_usage[] = { diff --git a/cmds/filesystem.c b/cmds/filesystem.c index 44a5da73..4f22089a 100644 --- a/cmds/filesystem.c +++ b/cmds/filesystem.c @@ -42,6 +42,7 @@ #include "common/help.h" #include "common/fsfeatures.h" #include "common/path-utils.h" +#include "common/device-scan.h" /* * for btrfs fi show, we maintain a hash of fsids we've already printed. diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c index 6b202a54..b02aacc8 100644 --- a/cmds/inspect-dump-tree.c +++ b/cmds/inspect-dump-tree.c @@ -32,6 +32,7 @@ #include "cmds/commands.h" #include "common/utils.h" #include "common/help.h" +#include "common/device-scan.h" static void print_extents(struct extent_buffer *eb) { diff --git a/cmds/subvolume.c b/cmds/subvolume.c index ff0ef2f3..7a5fd79b 100644 --- a/cmds/subvolume.c +++ b/cmds/subvolume.c @@ -41,6 +41,7 @@ #include "btrfs-list.h" #include "common/help.h" #include "common/path-utils.h" +#include "common/device-scan.h" static int wait_for_subvolume_cleaning(int fd, size_t count, uint64_t *ids, int sleep_interval) diff --git a/common/device-scan.c b/common/device-scan.c new file mode 100644 index 00000000..2c5ae225 --- /dev/null +++ b/common/device-scan.c @@ -0,0 +1,408 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "kerncompat.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/path-utils.h" +#include "common/device-scan.h" +#include "common/messages.h" +#include "common/utils.h" +#include "common-defs.h" +#include "ctree.h" +#include "volumes.h" +#include "disk-io.h" +#include "ioctl.h" + +static int btrfs_scan_done = 0; + +/* + * This function checks if the given input parameter is + * an uuid or a path + * return <0 : some error in the given input + * return BTRFS_ARG_UNKNOWN: unknown input + * return BTRFS_ARG_UUID: given input is uuid + * return BTRFS_ARG_MNTPOINT: given input is path + * return BTRFS_ARG_REG: given input is regular file + * return BTRFS_ARG_BLKDEV: given input is block device + */ +int check_arg_type(const char *input) +{ + uuid_t uuid; + char path[PATH_MAX]; + + if (!input) + return -EINVAL; + + if (realpath(input, path)) { + if (path_is_block_device(path) == 1) + return BTRFS_ARG_BLKDEV; + + if (path_is_mount_point(path) == 1) + return BTRFS_ARG_MNTPOINT; + + if (path_is_reg_file(path)) + return BTRFS_ARG_REG; + + return BTRFS_ARG_UNKNOWN; + } else { + return -errno; + } + + if (strlen(input) == (BTRFS_UUID_UNPARSED_SIZE - 1) && + !uuid_parse(input, uuid)) + return BTRFS_ARG_UUID; + + return BTRFS_ARG_UNKNOWN; +} + +int test_uuid_unique(char *fs_uuid) +{ + int unique = 1; + blkid_dev_iterate iter = NULL; + blkid_dev dev = NULL; + blkid_cache cache = NULL; + + if (blkid_get_cache(&cache, NULL) < 0) { + printf("ERROR: lblkid cache get failed\n"); + return 1; + } + blkid_probe_all(cache); + iter = blkid_dev_iterate_begin(cache); + blkid_dev_set_search(iter, "UUID", fs_uuid); + + while (blkid_dev_next(iter, &dev) == 0) { + dev = blkid_verify(cache, dev); + if (dev) { + unique = 0; + break; + } + } + + blkid_dev_iterate_end(iter); + blkid_put_cache(cache); + + return unique; +} + +int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, + struct btrfs_root *root, int fd, const char *path, + u64 device_total_bytes, u32 io_width, u32 io_align, + u32 sectorsize) +{ + struct btrfs_super_block *disk_super; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_super_block *super = fs_info->super_copy; + struct btrfs_device *device; + struct btrfs_dev_item *dev_item; + char *buf = NULL; + u64 fs_total_bytes; + u64 num_devs; + int ret; + + device_total_bytes = (device_total_bytes / sectorsize) * sectorsize; + + device = calloc(1, sizeof(*device)); + if (!device) { + ret = -ENOMEM; + goto out; + } + buf = calloc(1, sectorsize); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + disk_super = (struct btrfs_super_block *)buf; + dev_item = &disk_super->dev_item; + + uuid_generate(device->uuid); + device->devid = 0; + device->type = 0; + device->io_width = io_width; + device->io_align = io_align; + device->sector_size = sectorsize; + device->fd = fd; + device->writeable = 1; + device->total_bytes = device_total_bytes; + device->bytes_used = 0; + device->total_ios = 0; + device->dev_root = fs_info->dev_root; + device->name = strdup(path); + if (!device->name) { + ret = -ENOMEM; + goto out; + } + + INIT_LIST_HEAD(&device->dev_list); + ret = btrfs_add_device(trans, fs_info, device); + if (ret) + goto out; + + fs_total_bytes = btrfs_super_total_bytes(super) + device_total_bytes; + btrfs_set_super_total_bytes(super, fs_total_bytes); + + num_devs = btrfs_super_num_devices(super) + 1; + btrfs_set_super_num_devices(super, num_devs); + + memcpy(disk_super, super, sizeof(*disk_super)); + + btrfs_set_super_bytenr(disk_super, BTRFS_SUPER_INFO_OFFSET); + btrfs_set_stack_device_id(dev_item, device->devid); + btrfs_set_stack_device_type(dev_item, device->type); + btrfs_set_stack_device_io_align(dev_item, device->io_align); + btrfs_set_stack_device_io_width(dev_item, device->io_width); + btrfs_set_stack_device_sector_size(dev_item, device->sector_size); + btrfs_set_stack_device_total_bytes(dev_item, device->total_bytes); + btrfs_set_stack_device_bytes_used(dev_item, device->bytes_used); + memcpy(&dev_item->uuid, device->uuid, BTRFS_UUID_SIZE); + + ret = pwrite(fd, buf, sectorsize, BTRFS_SUPER_INFO_OFFSET); + BUG_ON(ret != sectorsize); + + free(buf); + list_add(&device->dev_list, &fs_info->fs_devices->devices); + device->fs_devices = fs_info->fs_devices; + return 0; + +out: + free(device); + free(buf); + return ret; +} + +int btrfs_register_one_device(const char *fname) +{ + struct btrfs_ioctl_vol_args args; + int fd; + int ret; + + fd = open("/dev/btrfs-control", O_RDWR); + if (fd < 0) { + warning( + "failed to open /dev/btrfs-control, skipping device registration: %m"); + return -errno; + } + memset(&args, 0, sizeof(args)); + strncpy_null(args.name, fname); + ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args); + if (ret < 0) { + error("device scan failed on '%s': %m", fname); + ret = -errno; + } + close(fd); + return ret; +} + +/* + * Register all devices in the fs_uuid list created in the user + * space. Ensure btrfs_scan_devices() is called before this func. + */ +int btrfs_register_all_devices(void) +{ + int err = 0; + int ret = 0; + struct btrfs_fs_devices *fs_devices; + struct btrfs_device *device; + struct list_head *all_uuids; + + all_uuids = btrfs_scanned_uuids(); + + list_for_each_entry(fs_devices, all_uuids, list) { + list_for_each_entry(device, &fs_devices->devices, dev_list) { + if (*device->name) + err = btrfs_register_one_device(device->name); + + if (err) + ret++; + } + } + + return ret; +} + +int btrfs_device_already_in_root(struct btrfs_root *root, int fd, + int super_offset) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret = 0; + + buf = malloc(BTRFS_SUPER_INFO_SIZE); + if (!buf) { + ret = -ENOMEM; + goto out; + } + ret = pread(fd, buf, BTRFS_SUPER_INFO_SIZE, super_offset); + if (ret != BTRFS_SUPER_INFO_SIZE) + goto brelse; + + ret = 0; + disk_super = (struct btrfs_super_block *)buf; + /* + * Accept devices from the same filesystem, allow partially created + * structures. + */ + if (btrfs_super_magic(disk_super) != BTRFS_MAGIC && + btrfs_super_magic(disk_super) != BTRFS_MAGIC_TEMPORARY) + goto brelse; + + if (!memcmp(disk_super->fsid, root->fs_info->super_copy->fsid, + BTRFS_FSID_SIZE)) + ret = 1; +brelse: + free(buf); +out: + return ret; +} + +int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]) +{ + u8 hash = fsid[0]; + int slot = hash % SEEN_FSID_HASH_SIZE; + struct seen_fsid *seen = seen_fsid_hash[slot]; + + while (seen) { + if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) + return 1; + + seen = seen->next; + } + + return 0; +} + +int add_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[], + int fd, DIR *dirstream) +{ + u8 hash = fsid[0]; + int slot = hash % SEEN_FSID_HASH_SIZE; + struct seen_fsid *seen = seen_fsid_hash[slot]; + struct seen_fsid *alloc; + + if (!seen) + goto insert; + + while (1) { + if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) + return -EEXIST; + + if (!seen->next) + break; + + seen = seen->next; + } + +insert: + alloc = malloc(sizeof(*alloc)); + if (!alloc) + return -ENOMEM; + + alloc->next = NULL; + memcpy(alloc->fsid, fsid, BTRFS_FSID_SIZE); + alloc->fd = fd; + alloc->dirstream = dirstream; + + if (seen) + seen->next = alloc; + else + seen_fsid_hash[slot] = alloc; + + return 0; +} + +void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]) +{ + int slot; + struct seen_fsid *seen; + struct seen_fsid *next; + + for (slot = 0; slot < SEEN_FSID_HASH_SIZE; slot++) { + seen = seen_fsid_hash[slot]; + while (seen) { + next = seen->next; + close_file_or_dir(seen->fd, seen->dirstream); + free(seen); + seen = next; + } + seen_fsid_hash[slot] = NULL; + } +} + +int btrfs_scan_devices(void) +{ + int fd = -1; + int ret; + u64 num_devices; + struct btrfs_fs_devices *tmp_devices; + blkid_dev_iterate iter = NULL; + blkid_dev dev = NULL; + blkid_cache cache = NULL; + char path[PATH_MAX]; + + if (btrfs_scan_done) + return 0; + + ret = blkid_get_cache(&cache, NULL); + if (ret < 0) { + errno = -ret; + error("blkid cache get failed: %m"); + return ret; + } + blkid_probe_all(cache); + iter = blkid_dev_iterate_begin(cache); + blkid_dev_set_search(iter, "TYPE", "btrfs"); + while (blkid_dev_next(iter, &dev) == 0) { + dev = blkid_verify(cache, dev); + if (!dev) + continue; + /* if we are here its definitely a btrfs disk*/ + strncpy_null(path, blkid_dev_devname(dev)); + + fd = open(path, O_RDONLY); + if (fd < 0) { + error("cannot open %s: %m", path); + continue; + } + ret = btrfs_scan_one_device(fd, path, &tmp_devices, + &num_devices, BTRFS_SUPER_INFO_OFFSET, + SBREAD_DEFAULT); + if (ret) { + errno = -ret; + error("cannot scan %s: %m", path); + close (fd); + continue; + } + + close(fd); + } + blkid_dev_iterate_end(iter); + blkid_put_cache(cache); + + btrfs_scan_done = 1; + + return 0; +} + diff --git a/common/device-scan.h b/common/device-scan.h new file mode 100644 index 00000000..eda2bae5 --- /dev/null +++ b/common/device-scan.h @@ -0,0 +1,46 @@ +#ifndef __DEVICE_SCAN_H__ +#define __DEVICE_SCAN_H__ + +#include "kerncompat.h" +#include "ioctl.h" + +#define BTRFS_SCAN_MOUNTED (1ULL << 0) +#define BTRFS_SCAN_LBLKID (1ULL << 1) + +#define BTRFS_UPDATE_KERNEL 1 + +#define BTRFS_ARG_UNKNOWN 0 +#define BTRFS_ARG_MNTPOINT 1 +#define BTRFS_ARG_UUID 2 +#define BTRFS_ARG_BLKDEV 3 +#define BTRFS_ARG_REG 4 + +#define SEEN_FSID_HASH_SIZE 256 + +struct btrfs_root; +struct btrfs_trans_handle; +struct seen_fsid; +struct DIR; + +struct seen_fsid { + u8 fsid[BTRFS_FSID_SIZE]; + struct seen_fsid *next; + DIR *dirstream; + int fd; +}; + +int btrfs_scan_devices(void); +int btrfs_register_one_device(const char *fname); +int btrfs_register_all_devices(void); +int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, + struct btrfs_root *root, int fd, const char *path, + u64 device_total_bytes, u32 io_width, u32 io_align, + u32 sectorsize); +int btrfs_device_already_in_root(struct btrfs_root *root, int fd, + int super_offset); +int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]); +int add_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[], + int fd, DIR *dirstream); +void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]); + +#endif diff --git a/common/utils.c b/common/utils.c index 159689c1..ad938409 100644 --- a/common/utils.c +++ b/common/utils.c @@ -50,133 +50,17 @@ #include "kernel-lib/crc32c.h" #include "common/utils.h" #include "common/path-utils.h" +#include "common/device-scan.h" #include "volumes.h" #include "ioctl.h" #include "cmds/commands.h" #include "mkfs/common.h" -static int btrfs_scan_done = 0; - static int rand_seed_initialized = 0; static unsigned short rand_seed[3]; struct btrfs_config bconf; -int test_uuid_unique(char *fs_uuid) -{ - int unique = 1; - blkid_dev_iterate iter = NULL; - blkid_dev dev = NULL; - blkid_cache cache = NULL; - - if (blkid_get_cache(&cache, NULL) < 0) { - printf("ERROR: lblkid cache get failed\n"); - return 1; - } - blkid_probe_all(cache); - iter = blkid_dev_iterate_begin(cache); - blkid_dev_set_search(iter, "UUID", fs_uuid); - - while (blkid_dev_next(iter, &dev) == 0) { - dev = blkid_verify(cache, dev); - if (dev) { - unique = 0; - break; - } - } - - blkid_dev_iterate_end(iter); - blkid_put_cache(cache); - - return unique; -} - -int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int fd, const char *path, - u64 device_total_bytes, u32 io_width, u32 io_align, - u32 sectorsize) -{ - struct btrfs_super_block *disk_super; - struct btrfs_fs_info *fs_info = root->fs_info; - struct btrfs_super_block *super = fs_info->super_copy; - struct btrfs_device *device; - struct btrfs_dev_item *dev_item; - char *buf = NULL; - u64 fs_total_bytes; - u64 num_devs; - int ret; - - device_total_bytes = (device_total_bytes / sectorsize) * sectorsize; - - device = calloc(1, sizeof(*device)); - if (!device) { - ret = -ENOMEM; - goto out; - } - buf = calloc(1, sectorsize); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - disk_super = (struct btrfs_super_block *)buf; - dev_item = &disk_super->dev_item; - - uuid_generate(device->uuid); - device->devid = 0; - device->type = 0; - device->io_width = io_width; - device->io_align = io_align; - device->sector_size = sectorsize; - device->fd = fd; - device->writeable = 1; - device->total_bytes = device_total_bytes; - device->bytes_used = 0; - device->total_ios = 0; - device->dev_root = fs_info->dev_root; - device->name = strdup(path); - if (!device->name) { - ret = -ENOMEM; - goto out; - } - - INIT_LIST_HEAD(&device->dev_list); - ret = btrfs_add_device(trans, fs_info, device); - if (ret) - goto out; - - fs_total_bytes = btrfs_super_total_bytes(super) + device_total_bytes; - btrfs_set_super_total_bytes(super, fs_total_bytes); - - num_devs = btrfs_super_num_devices(super) + 1; - btrfs_set_super_num_devices(super, num_devs); - - memcpy(disk_super, super, sizeof(*disk_super)); - - btrfs_set_super_bytenr(disk_super, BTRFS_SUPER_INFO_OFFSET); - btrfs_set_stack_device_id(dev_item, device->devid); - btrfs_set_stack_device_type(dev_item, device->type); - btrfs_set_stack_device_io_align(dev_item, device->io_align); - btrfs_set_stack_device_io_width(dev_item, device->io_width); - btrfs_set_stack_device_sector_size(dev_item, device->sector_size); - btrfs_set_stack_device_total_bytes(dev_item, device->total_bytes); - btrfs_set_stack_device_bytes_used(dev_item, device->bytes_used); - memcpy(&dev_item->uuid, device->uuid, BTRFS_UUID_SIZE); - - ret = pwrite(fd, buf, sectorsize, BTRFS_SUPER_INFO_OFFSET); - BUG_ON(ret != sectorsize); - - free(buf); - list_add(&device->dev_list, &fs_info->fs_devices->devices); - device->fs_devices = fs_info->fs_devices; - return 0; - -out: - free(device); - free(buf); - return ret; -} - int btrfs_make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid) { @@ -216,46 +100,6 @@ error: return ret; } -/* - * This function checks if the given input parameter is - * an uuid or a path - * return <0 : some error in the given input - * return BTRFS_ARG_UNKNOWN: unknown input - * return BTRFS_ARG_UUID: given input is uuid - * return BTRFS_ARG_MNTPOINT: given input is path - * return BTRFS_ARG_REG: given input is regular file - * return BTRFS_ARG_BLKDEV: given input is block device - */ -int check_arg_type(const char *input) -{ - uuid_t uuid; - char path[PATH_MAX]; - - if (!input) - return -EINVAL; - - if (realpath(input, path)) { - if (path_is_block_device(path) == 1) - return BTRFS_ARG_BLKDEV; - - if (path_is_mount_point(path) == 1) - return BTRFS_ARG_MNTPOINT; - - if (path_is_reg_file(path)) - return BTRFS_ARG_REG; - - return BTRFS_ARG_UNKNOWN; - } else { - return -errno; - } - - if (strlen(input) == (BTRFS_UUID_UNPARSED_SIZE - 1) && - !uuid_parse(input, uuid)) - return BTRFS_ARG_UUID; - - return BTRFS_ARG_UNKNOWN; -} - /* * Find the mount point for a mounted device. * On success, returns 0 with mountpoint in *mp. @@ -486,91 +330,6 @@ struct pending_dir { char name[PATH_MAX]; }; -int btrfs_register_one_device(const char *fname) -{ - struct btrfs_ioctl_vol_args args; - int fd; - int ret; - - fd = open("/dev/btrfs-control", O_RDWR); - if (fd < 0) { - warning( - "failed to open /dev/btrfs-control, skipping device registration: %m"); - return -errno; - } - memset(&args, 0, sizeof(args)); - strncpy_null(args.name, fname); - ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args); - if (ret < 0) { - error("device scan failed on '%s': %m", fname); - ret = -errno; - } - close(fd); - return ret; -} - -/* - * Register all devices in the fs_uuid list created in the user - * space. Ensure btrfs_scan_devices() is called before this func. - */ -int btrfs_register_all_devices(void) -{ - int err = 0; - int ret = 0; - struct btrfs_fs_devices *fs_devices; - struct btrfs_device *device; - struct list_head *all_uuids; - - all_uuids = btrfs_scanned_uuids(); - - list_for_each_entry(fs_devices, all_uuids, list) { - list_for_each_entry(device, &fs_devices->devices, dev_list) { - if (*device->name) - err = btrfs_register_one_device(device->name); - - if (err) - ret++; - } - } - - return ret; -} - -int btrfs_device_already_in_root(struct btrfs_root *root, int fd, - int super_offset) -{ - struct btrfs_super_block *disk_super; - char *buf; - int ret = 0; - - buf = malloc(BTRFS_SUPER_INFO_SIZE); - if (!buf) { - ret = -ENOMEM; - goto out; - } - ret = pread(fd, buf, BTRFS_SUPER_INFO_SIZE, super_offset); - if (ret != BTRFS_SUPER_INFO_SIZE) - goto brelse; - - ret = 0; - disk_super = (struct btrfs_super_block *)buf; - /* - * Accept devices from the same filesystem, allow partially created - * structures. - */ - if (btrfs_super_magic(disk_super) != BTRFS_MAGIC && - btrfs_super_magic(disk_super) != BTRFS_MAGIC_TEMPORARY) - goto brelse; - - if (!memcmp(disk_super->fsid, root->fs_info->super_copy->fsid, - BTRFS_FSID_SIZE)) - ret = 1; -brelse: - free(buf); -out: - return ret; -} - /* * Note: this function uses a static per-thread buffer. Do not call this * function more than 10 times within one argument list! @@ -1347,79 +1106,6 @@ out: return ret; } -int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]) -{ - u8 hash = fsid[0]; - int slot = hash % SEEN_FSID_HASH_SIZE; - struct seen_fsid *seen = seen_fsid_hash[slot]; - - while (seen) { - if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) - return 1; - - seen = seen->next; - } - - return 0; -} - -int add_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[], - int fd, DIR *dirstream) -{ - u8 hash = fsid[0]; - int slot = hash % SEEN_FSID_HASH_SIZE; - struct seen_fsid *seen = seen_fsid_hash[slot]; - struct seen_fsid *alloc; - - if (!seen) - goto insert; - - while (1) { - if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) - return -EEXIST; - - if (!seen->next) - break; - - seen = seen->next; - } - -insert: - alloc = malloc(sizeof(*alloc)); - if (!alloc) - return -ENOMEM; - - alloc->next = NULL; - memcpy(alloc->fsid, fsid, BTRFS_FSID_SIZE); - alloc->fd = fd; - alloc->dirstream = dirstream; - - if (seen) - seen->next = alloc; - else - seen_fsid_hash[slot] = alloc; - - return 0; -} - -void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]) -{ - int slot; - struct seen_fsid *seen; - struct seen_fsid *next; - - for (slot = 0; slot < SEEN_FSID_HASH_SIZE; slot++) { - seen = seen_fsid_hash[slot]; - while (seen) { - next = seen->next; - close_file_or_dir(seen->fd, seen->dirstream); - free(seen); - seen = next; - } - seen_fsid_hash[slot] = NULL; - } -} - static int group_profile_devs_min(u64 flag) { switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) { @@ -1511,61 +1197,6 @@ int group_profile_max_safe_loss(u64 flags) } } -int btrfs_scan_devices(void) -{ - int fd = -1; - int ret; - u64 num_devices; - struct btrfs_fs_devices *tmp_devices; - blkid_dev_iterate iter = NULL; - blkid_dev dev = NULL; - blkid_cache cache = NULL; - char path[PATH_MAX]; - - if (btrfs_scan_done) - return 0; - - ret = blkid_get_cache(&cache, NULL); - if (ret < 0) { - errno = -ret; - error("blkid cache get failed: %m"); - return ret; - } - blkid_probe_all(cache); - iter = blkid_dev_iterate_begin(cache); - blkid_dev_set_search(iter, "TYPE", "btrfs"); - while (blkid_dev_next(iter, &dev) == 0) { - dev = blkid_verify(cache, dev); - if (!dev) - continue; - /* if we are here its definitely a btrfs disk*/ - strncpy_null(path, blkid_dev_devname(dev)); - - fd = open(path, O_RDONLY); - if (fd < 0) { - error("cannot open %s: %m", path); - continue; - } - ret = btrfs_scan_one_device(fd, path, &tmp_devices, - &num_devices, BTRFS_SUPER_INFO_OFFSET, - SBREAD_DEFAULT); - if (ret) { - errno = -ret; - error("cannot scan %s: %m", path); - close (fd); - continue; - } - - close(fd); - } - blkid_dev_iterate_end(iter); - blkid_put_cache(cache); - - btrfs_scan_done = 1; - - return 0; -} - /* * 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 diff --git a/common/utils.h b/common/utils.h index 8da5bbf4..7867fb0a 100644 --- a/common/utils.h +++ b/common/utils.h @@ -31,17 +31,6 @@ #include "ioctl.h" #include "common/fsfeatures.h" -#define BTRFS_SCAN_MOUNTED (1ULL << 0) -#define BTRFS_SCAN_LBLKID (1ULL << 1) - -#define BTRFS_UPDATE_KERNEL 1 - -#define BTRFS_ARG_UNKNOWN 0 -#define BTRFS_ARG_MNTPOINT 1 -#define BTRFS_ARG_UUID 2 -#define BTRFS_ARG_BLKDEV 3 -#define BTRFS_ARG_REG 4 - /* * Output modes of size */ @@ -66,28 +55,11 @@ void units_set_mode(unsigned *units, unsigned mode); void units_set_base(unsigned *units, unsigned base); -#define SEEN_FSID_HASH_SIZE 256 -struct seen_fsid { - u8 fsid[BTRFS_FSID_SIZE]; - struct seen_fsid *next; - DIR *dirstream; - int fd; -}; - int btrfs_make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid); -int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int fd, const char *path, - u64 block_count, u32 io_width, u32 io_align, - u32 sectorsize); -int btrfs_scan_for_fsid(int run_ioctls); -int btrfs_register_one_device(const char *fname); -int btrfs_register_all_devices(void); int check_mounted(const char *devicename); int check_mounted_where(int fd, const char *file, char *where, int size, struct btrfs_fs_devices **fs_devices_mnt, unsigned sbflags); -int btrfs_device_already_in_root(struct btrfs_root *root, int fd, - int super_offset); int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, unsigned unit_mode); #define pretty_size(size) pretty_size_mode(size, UNITS_DEFAULT) @@ -103,11 +75,6 @@ int get_fs_info(const char *path, struct btrfs_ioctl_fs_info_args *fi_args, struct btrfs_ioctl_dev_info_args **di_ret); int get_fsid(const char *path, u8 *fsid, int silent); -int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]); -int add_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[], - int fd, DIR *dirstream); -void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]); - int get_label(const char *btrfs_dev, char *label); int set_label(const char *btrfs_dev, const char *label); @@ -123,7 +90,6 @@ int csum_tree_block(struct btrfs_fs_info *root, struct extent_buffer *buf, int verify); int ask_user(const char *question); int lookup_path_rootid(int fd, u64 *rootid); -int btrfs_scan_devices(void); int get_btrfs_mount(const char *dev, char *mp, size_t mp_size); int find_mount_root(const char *path, char **mount_root); int get_device_info(int fd, u64 devid, diff --git a/disk-io.c b/disk-io.c index 8ccce81f..be44eead 100644 --- a/disk-io.c +++ b/disk-io.c @@ -33,6 +33,7 @@ #include "common/utils.h" #include "print-tree.h" #include "common/rbtree-utils.h" +#include "common/device-scan.h" /* specified errno for check_tree_block */ #define BTRFS_BAD_BYTENR (-1) diff --git a/mkfs/main.c b/mkfs/main.c index c50f7eb5..383379e6 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -39,6 +39,7 @@ #include "common/utils.h" #include "common/path-utils.h" #include "common/device-utils.h" +#include "common/device-scan.h" #include "kernel-lib/list_sort.h" #include "common/help.h" #include "common/rbtree-utils.h"