mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
bcachefs: BCH_SB_MEMBER_DELETED_UUID
Add a sentinal value for devices that have been removed, but don't want to reuse their index until a fsck has completed. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -1079,6 +1079,10 @@ out:
|
||||
* allocator thread - issue wakeup in case they blocked on gc_lock:
|
||||
*/
|
||||
closure_wake_up(&c->freelist_wait);
|
||||
|
||||
if (!ret && !test_bit(BCH_FS_errors_not_fixed, &c->flags))
|
||||
bch2_sb_members_clean_deleted(c);
|
||||
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -525,6 +525,7 @@ int bch2_sb_member_alloc(struct bch_fs *c)
|
||||
unsigned u64s;
|
||||
int best = -1;
|
||||
u64 best_last_mount = 0;
|
||||
unsigned nr_deleted = 0;
|
||||
|
||||
if (dev_idx < BCH_SB_MEMBERS_MAX)
|
||||
goto have_slot;
|
||||
@@ -535,7 +536,10 @@ int bch2_sb_member_alloc(struct bch_fs *c)
|
||||
continue;
|
||||
|
||||
struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, dev_idx);
|
||||
if (bch2_member_alive(&m))
|
||||
|
||||
nr_deleted += uuid_equal(&m.uuid, &BCH_SB_MEMBER_DELETED_UUID);
|
||||
|
||||
if (!bch2_is_zero(&m.uuid, sizeof(m.uuid)))
|
||||
continue;
|
||||
|
||||
u64 last_mount = le64_to_cpu(m.last_mount);
|
||||
@@ -549,6 +553,10 @@ int bch2_sb_member_alloc(struct bch_fs *c)
|
||||
goto have_slot;
|
||||
}
|
||||
|
||||
if (nr_deleted)
|
||||
bch_err(c, "unable to allocate new member, but have %u deleted: run fsck",
|
||||
nr_deleted);
|
||||
|
||||
return -BCH_ERR_ENOSPC_sb_members;
|
||||
have_slot:
|
||||
nr_devices = max_t(unsigned, dev_idx + 1, c->sb.nr_devices);
|
||||
@@ -564,3 +572,22 @@ have_slot:
|
||||
c->disk_sb.sb->nr_devices = nr_devices;
|
||||
return dev_idx;
|
||||
}
|
||||
|
||||
void bch2_sb_members_clean_deleted(struct bch_fs *c)
|
||||
{
|
||||
mutex_lock(&c->sb_lock);
|
||||
bool write_sb = false;
|
||||
|
||||
for (unsigned i = 0; i < c->sb.nr_devices; i++) {
|
||||
struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, i);
|
||||
|
||||
if (uuid_equal(&m->uuid, &BCH_SB_MEMBER_DELETED_UUID)) {
|
||||
memset(&m->uuid, 0, sizeof(m->uuid));
|
||||
write_sb = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_sb)
|
||||
bch2_write_super(c);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
}
|
||||
|
||||
@@ -320,7 +320,8 @@ extern const struct bch_sb_field_ops bch_sb_field_ops_members_v2;
|
||||
|
||||
static inline bool bch2_member_alive(struct bch_member *m)
|
||||
{
|
||||
return !bch2_is_zero(&m->uuid, sizeof(m->uuid));
|
||||
return !bch2_is_zero(&m->uuid, sizeof(m->uuid)) &&
|
||||
!uuid_equal(&m->uuid, &BCH_SB_MEMBER_DELETED_UUID);
|
||||
}
|
||||
|
||||
static inline bool bch2_member_exists(struct bch_sb *sb, unsigned dev)
|
||||
@@ -381,5 +382,6 @@ 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 *);
|
||||
void bch2_sb_members_clean_deleted(struct bch_fs *);
|
||||
|
||||
#endif /* _BCACHEFS_SB_MEMBERS_H */
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
*/
|
||||
#define BCH_SB_MEMBER_INVALID 255
|
||||
|
||||
#define BCH_SB_MEMBER_DELETED_UUID \
|
||||
UUID_INIT(0xffffffff, 0xffff, 0xffff, \
|
||||
0xd9, 0x6a, 0x60, 0xcf, 0x80, 0x3d, 0xf7, 0xef)
|
||||
|
||||
#define BCH_MIN_NR_NBUCKETS (1 << 6)
|
||||
|
||||
#define BCH_IOPS_MEASUREMENTS() \
|
||||
|
||||
Reference in New Issue
Block a user