diff options
Diffstat (limited to 'libbcachefs/super.c')
-rw-r--r-- | libbcachefs/super.c | 487 |
1 files changed, 213 insertions, 274 deletions
diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 77670ea6..05910c40 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -18,6 +18,7 @@ #include "clock.h" #include "compress.h" #include "debug.h" +#include "disk_groups.h" #include "error.h" #include "fs.h" #include "fs-io.h" @@ -30,6 +31,7 @@ #include "migrate.h" #include "movinggc.h" #include "quota.h" +#include "replicas.h" #include "super.h" #include "super-io.h" #include "sysfs.h" @@ -122,7 +124,7 @@ static struct bch_fs *__bch2_uuid_to_fs(uuid_le uuid) lockdep_assert_held(&bch_fs_list_lock); list_for_each_entry(c, &bch_fs_list, list) - if (!memcmp(&c->disk_sb->uuid, &uuid, sizeof(uuid_le))) + if (!memcmp(&c->disk_sb.sb->uuid, &uuid, sizeof(uuid_le))) return c; return NULL; @@ -203,23 +205,12 @@ static void bch_fs_mark_clean(struct bch_fs *c) !test_bit(BCH_FS_ERROR, &c->flags) && !test_bit(BCH_FS_EMERGENCY_RO, &c->flags)) { mutex_lock(&c->sb_lock); - SET_BCH_SB_CLEAN(c->disk_sb, true); + SET_BCH_SB_CLEAN(c->disk_sb.sb, true); bch2_write_super(c); mutex_unlock(&c->sb_lock); } } -static bool btree_interior_updates_done(struct bch_fs *c) -{ - bool ret; - - mutex_lock(&c->btree_interior_update_lock); - ret = list_empty(&c->btree_interior_update_list); - mutex_unlock(&c->btree_interior_update_lock); - - return ret; -} - static void __bch2_fs_read_only(struct bch_fs *c) { struct bch_dev *ca; @@ -251,7 +242,7 @@ static void __bch2_fs_read_only(struct bch_fs *c) * fully complete: */ closure_wait_event(&c->btree_interior_update_wait, - btree_interior_updates_done(c)); + !bch2_btree_interior_updates_nr_pending(c)); if (!test_bit(BCH_FS_EMERGENCY_RO, &c->flags)) bch2_btree_verify_flushed(c); @@ -433,7 +424,8 @@ static void bch2_fs_free(struct bch_fs *c) if (c->wq) destroy_workqueue(c->wq); - free_pages((unsigned long) c->disk_sb, c->disk_sb_order); + free_pages((unsigned long) c->disk_sb.sb, + c->disk_sb.page_order); kvpfree(c, sizeof(*c)); module_put(THIS_MODULE); } @@ -501,11 +493,54 @@ void bch2_fs_stop(struct bch_fs *c) kobject_put(&c->kobj); } +static const char *bch2_fs_online(struct bch_fs *c) +{ + struct bch_dev *ca; + const char *err = NULL; + unsigned i; + int ret; + + lockdep_assert_held(&bch_fs_list_lock); + + if (!list_empty(&c->list)) + return NULL; + + if (__bch2_uuid_to_fs(c->sb.uuid)) + return "filesystem UUID already open"; + + ret = bch2_fs_chardev_init(c); + if (ret) + return "error creating character device"; + + bch2_fs_debug_init(c); + + if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || + kobject_add(&c->internal, &c->kobj, "internal") || + kobject_add(&c->opts_dir, &c->kobj, "options") || + kobject_add(&c->time_stats, &c->kobj, "time_stats") || + bch2_opts_create_sysfs_files(&c->opts_dir)) + return "error creating sysfs objects"; + + mutex_lock(&c->state_lock); + + err = "error creating sysfs objects"; + __for_each_member_device(ca, c, i, NULL) + if (bch2_dev_sysfs_online(c, ca)) + goto err; + + list_add(&c->list, &bch_fs_list); + err = NULL; +err: + mutex_unlock(&c->state_lock); + return err; +} + static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) { struct bch_sb_field_members *mi; struct bch_fs *c; unsigned i, iter_size; + const char *err; pr_verbose_init(opts, ""); @@ -516,6 +551,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) __module_get(THIS_MODULE); c->minor = -1; + c->disk_sb.fs_sb = true; mutex_init(&c->state_lock); mutex_init(&c->sb_lock); @@ -627,9 +663,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) bch2_fs_fsio_init(c)) goto err; - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); for (i = 0; i < c->sb.nr_devices; i++) - if (bch2_dev_exists(c->disk_sb, mi, i) && + if (bch2_dev_exists(c->disk_sb.sb, mi, i) && bch2_dev_alloc(c, i)) goto err; @@ -644,6 +680,14 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) kobject_init(&c->internal, &bch2_fs_internal_ktype); kobject_init(&c->opts_dir, &bch2_fs_opts_dir_ktype); kobject_init(&c->time_stats, &bch2_fs_time_stats_ktype); + + mutex_lock(&bch_fs_list_lock); + err = bch2_fs_online(c); + mutex_unlock(&bch_fs_list_lock); + if (err) { + bch_err(c, "bch2_fs_online() error: %s", err); + goto err; + } out: pr_verbose_init(opts, "ret %i", c ? 0 : -ENOMEM); return c; @@ -653,60 +697,7 @@ err: goto out; } -static const char *__bch2_fs_online(struct bch_fs *c) -{ - struct bch_dev *ca; - const char *err = NULL; - unsigned i; - int ret; - - lockdep_assert_held(&bch_fs_list_lock); - - if (!list_empty(&c->list)) - return NULL; - - if (__bch2_uuid_to_fs(c->sb.uuid)) - return "filesystem UUID already open"; - - ret = bch2_fs_chardev_init(c); - if (ret) - return "error creating character device"; - - bch2_fs_debug_init(c); - - if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || - kobject_add(&c->internal, &c->kobj, "internal") || - kobject_add(&c->opts_dir, &c->kobj, "options") || - kobject_add(&c->time_stats, &c->kobj, "time_stats") || - bch2_opts_create_sysfs_files(&c->opts_dir)) - return "error creating sysfs objects"; - - mutex_lock(&c->state_lock); - - err = "error creating sysfs objects"; - __for_each_member_device(ca, c, i, NULL) - if (bch2_dev_sysfs_online(c, ca)) - goto err; - - list_add(&c->list, &bch_fs_list); - err = NULL; -err: - mutex_unlock(&c->state_lock); - return err; -} - -static const char *bch2_fs_online(struct bch_fs *c) -{ - const char *err; - - mutex_lock(&bch_fs_list_lock); - err = __bch2_fs_online(c); - mutex_unlock(&bch_fs_list_lock); - - return err; -} - -static const char *__bch2_fs_start(struct bch_fs *c) +const char *bch2_fs_start(struct bch_fs *c) { const char *err = "cannot allocate memory"; struct bch_sb_field_members *mi; @@ -730,15 +721,15 @@ static const char *__bch2_fs_start(struct bch_fs *c) bch2_dev_allocator_add(c, ca); bch2_recalc_capacity(c); - if (BCH_SB_INITIALIZED(c->disk_sb)) { + if (BCH_SB_INITIALIZED(c->disk_sb.sb)) { ret = bch2_journal_read(c, &journal); if (ret) goto err; j = &list_entry(journal.prev, struct journal_replay, list)->j; - c->prio_clock[READ].hand = le16_to_cpu(j->read_clock); - c->prio_clock[WRITE].hand = le16_to_cpu(j->write_clock); + c->bucket_clock[READ].hand = le16_to_cpu(j->read_clock); + c->bucket_clock[WRITE].hand = le16_to_cpu(j->write_clock); for (i = 0; i < BTREE_ID_NR; i++) { unsigned level; @@ -824,21 +815,18 @@ static const char *__bch2_fs_start(struct bch_fs *c) bch_notice(c, "initializing new filesystem"); set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags); - set_bit(BCH_FS_BRAND_NEW_FS, &c->flags); ret = bch2_initial_gc(c, &journal); if (ret) goto err; err = "unable to allocate journal buckets"; - for_each_rw_member(ca, c, i) - if (bch2_dev_journal_alloc(c, ca)) { + for_each_online_member(ca, c, i) + if (bch2_dev_journal_alloc(ca)) { percpu_ref_put(&ca->io_ref); goto err; } - clear_bit(BCH_FS_BRAND_NEW_FS, &c->flags); - for (i = 0; i < BTREE_ID_NR; i++) bch2_btree_root_alloc(c, i); @@ -889,18 +877,20 @@ recovery_done: } mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); now = ktime_get_seconds(); for_each_member_device(ca, c, i) mi->members[ca->dev_idx].last_mount = cpu_to_le64(now); - SET_BCH_SB_INITIALIZED(c->disk_sb, true); - SET_BCH_SB_CLEAN(c->disk_sb, false); + SET_BCH_SB_INITIALIZED(c->disk_sb.sb, true); + SET_BCH_SB_CLEAN(c->disk_sb.sb, false); bch2_write_super(c); mutex_unlock(&c->sb_lock); + set_bit(BCH_FS_STARTED, &c->flags); + err = NULL; out: mutex_unlock(&c->state_lock); @@ -939,11 +929,6 @@ fsck_err: goto out; } -const char *bch2_fs_start(struct bch_fs *c) -{ - return __bch2_fs_start(c) ?: bch2_fs_online(c); -} - static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c) { struct bch_sb_field_members *sb_mi; @@ -956,7 +941,7 @@ static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c) return "mismatched block size"; if (le16_to_cpu(sb_mi->members[sb->dev_idx].bucket_size) < - BCH_SB_BTREE_NODE_SIZE(c->disk_sb)) + BCH_SB_BTREE_NODE_SIZE(c->disk_sb.sb)) return "new cache bucket size is too small"; return NULL; @@ -1082,28 +1067,19 @@ static int bch2_dev_sysfs_online(struct bch_fs *c, struct bch_dev *ca) return 0; } -static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) +static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, + struct bch_member *member) { - struct bch_member *member; - struct bch_dev *ca = NULL; - int ret = 0; - - pr_verbose_init(c->opts, ""); - - if (bch2_fs_init_fault("dev_alloc")) - goto err; + struct bch_dev *ca; ca = kzalloc(sizeof(*ca), GFP_KERNEL); if (!ca) - goto err; + return NULL; kobject_init(&ca->kobj, &bch2_dev_ktype); init_completion(&ca->ref_completion); init_completion(&ca->io_ref_completion); - ca->dev_idx = dev_idx; - __set_bit(ca->dev_idx, ca->self.d); - init_rwsem(&ca->bucket_lock); writepoint_init(&ca->copygc_write_point, BCH_DATA_USER); @@ -1113,14 +1089,8 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) INIT_WORK(&ca->io_error_work, bch2_io_error_work); - if (bch2_fs_init_fault("dev_alloc")) - goto err; - - member = bch2_sb_get_members(c->disk_sb)->members + dev_idx; - ca->mi = bch2_mi_to_cpu(member); ca->uuid = member->uuid; - scnprintf(ca->name, sizeof(ca->name), "dev-%u", dev_idx); if (percpu_ref_init(&ca->ref, bch2_dev_ref_complete, 0, GFP_KERNEL) || @@ -1132,11 +1102,43 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) !(ca->io_done = alloc_percpu(*ca->io_done))) goto err; + return ca; +err: + bch2_dev_free(ca); + return NULL; +} + +static void bch2_dev_attach(struct bch_fs *c, struct bch_dev *ca, + unsigned dev_idx) +{ + ca->dev_idx = dev_idx; + __set_bit(ca->dev_idx, ca->self.d); + scnprintf(ca->name, sizeof(ca->name), "dev-%u", dev_idx); + ca->fs = c; rcu_assign_pointer(c->devs[ca->dev_idx], ca); if (bch2_dev_sysfs_online(c, ca)) pr_warn("error creating sysfs objects"); +} + +static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) +{ + struct bch_member *member = + bch2_sb_get_members(c->disk_sb.sb)->members + dev_idx; + struct bch_dev *ca = NULL; + int ret = 0; + + pr_verbose_init(c->opts, ""); + + if (bch2_fs_init_fault("dev_alloc")) + goto err; + + ca = __bch2_dev_alloc(c, member); + if (!ca) + goto err; + + bch2_dev_attach(c, ca, dev_idx); out: pr_verbose_init(c->opts, "ret %i", ret); return ret; @@ -1147,21 +1149,9 @@ err: goto out; } -static int __bch2_dev_online(struct bch_fs *c, struct bch_sb_handle *sb) +static int __bch2_dev_attach_bdev(struct bch_dev *ca, struct bch_sb_handle *sb) { - struct bch_dev *ca; - int ret; - - lockdep_assert_held(&c->state_lock); - - if (le64_to_cpu(sb->sb->seq) > - le64_to_cpu(c->disk_sb->seq)) - bch2_sb_to_fs(c, sb->sb); - - BUG_ON(sb->sb->dev_idx >= c->sb.nr_devices || - !c->devs[sb->sb->dev_idx]); - - ca = bch_dev_locked(c, sb->sb->dev_idx); + unsigned ret; if (bch2_dev_is_online(ca)) { bch_err(ca, "already have device online in slot %u", @@ -1179,7 +1169,7 @@ static int __bch2_dev_online(struct bch_fs *c, struct bch_sb_handle *sb) if (get_capacity(sb->bdev->bd_disk) < ca->mi.bucket_size * ca->mi.nbuckets) { - bch_err(c, "device too small"); + bch_err(ca, "device too small"); return -EINVAL; } @@ -1187,35 +1177,50 @@ static int __bch2_dev_online(struct bch_fs *c, struct bch_sb_handle *sb) if (ret) return ret; - /* - * Increase journal write timeout if flushes to this device are - * expensive: - */ - if (!blk_queue_nonrot(bdev_get_queue(sb->bdev)) && - journal_flushes_device(ca)) - c->journal.write_delay_ms = - max(c->journal.write_delay_ms, 1000U); - /* Commit: */ ca->disk_sb = *sb; if (sb->mode & FMODE_EXCL) ca->disk_sb.bdev->bd_holder = ca; memset(sb, 0, sizeof(*sb)); + if (ca->fs) + mutex_lock(&ca->fs->sb_lock); + + bch2_mark_dev_superblock(ca->fs, ca, BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE); + + if (ca->fs) + mutex_unlock(&ca->fs->sb_lock); + + percpu_ref_reinit(&ca->io_ref); + + return 0; +} + +static int bch2_dev_attach_bdev(struct bch_fs *c, struct bch_sb_handle *sb) +{ + struct bch_dev *ca; + int ret; + + lockdep_assert_held(&c->state_lock); + + if (le64_to_cpu(sb->sb->seq) > + le64_to_cpu(c->disk_sb.sb->seq)) + bch2_sb_to_fs(c, sb->sb); + + BUG_ON(sb->sb->dev_idx >= c->sb.nr_devices || + !c->devs[sb->sb->dev_idx]); + + ca = bch_dev_locked(c, sb->sb->dev_idx); + + ret = __bch2_dev_attach_bdev(ca, sb); + if (ret) + return ret; + if (c->sb.nr_devices == 1) bdevname(ca->disk_sb.bdev, c->name); bdevname(ca->disk_sb.bdev, ca->name); - mutex_lock(&c->sb_lock); - bch2_mark_dev_superblock(c, ca, BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE); - mutex_unlock(&c->sb_lock); - - if (ca->mi.state == BCH_MEMBER_STATE_RW) - bch2_dev_allocator_add(c, ca); - rebalance_wakeup(c); - - percpu_ref_reinit(&ca->io_ref); return 0; } @@ -1289,10 +1294,10 @@ static bool bch2_fs_may_start(struct bch_fs *c) if (!c->opts.degraded) { mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); - for (i = 0; i < c->disk_sb->nr_devices; i++) { - if (!bch2_dev_exists(c->disk_sb, mi, i)) + for (i = 0; i < c->disk_sb.sb->nr_devices; i++) { + if (!bch2_dev_exists(c->disk_sb.sb, mi, i)) continue; ca = bch_dev_locked(c, i); @@ -1360,7 +1365,7 @@ int __bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca, bch_notice(ca, "%s", bch2_dev_state[new_state]); mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); SET_BCH_MEMBER_STATE(&mi->members[ca->dev_idx], new_state); bch2_write_super(c); mutex_unlock(&c->sb_lock); @@ -1470,7 +1475,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags) * this device must be gone: */ mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); memset(&mi->members[dev_idx].uuid, 0, sizeof(mi->members[dev_idx].uuid)); bch2_write_super(c); @@ -1492,8 +1497,8 @@ int bch2_dev_add(struct bch_fs *c, const char *path) struct bch_sb_handle sb; const char *err; struct bch_dev *ca = NULL; - struct bch_sb_field_members *mi, *dev_mi; - struct bch_member saved_mi; + struct bch_sb_field_members *mi; + struct bch_member dev_mi; unsigned dev_idx, nr_devices, u64s; int ret; @@ -1505,24 +1510,52 @@ int bch2_dev_add(struct bch_fs *c, const char *path) if (err) return -EINVAL; + dev_mi = bch2_sb_get_members(sb.sb)->members[sb.sb->dev_idx]; + err = bch2_dev_may_add(sb.sb, c); if (err) return -EINVAL; + ca = __bch2_dev_alloc(c, &dev_mi); + if (!ca) { + bch2_free_super(&sb); + return -ENOMEM; + } + + ret = __bch2_dev_attach_bdev(ca, &sb); + if (ret) { + bch2_dev_free(ca); + return ret; + } + + err = "journal alloc failed"; + ret = bch2_dev_journal_alloc(ca); + if (ret) + goto err; + mutex_lock(&c->state_lock); mutex_lock(&c->sb_lock); - /* Grab member info for new disk: */ - dev_mi = bch2_sb_get_members(sb.sb); - saved_mi = dev_mi->members[sb.sb->dev_idx]; - saved_mi.last_mount = cpu_to_le64(ktime_get_seconds()); + err = "insufficient space in new superblock"; + ret = bch2_sb_from_fs(c, ca); + if (ret) + goto err_unlock; + + mi = bch2_sb_get_members(ca->disk_sb.sb); + + if (!bch2_sb_resize_members(&ca->disk_sb, + le32_to_cpu(mi->field.u64s) + + sizeof(dev_mi) / sizeof(u64))) { + ret = -ENOSPC; + goto err_unlock; + } if (dynamic_fault("bcachefs:add:no_slot")) goto no_slot; - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++) - if (!bch2_dev_exists(c->disk_sb, mi, dev_idx)) + if (!bch2_dev_exists(c->disk_sb.sb, mi, dev_idx)) goto have_slot; no_slot: err = "no slots available in superblock"; @@ -1533,64 +1566,47 @@ have_slot: nr_devices = max_t(unsigned, dev_idx + 1, c->sb.nr_devices); u64s = (sizeof(struct bch_sb_field_members) + sizeof(struct bch_member) * nr_devices) / sizeof(u64); - err = "no space in superblock for member info"; - dev_mi = bch2_sb_resize_members(&sb, u64s); - if (!dev_mi) - goto err_unlock; + err = "no space in superblock for member info"; + ret = -ENOSPC; - mi = bch2_fs_sb_resize_members(c, u64s); + mi = bch2_sb_resize_members(&c->disk_sb, u64s); if (!mi) goto err_unlock; - memcpy(dev_mi, mi, u64s * sizeof(u64)); - dev_mi->members[dev_idx] = saved_mi; + /* success: */ - sb.sb->uuid = c->disk_sb->uuid; - sb.sb->dev_idx = dev_idx; - sb.sb->nr_devices = nr_devices; + mi->members[dev_idx] = dev_mi; + mi->members[dev_idx].last_mount = cpu_to_le64(ktime_get_seconds()); + c->disk_sb.sb->nr_devices = nr_devices; - /* commit new member info */ - memcpy(mi, dev_mi, u64s * sizeof(u64)); - c->disk_sb->nr_devices = nr_devices; - c->sb.nr_devices = nr_devices; + ca->disk_sb.sb->dev_idx = dev_idx; + bch2_dev_attach(c, ca, dev_idx); bch2_write_super(c); mutex_unlock(&c->sb_lock); - if (bch2_dev_alloc(c, dev_idx)) { - err = "cannot allocate memory"; - ret = -ENOMEM; - goto err; - } - - if (__bch2_dev_online(c, &sb)) { - err = "bch2_dev_online() error"; - ret = -ENOMEM; - goto err; - } - - ca = bch_dev_locked(c, dev_idx); if (ca->mi.state == BCH_MEMBER_STATE_RW) { err = __bch2_dev_read_write(c, ca); if (err) - goto err; - - err = "journal alloc failed"; - if (bch2_dev_journal_alloc(c, ca)) - goto err; + goto err_late; } mutex_unlock(&c->state_lock); return 0; + err_unlock: mutex_unlock(&c->sb_lock); -err: mutex_unlock(&c->state_lock); +err: + if (ca) + bch2_dev_free(ca); bch2_free_super(&sb); - bch_err(c, "Unable to add device: %s", err); - return ret ?: -EINVAL; + return ret; +err_late: + bch_err(c, "Error going rw after adding device: %s", err); + return -EINVAL; } /* Hot add existing device to running filesystem: */ @@ -1613,12 +1629,12 @@ int bch2_dev_online(struct bch_fs *c, const char *path) dev_idx = sb.sb->dev_idx; - err = bch2_dev_in_fs(c->disk_sb, sb.sb); + err = bch2_dev_in_fs(c->disk_sb.sb, sb.sb); if (err) goto err; - if (__bch2_dev_online(c, &sb)) { - err = "__bch2_dev_online() error"; + if (bch2_dev_attach_bdev(c, &sb)) { + err = "bch2_dev_attach_bdev() error"; goto err; } @@ -1688,7 +1704,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) } mutex_lock(&c->sb_lock); - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; + mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; mi->nbuckets = cpu_to_le64(nbuckets); bch2_write_super(c); @@ -1721,74 +1737,6 @@ found: return ca; } -int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *label) -{ - struct bch_sb_field_disk_groups *groups; - struct bch_disk_group *g; - struct bch_member *mi; - unsigned i, v, nr_groups; - int ret; - - if (strlen(label) > BCH_SB_LABEL_SIZE) - return -EINVAL; - - mutex_lock(&c->sb_lock); - groups = bch2_sb_get_disk_groups(c->disk_sb); - nr_groups = disk_groups_nr(groups); - - if (!strcmp(label, "none")) { - v = 0; - goto write_sb; - } - - ret = __bch2_disk_group_find(groups, label); - if (ret >= 0) { - v = ret + 1; - goto write_sb; - } - - /* not found - create a new disk group: */ - - for (i = 0; - i < nr_groups && !BCH_GROUP_DELETED(&groups->entries[i]); - i++) - ; - - if (i == nr_groups) { - unsigned u64s = - (sizeof(struct bch_sb_field_disk_groups) + - sizeof(struct bch_disk_group) * (nr_groups + 1)) / - sizeof(u64); - - groups = bch2_fs_sb_resize_disk_groups(c, u64s); - if (!groups) { - mutex_unlock(&c->sb_lock); - return -ENOSPC; - } - - nr_groups = disk_groups_nr(groups); - } - - BUG_ON(i >= nr_groups); - - g = &groups->entries[i]; - v = i + 1; - - memcpy(g->label, label, strlen(label)); - if (strlen(label) < sizeof(g->label)) - g->label[strlen(label)] = '\0'; - SET_BCH_GROUP_DELETED(g, 0); - SET_BCH_GROUP_DATA_ALLOWED(g, ~0); -write_sb: - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; - SET_BCH_MEMBER_GROUP(mi, v); - - bch2_write_super(c); - mutex_unlock(&c->sb_lock); - - return 0; -} - /* Filesystem open: */ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, @@ -1845,7 +1793,7 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, err = "bch2_dev_online() error"; mutex_lock(&c->state_lock); for (i = 0; i < nr_devices; i++) - if (__bch2_dev_online(c, &sb[i])) { + if (bch2_dev_attach_bdev(c, &sb[i])) { mutex_unlock(&c->state_lock); goto err_print; } @@ -1856,15 +1804,10 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, goto err_print; if (!c->opts.nostart) { - err = __bch2_fs_start(c); + err = bch2_fs_start(c); if (err) goto err_print; } - - err = bch2_fs_online(c); - if (err) - goto err_print; - out: kfree(sb); module_put(THIS_MODULE); @@ -1900,7 +1843,7 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, if (c) { closure_get(&c->cl); - err = bch2_dev_in_fs(c->disk_sb, sb->sb); + err = bch2_dev_in_fs(c->disk_sb.sb, sb->sb); if (err) goto err; } else { @@ -1915,22 +1858,18 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, err = "bch2_dev_online() error"; mutex_lock(&c->sb_lock); - if (__bch2_dev_online(c, sb)) { + if (bch2_dev_attach_bdev(c, sb)) { mutex_unlock(&c->sb_lock); goto err; } mutex_unlock(&c->sb_lock); if (!c->opts.nostart && bch2_fs_may_start(c)) { - err = __bch2_fs_start(c); + err = bch2_fs_start(c); if (err) goto err; } - err = __bch2_fs_online(c); - if (err) - goto err; - closure_put(&c->cl); mutex_unlock(&bch_fs_list_lock); |