Commit 17405279 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: bch2_sb_member_alloc()



refactoring

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 6b812f1d
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -474,3 +474,47 @@ unsigned bch2_sb_nr_devices(const struct bch_sb *sb)
		nr += bch2_member_exists((struct bch_sb *) sb, i);
	return nr;
}

int bch2_sb_member_alloc(struct bch_fs *c)
{
	unsigned dev_idx = c->sb.nr_devices;
	if (dev_idx < BCH_SB_MEMBERS_MAX)
		goto have_slot;

	int best = -1;
	u64 best_last_mount = 0;
	for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++) {
		/* eventually BCH_SB_MEMBERS_MAX will be raised */
		if (dev_idx == BCH_SB_MEMBER_INVALID)
			continue;

		struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, dev_idx);
		if (bch2_member_alive(&m))
			continue;

		u64 last_mount = le64_to_cpu(m.last_mount);
		if (best < 0 || last_mount < best_last_mount) {
			best = dev_idx;
			best_last_mount = last_mount;
		}
	}
	if (best >= 0) {
		dev_idx = best;
		goto have_slot;
	}

	return -BCH_ERR_ENOSPC_sb_members;
have_slot:
	unsigned nr_devices = max_t(unsigned, dev_idx + 1, c->sb.nr_devices);

	struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
	unsigned u64s = DIV_ROUND_UP(sizeof(struct bch_sb_field_members_v2) +
				     le16_to_cpu(mi->member_bytes) * nr_devices, sizeof(u64));

	mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s);
	if (!mi)
		return -BCH_ERR_ENOSPC_sb_members;

	c->disk_sb.sb->nr_devices = nr_devices;
	return dev_idx;
}
+2 −0
Original line number Diff line number Diff line
@@ -354,4 +354,6 @@ static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64
bool bch2_dev_btree_bitmap_marked(struct bch_fs *, struct bkey_s_c);
void bch2_dev_btree_bitmap_mark(struct bch_fs *, struct bkey_s_c);

int bch2_sb_member_alloc(struct bch_fs *);

#endif /* _BCACHEFS_SB_MEMBERS_H */
+7 −46
Original line number Diff line number Diff line
@@ -1703,9 +1703,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
	struct bch_opts opts = bch2_opts_empty();
	struct bch_sb_handle sb;
	struct bch_dev *ca = NULL;
	struct bch_sb_field_members_v2 *mi;
	struct bch_member dev_mi;
	unsigned dev_idx, nr_devices, u64s;
	struct printbuf errbuf = PRINTBUF;
	struct printbuf label = PRINTBUF;
	int ret;
@@ -1715,7 +1712,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
	if (ret)
		goto err;

	dev_mi = bch2_sb_member_get(sb.sb, sb.sb->dev_idx);
	struct bch_member dev_mi = bch2_sb_member_get(sb.sb, sb.sb->dev_idx);

	if (BCH_MEMBER_GROUP(&dev_mi)) {
		bch2_disk_path_to_text_sb(&label, sb.sb, BCH_MEMBER_GROUP(&dev_mi) - 1);
@@ -1753,55 +1750,19 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
		goto err_unlock;

	if (dynamic_fault("bcachefs:add:no_slot"))
		goto no_slot;

	if (c->sb.nr_devices < BCH_SB_MEMBERS_MAX) {
		dev_idx = c->sb.nr_devices;
		goto have_slot;
	}

	int best = -1;
	u64 best_last_mount = 0;
	for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++) {
		struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, dev_idx);
		if (bch2_member_alive(&m))
			continue;

		u64 last_mount = le64_to_cpu(m.last_mount);
		if (best < 0 || last_mount < best_last_mount) {
			best = dev_idx;
			best_last_mount = last_mount;
		}
	}
	if (best >= 0) {
		dev_idx = best;
		goto have_slot;
	}
no_slot:
	ret = -BCH_ERR_ENOSPC_sb_members;
	bch_err_msg(c, ret, "setting up new superblock");
		goto err_unlock;

have_slot:
	nr_devices = max_t(unsigned, dev_idx + 1, c->sb.nr_devices);

	mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
	u64s = DIV_ROUND_UP(sizeof(struct bch_sb_field_members_v2) +
			    le16_to_cpu(mi->member_bytes) * nr_devices, sizeof(u64));

	mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s);
	if (!mi) {
		ret = -BCH_ERR_ENOSPC_sb_members;
	ret = bch2_sb_member_alloc(c);
	if (ret < 0) {
		bch_err_msg(c, ret, "setting up new superblock");
		goto err_unlock;
	}
	struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, dev_idx);
	unsigned dev_idx = ret;

	/* success: */

	*m = dev_mi;
	m->last_mount = cpu_to_le64(ktime_get_real_seconds());
	c->disk_sb.sb->nr_devices	= nr_devices;
	dev_mi.last_mount = cpu_to_le64(ktime_get_real_seconds());
	*bch2_members_v2_get_mut(c->disk_sb.sb, dev_idx) = dev_mi;

	ca->disk_sb.sb->dev_idx	= dev_idx;
	bch2_dev_attach(c, ca, dev_idx);