From 6a34032417d9bb90ead6f3b7bf891347bc4a1ed3 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 18 Oct 2023 21:57:11 -0400 Subject: [PATCH] Update bcachefs sources to a180af9dd349 bcachefs: Refactor memcpy into direct assignment Signed-off-by: Kent Overstreet --- .bcachefs_revision | 2 +- cmd_format.c | 2 +- cmd_key.c | 4 ++-- crypto.c | 4 ++-- include/linux/compiler.h | 1 + libbcachefs.c | 4 ++-- libbcachefs/alloc_background.c | 6 +++--- libbcachefs/bcachefs.h | 1 + libbcachefs/bkey_methods.c | 1 - libbcachefs/buckets.c | 5 +++-- libbcachefs/checksum.c | 9 +++++---- libbcachefs/counters.c | 6 +++--- libbcachefs/disk_groups.c | 15 +++++++------- libbcachefs/extents.h | 9 +++++---- libbcachefs/fs-ioctl.c | 14 +++++++++++-- libbcachefs/io_misc.c | 22 ++++++++++++++++++-- libbcachefs/journal.c | 4 ++-- libbcachefs/journal_sb.c | 2 +- libbcachefs/journal_seq_blacklist.c | 16 +++++++-------- libbcachefs/quota.c | 6 +++--- libbcachefs/recovery.c | 30 ++++++++++++++-------------- libbcachefs/replicas.c | 16 +++++++-------- libbcachefs/sb-clean.c | 4 ++-- libbcachefs/sb-members.c | 24 +++++++++++----------- libbcachefs/snapshot.c | 16 ++++++++++++--- libbcachefs/super-io.c | 18 ++++++++--------- libbcachefs/super-io.h | 30 +++++++++------------------- libbcachefs/super.c | 7 ++++--- libbcachefs/super_types.h | 2 +- rust-src/bch_bindgen/src/bcachefs.rs | 2 +- 30 files changed, 156 insertions(+), 126 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index 48318a7..6f98bb8 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -7bf1ac0d46ebede68561e0476f7af9c07ac21de8 +a180af9dd349d9819b13af43f877bea4f94c1c79 diff --git a/cmd_format.c b/cmd_format.c index 42f3fc6..954d40f 100644 --- a/cmd_format.c +++ b/cmd_format.c @@ -348,7 +348,7 @@ int cmd_show_super(int argc, char *argv[]) die("Error opening %s: %s", dev, bch2_err_str(ret)); if (print_default_fields) - fields = bch2_sb_get_members_v2(sb.sb) + fields = bch2_sb_field_get(sb.sb, members_v2) ? 1 << BCH_SB_FIELD_members_v2 : 1 << BCH_SB_FIELD_members_v1; diff --git a/cmd_key.c b/cmd_key.c index d3e5d7b..96206c4 100644 --- a/cmd_key.c +++ b/cmd_key.c @@ -92,7 +92,7 @@ int cmd_set_passphrase(int argc, char *argv[]) if (IS_ERR(c)) die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c))); - struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.sb); + struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); if (!crypt) die("Filesystem does not have encryption enabled"); @@ -130,7 +130,7 @@ int cmd_remove_passphrase(int argc, char *argv[]) if (IS_ERR(c)) die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c))); - struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.sb); + struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); if (!crypt) die("Filesystem does not have encryption enabled"); diff --git a/crypto.c b/crypto.c index 4e4d15a..32671bd 100644 --- a/crypto.c +++ b/crypto.c @@ -105,7 +105,7 @@ bool bch2_sb_is_encrypted(struct bch_sb *sb) { struct bch_sb_field_crypt *crypt; - return (crypt = bch2_sb_get_crypt(sb)) && + return (crypt = bch2_sb_field_get(sb, crypt)) && bch2_key_is_encrypted(&crypt->key); } @@ -113,7 +113,7 @@ void bch2_passphrase_check(struct bch_sb *sb, const char *passphrase, struct bch_key *passphrase_key, struct bch_encrypted_key *sb_key) { - struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(sb); + struct bch_sb_field_crypt *crypt = bch2_sb_field_get(sb, crypt); if (!crypt) die("filesystem is not encrypted"); diff --git a/include/linux/compiler.h b/include/linux/compiler.h index b9486db..61beee9 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -66,6 +66,7 @@ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define fallthrough __attribute__((__fallthrough__)) #define __noreturn __attribute__((__noreturn__)) +#define __counted_by(nr) #define ___PASTE(a,b) a##b #define __PASTE(a,b) ___PASTE(a,b) diff --git a/libbcachefs.c b/libbcachefs.c index 499badb..577ccac 100644 --- a/libbcachefs.c +++ b/libbcachefs.c @@ -221,7 +221,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs, /* Member info: */ struct bch_sb_field_members_v2 *mi = - bch2_sb_resize_members_v2(&sb, + bch2_sb_field_resize(&sb, members_v2, (sizeof(*mi) + sizeof(struct bch_member) * nr_devs) / sizeof(u64)); mi->member_bytes = cpu_to_le16(sizeof(struct bch_member)); @@ -270,7 +270,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs, /* Crypt: */ if (opts.encrypted) { struct bch_sb_field_crypt *crypt = - bch2_sb_resize_crypt(&sb, sizeof(*crypt) / sizeof(u64)); + bch2_sb_field_resize(&sb, crypt, sizeof(*crypt) / sizeof(u64)); bch_sb_crypt_init(sb.sb, crypt, opts.passphrase); SET_BCH_SB_ENCRYPTION_TYPE(sb.sb, 1); diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index d1c323f..2d51620 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -1839,7 +1839,7 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, struct bkey_s_c k; struct bkey hole; struct bpos end = POS(ca->dev_idx, bucket_end); - struct bch_member m; + struct bch_member *m; unsigned long last_updated = jiffies; int ret; @@ -1926,8 +1926,8 @@ bkey_err: } mutex_lock(&c->sb_lock); - m = bch2_sb_member_get(c->disk_sb.sb, ca->dev_idx); - SET_BCH_MEMBER_FREESPACE_INITIALIZED(&m, true); + m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx); + SET_BCH_MEMBER_FREESPACE_INITIALIZED(m, true); mutex_unlock(&c->sb_lock); return 0; diff --git a/libbcachefs/bcachefs.h b/libbcachefs/bcachefs.h index e9d07f9..53ffa88 100644 --- a/libbcachefs/bcachefs.h +++ b/libbcachefs/bcachefs.h @@ -746,6 +746,7 @@ struct bch_fs { struct snapshot_table __rcu *snapshots; size_t snapshot_table_size; struct mutex snapshot_table_lock; + struct rw_semaphore snapshot_create_lock; struct work_struct snapshot_delete_work; struct work_struct snapshot_wait_for_pagecache_and_delete_work; diff --git a/libbcachefs/bkey_methods.c b/libbcachefs/bkey_methods.c index be9f012..d9fb1fc 100644 --- a/libbcachefs/bkey_methods.c +++ b/libbcachefs/bkey_methods.c @@ -121,7 +121,6 @@ const struct bkey_ops bch2_bkey_ops[] = { }; const struct bkey_ops bch2_bkey_null_ops = { - .min_val_size = U8_MAX, }; int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k, diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c index 46b6406..a1a4b5f 100644 --- a/libbcachefs/buckets.c +++ b/libbcachefs/buckets.c @@ -473,8 +473,9 @@ static inline int update_replicas_list(struct btree_trans *trans, d = trans->fs_usage_deltas; n = (void *) d->d + d->used; n->delta = sectors; - memcpy((void *) n + offsetof(struct replicas_delta, r), - r, replicas_entry_bytes(r)); + unsafe_memcpy((void *) n + offsetof(struct replicas_delta, r), + r, replicas_entry_bytes(r), + "flexible array member embedded in strcuct with padding"); bch2_replicas_entry_sort(&n->r); d->used += b; return 0; diff --git a/libbcachefs/checksum.c b/libbcachefs/checksum.c index 839f00d..3c761ad 100644 --- a/libbcachefs/checksum.c +++ b/libbcachefs/checksum.c @@ -678,7 +678,7 @@ int bch2_disable_encryption(struct bch_fs *c) mutex_lock(&c->sb_lock); - crypt = bch2_sb_get_crypt(c->disk_sb.sb); + crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); if (!crypt) goto out; @@ -712,7 +712,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) mutex_lock(&c->sb_lock); /* Do we already have an encryption key? */ - if (bch2_sb_get_crypt(c->disk_sb.sb)) + if (bch2_sb_field_get(c->disk_sb.sb, crypt)) goto err; ret = bch2_alloc_ciphers(c); @@ -740,7 +740,8 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) if (ret) goto err; - crypt = bch2_sb_resize_crypt(&c->disk_sb, sizeof(*crypt) / sizeof(u64)); + crypt = bch2_sb_field_resize(&c->disk_sb, crypt, + sizeof(*crypt) / sizeof(u64)); if (!crypt) { ret = -BCH_ERR_ENOSPC_sb_crypt; goto err; @@ -781,7 +782,7 @@ int bch2_fs_encryption_init(struct bch_fs *c) goto out; } - crypt = bch2_sb_get_crypt(c->disk_sb.sb); + crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); if (!crypt) goto out; diff --git a/libbcachefs/counters.c b/libbcachefs/counters.c index 26eb3d8..02a996e 100644 --- a/libbcachefs/counters.c +++ b/libbcachefs/counters.c @@ -48,7 +48,7 @@ static void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb, int bch2_sb_counters_to_cpu(struct bch_fs *c) { - struct bch_sb_field_counters *ctrs = bch2_sb_get_counters(c->disk_sb.sb); + struct bch_sb_field_counters *ctrs = bch2_sb_field_get(c->disk_sb.sb, counters); unsigned int i; unsigned int nr = bch2_sb_counter_nr_entries(ctrs); u64 val = 0; @@ -66,13 +66,13 @@ int bch2_sb_counters_to_cpu(struct bch_fs *c) int bch2_sb_counters_from_cpu(struct bch_fs *c) { - struct bch_sb_field_counters *ctrs = bch2_sb_get_counters(c->disk_sb.sb); + struct bch_sb_field_counters *ctrs = bch2_sb_field_get(c->disk_sb.sb, counters); struct bch_sb_field_counters *ret; unsigned int i; unsigned int nr = bch2_sb_counter_nr_entries(ctrs); if (nr < BCH_COUNTER_NR) { - ret = bch2_sb_resize_counters(&c->disk_sb, + ret = bch2_sb_field_resize(&c->disk_sb, counters, sizeof(*ctrs) / sizeof(u64) + BCH_COUNTER_NR); if (ret) { diff --git a/libbcachefs/disk_groups.c b/libbcachefs/disk_groups.c index 43aad8b..e00133b 100644 --- a/libbcachefs/disk_groups.c +++ b/libbcachefs/disk_groups.c @@ -157,14 +157,13 @@ int bch2_sb_disk_groups_to_cpu(struct bch_fs *c) lockdep_assert_held(&c->sb_lock); - groups = bch2_sb_get_disk_groups(c->disk_sb.sb); + groups = bch2_sb_field_get(c->disk_sb.sb, disk_groups); nr_groups = disk_groups_nr(groups); if (!groups) return 0; - cpu_g = kzalloc(sizeof(*cpu_g) + - sizeof(cpu_g->entries[0]) * nr_groups, GFP_KERNEL); + cpu_g = kzalloc(struct_size(cpu_g, entries, nr_groups), GFP_KERNEL); if (!cpu_g) return -BCH_ERR_ENOMEM_disk_groups_to_cpu; @@ -296,7 +295,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, const char *name, unsigned namelen) { struct bch_sb_field_disk_groups *groups = - bch2_sb_get_disk_groups(sb->sb); + bch2_sb_field_get(sb->sb, disk_groups); unsigned i, nr_groups = disk_groups_nr(groups); struct bch_disk_group *g; @@ -314,7 +313,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, sizeof(struct bch_disk_group) * (nr_groups + 1)) / sizeof(u64); - groups = bch2_sb_resize_disk_groups(sb, u64s); + groups = bch2_sb_field_resize(sb, disk_groups, u64s); if (!groups) return -BCH_ERR_ENOSPC_disk_label_add; @@ -338,7 +337,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, int bch2_disk_path_find(struct bch_sb_handle *sb, const char *name) { struct bch_sb_field_disk_groups *groups = - bch2_sb_get_disk_groups(sb->sb); + bch2_sb_field_get(sb->sb, disk_groups); int v = -1; do { @@ -368,7 +367,7 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name) if (*next == '.') next++; - groups = bch2_sb_get_disk_groups(sb->sb); + groups = bch2_sb_field_get(sb->sb, disk_groups); v = __bch2_disk_group_find(groups, parent, name, len); if (v < 0) @@ -386,7 +385,7 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name) void bch2_disk_path_to_text(struct printbuf *out, struct bch_sb *sb, unsigned v) { struct bch_sb_field_disk_groups *groups = - bch2_sb_get_disk_groups(sb); + bch2_sb_field_get(sb, disk_groups); struct bch_disk_group *g; unsigned nr = 0; u16 path[32]; diff --git a/libbcachefs/extents.h b/libbcachefs/extents.h index 7ee8d03..879e7d2 100644 --- a/libbcachefs/extents.h +++ b/libbcachefs/extents.h @@ -520,6 +520,7 @@ static inline bool bkey_extent_is_allocation(const struct bkey *k) case KEY_TYPE_reflink_v: case KEY_TYPE_inline_data: case KEY_TYPE_indirect_inline_data: + case KEY_TYPE_error: return true; default: return false; @@ -632,6 +633,8 @@ void bch2_bkey_extent_entry_drop(struct bkey_i *, union bch_extent_entry *); static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr ptr) { + struct bch_extent_ptr *dest; + EBUG_ON(bch2_bkey_has_device(bkey_i_to_s(k), ptr.dev)); switch (k->k.type) { @@ -641,10 +644,8 @@ static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr EBUG_ON(bkey_val_u64s(&k->k) >= BKEY_EXTENT_VAL_U64s_MAX); ptr.type = 1 << BCH_EXTENT_ENTRY_ptr; - - memcpy((void *) &k->v + bkey_val_bytes(&k->k), - &ptr, - sizeof(ptr)); + dest = (struct bch_extent_ptr *)((void *) &k->v + bkey_val_bytes(&k->k)); + *dest = ptr; k->k.u64s++; break; default: diff --git a/libbcachefs/fs-ioctl.c b/libbcachefs/fs-ioctl.c index 0679b2f..6040bd3 100644 --- a/libbcachefs/fs-ioctl.c +++ b/libbcachefs/fs-ioctl.c @@ -318,8 +318,8 @@ err: return ret; } -static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, - struct bch_ioctl_subvolume arg) +static long __bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) { struct inode *dir; struct bch_inode_info *inode; @@ -440,6 +440,16 @@ err1: return error; } +static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) +{ + down_write(&c->snapshot_create_lock); + long ret = __bch2_ioctl_subvolume_create(c, filp, arg); + up_write(&c->snapshot_create_lock); + + return ret; +} + static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, struct bch_ioctl_subvolume arg) { diff --git a/libbcachefs/io_misc.c b/libbcachefs/io_misc.c index 32432bd..119834c 100644 --- a/libbcachefs/io_misc.c +++ b/libbcachefs/io_misc.c @@ -287,9 +287,18 @@ int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sec op.v.inum = cpu_to_le64(inum.inum); op.v.new_i_size = cpu_to_le64(new_i_size); - return bch2_trans_run(c, + /* + * Logged ops aren't atomic w.r.t. snapshot creation: creating a + * snapshot while they're in progress, then crashing, will result in the + * resume only proceeding in one of the snapshots + */ + down_read(&c->snapshot_create_lock); + int ret = bch2_trans_run(c, bch2_logged_op_start(trans, &op.k_i) ?: __bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta)); + up_read(&c->snapshot_create_lock); + + return ret; } /* finsert/fcollapse: */ @@ -491,7 +500,16 @@ int bch2_fcollapse_finsert(struct bch_fs *c, subvol_inum inum, op.v.src_offset = cpu_to_le64(offset); op.v.pos = cpu_to_le64(insert ? U64_MAX : offset); - return bch2_trans_run(c, + /* + * Logged ops aren't atomic w.r.t. snapshot creation: creating a + * snapshot while they're in progress, then crashing, will result in the + * resume only proceeding in one of the snapshots + */ + down_read(&c->snapshot_create_lock); + int ret = bch2_trans_run(c, bch2_logged_op_start(trans, &op.k_i) ?: __bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta)); + up_read(&c->snapshot_create_lock); + + return ret; } diff --git a/libbcachefs/journal.c b/libbcachefs/journal.c index fc3dd5b..0e7a9ff 100644 --- a/libbcachefs/journal.c +++ b/libbcachefs/journal.c @@ -1170,9 +1170,9 @@ int bch2_dev_journal_init(struct bch_dev *ca, struct bch_sb *sb) { struct journal_device *ja = &ca->journal; struct bch_sb_field_journal *journal_buckets = - bch2_sb_get_journal(sb); + bch2_sb_field_get(sb, journal); struct bch_sb_field_journal_v2 *journal_buckets_v2 = - bch2_sb_get_journal_v2(sb); + bch2_sb_field_get(sb, journal_v2); unsigned i, nr_bvecs; ja->nr = 0; diff --git a/libbcachefs/journal_sb.c b/libbcachefs/journal_sb.c index 3c5a95e..ae4fb8c 100644 --- a/libbcachefs/journal_sb.c +++ b/libbcachefs/journal_sb.c @@ -194,7 +194,7 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca, if (buckets[i] + 1 != buckets[i + 1]) nr_compacted++; - j = bch2_sb_resize_journal_v2(&ca->disk_sb, + j = bch2_sb_field_resize(&ca->disk_sb, journal_v2, (sizeof(*j) + sizeof(j->d[0]) * nr_compacted) / sizeof(u64)); if (!j) return -BCH_ERR_ENOSPC_sb_journal; diff --git a/libbcachefs/journal_seq_blacklist.c b/libbcachefs/journal_seq_blacklist.c index 1e1a794..f9d9aa9 100644 --- a/libbcachefs/journal_seq_blacklist.c +++ b/libbcachefs/journal_seq_blacklist.c @@ -58,8 +58,8 @@ blacklist_entry_try_merge(struct bch_fs *c, &bl->start[i + 1], sizeof(bl->start[0]) * (nr - i)); - bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb, - sb_blacklist_u64s(nr)); + bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist, + sb_blacklist_u64s(nr)); BUG_ON(!bl); } @@ -79,7 +79,7 @@ int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64 start, u64 end) int ret = 0; mutex_lock(&c->sb_lock); - bl = bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb); + bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist); nr = blacklist_nr_entries(bl); for (i = 0; i < nr; i++) { @@ -100,8 +100,8 @@ int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64 start, u64 end) } } - bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb, - sb_blacklist_u64s(nr + 1)); + bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist, + sb_blacklist_u64s(nr + 1)); if (!bl) { ret = -BCH_ERR_ENOSPC_sb_journal_seq_blacklist; goto out; @@ -158,7 +158,7 @@ bool bch2_journal_seq_is_blacklisted(struct bch_fs *c, u64 seq, int bch2_blacklist_table_initialize(struct bch_fs *c) { struct bch_sb_field_journal_seq_blacklist *bl = - bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb); + bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist); struct journal_seq_blacklist_table *t; unsigned i, nr = blacklist_nr_entries(bl); @@ -281,7 +281,7 @@ retry: return; mutex_lock(&c->sb_lock); - bl = bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb); + bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist); if (!bl) goto out; @@ -306,7 +306,7 @@ retry: bch_info(c, "nr blacklist entries was %u, now %u", nr, new_nr); if (new_nr != nr) { - bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb, + bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist, new_nr ? sb_blacklist_u64s(new_nr) : 0); BUG_ON(new_nr && !bl); diff --git a/libbcachefs/quota.c b/libbcachefs/quota.c index 36de2f0..cb68ae4 100644 --- a/libbcachefs/quota.c +++ b/libbcachefs/quota.c @@ -513,12 +513,12 @@ void bch2_fs_quota_init(struct bch_fs *c) static struct bch_sb_field_quota *bch2_sb_get_or_create_quota(struct bch_sb_handle *sb) { - struct bch_sb_field_quota *sb_quota = bch2_sb_get_quota(sb->sb); + struct bch_sb_field_quota *sb_quota = bch2_sb_field_get(sb->sb, quota); if (sb_quota) return sb_quota; - sb_quota = bch2_sb_resize_quota(sb, sizeof(*sb_quota) / sizeof(u64)); + sb_quota = bch2_sb_field_resize(sb, quota, sizeof(*sb_quota) / sizeof(u64)); if (sb_quota) { unsigned qtype, qc; @@ -536,7 +536,7 @@ static void bch2_sb_quota_read(struct bch_fs *c) struct bch_sb_field_quota *sb_quota; unsigned i, j; - sb_quota = bch2_sb_get_quota(c->disk_sb.sb); + sb_quota = bch2_sb_field_get(c->disk_sb.sb, quota); if (!sb_quota) return; diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c index cd037f2..4cd6606 100644 --- a/libbcachefs/recovery.c +++ b/libbcachefs/recovery.c @@ -35,13 +35,27 @@ #define QSTR(n) { { { .len = strlen(n) } }, .name = n } +static bool btree_id_is_alloc(enum btree_id id) +{ + switch (id) { + case BTREE_ID_alloc: + case BTREE_ID_backpointers: + case BTREE_ID_need_discard: + case BTREE_ID_freespace: + case BTREE_ID_bucket_gens: + return true; + default: + return false; + } +} + /* for -o reconstruct_alloc: */ static void drop_alloc_keys(struct journal_keys *keys) { size_t src, dst; for (src = 0, dst = 0; src < keys->nr; src++) - if (keys->d[src].btree_id != BTREE_ID_alloc) + if (!btree_id_is_alloc(keys->d[src].btree_id)) keys->d[dst++] = keys->d[src]; keys->nr = dst; @@ -332,20 +346,6 @@ static int journal_replay_early(struct bch_fs *c, /* sb clean section: */ -static bool btree_id_is_alloc(enum btree_id id) -{ - switch (id) { - case BTREE_ID_alloc: - case BTREE_ID_backpointers: - case BTREE_ID_need_discard: - case BTREE_ID_freespace: - case BTREE_ID_bucket_gens: - return true; - default: - return false; - } -} - static int read_btree_roots(struct bch_fs *c) { unsigned i; diff --git a/libbcachefs/replicas.c b/libbcachefs/replicas.c index a9a694f..cef2a04 100644 --- a/libbcachefs/replicas.c +++ b/libbcachefs/replicas.c @@ -700,9 +700,9 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c) struct bch_replicas_cpu new_r = { 0, 0, NULL }; int ret = 0; - if ((sb_v1 = bch2_sb_get_replicas(c->disk_sb.sb))) + if ((sb_v1 = bch2_sb_field_get(c->disk_sb.sb, replicas))) ret = __bch2_sb_replicas_to_cpu_replicas(sb_v1, &new_r); - else if ((sb_v0 = bch2_sb_get_replicas_v0(c->disk_sb.sb))) + else if ((sb_v0 = bch2_sb_field_get(c->disk_sb.sb, replicas_v0))) ret = __bch2_sb_replicas_v0_to_cpu_replicas(sb_v0, &new_r); if (ret) return ret; @@ -732,13 +732,13 @@ static int bch2_cpu_replicas_to_sb_replicas_v0(struct bch_fs *c, for_each_cpu_replicas_entry(r, src) bytes += replicas_entry_bytes(src) - 1; - sb_r = bch2_sb_resize_replicas_v0(&c->disk_sb, + sb_r = bch2_sb_field_resize(&c->disk_sb, replicas_v0, DIV_ROUND_UP(bytes, sizeof(u64))); if (!sb_r) return -BCH_ERR_ENOSPC_sb_replicas; bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas); - sb_r = bch2_sb_get_replicas_v0(c->disk_sb.sb); + sb_r = bch2_sb_field_get(c->disk_sb.sb, replicas_v0); memset(&sb_r->entries, 0, vstruct_end(&sb_r->field) - @@ -777,13 +777,13 @@ static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *c, if (!need_v1) return bch2_cpu_replicas_to_sb_replicas_v0(c, r); - sb_r = bch2_sb_resize_replicas(&c->disk_sb, + sb_r = bch2_sb_field_resize(&c->disk_sb, replicas, DIV_ROUND_UP(bytes, sizeof(u64))); if (!sb_r) return -BCH_ERR_ENOSPC_sb_replicas; bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas_v0); - sb_r = bch2_sb_get_replicas(c->disk_sb.sb); + sb_r = bch2_sb_field_get(c->disk_sb.sb, replicas); memset(&sb_r->entries, 0, vstruct_end(&sb_r->field) - @@ -998,8 +998,8 @@ unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev) struct bch_sb_field_replicas_v0 *replicas_v0; unsigned i, data_has = 0; - replicas = bch2_sb_get_replicas(sb); - replicas_v0 = bch2_sb_get_replicas_v0(sb); + replicas = bch2_sb_field_get(sb, replicas); + replicas_v0 = bch2_sb_field_get(sb, replicas_v0); if (replicas) { struct bch_replicas_entry *r; diff --git a/libbcachefs/sb-clean.c b/libbcachefs/sb-clean.c index a3695e5..61203d7 100644 --- a/libbcachefs/sb-clean.c +++ b/libbcachefs/sb-clean.c @@ -137,7 +137,7 @@ struct bch_sb_field_clean *bch2_read_superblock_clean(struct bch_fs *c) int ret; mutex_lock(&c->sb_lock); - sb_clean = bch2_sb_get_clean(c->disk_sb.sb); + sb_clean = bch2_sb_field_get(c->disk_sb.sb, clean); if (fsck_err_on(!sb_clean, c, "superblock marked clean but clean section not present")) { @@ -359,7 +359,7 @@ void bch2_fs_mark_clean(struct bch_fs *c) u64s = sizeof(*sb_clean) / sizeof(u64) + c->journal.entry_u64s_reserved; - sb_clean = bch2_sb_resize_clean(&c->disk_sb, u64s); + sb_clean = bch2_sb_field_resize(&c->disk_sb, clean, u64s); if (!sb_clean) { bch_err(c, "error resizing superblock while setting filesystem clean"); goto out; diff --git a/libbcachefs/sb-members.c b/libbcachefs/sb-members.c index 04bde1a..6dd85bb 100644 --- a/libbcachefs/sb-members.c +++ b/libbcachefs/sb-members.c @@ -16,7 +16,7 @@ static struct bch_member *members_v2_get_mut(struct bch_sb_field_members_v2 *mi, struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i) { - return members_v2_get_mut(bch2_sb_get_members_v2(sb), i); + return members_v2_get_mut(bch2_sb_field_get(sb, members_v2), i); } static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i) @@ -41,22 +41,22 @@ static struct bch_member members_v1_get(struct bch_sb_field_members_v1 *mi, int struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i) { - struct bch_sb_field_members_v2 *mi2 = bch2_sb_get_members_v2(sb); + struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(sb, members_v2); if (mi2) return members_v2_get(mi2, i); - struct bch_sb_field_members_v1 *mi1 = bch2_sb_get_members_v1(sb); + struct bch_sb_field_members_v1 *mi1 = bch2_sb_field_get(sb, members_v1); return members_v1_get(mi1, i); } static int sb_members_v2_resize_entries(struct bch_fs *c) { - struct bch_sb_field_members_v2 *mi = bch2_sb_get_members_v2(c->disk_sb.sb); + struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); if (le16_to_cpu(mi->member_bytes) < sizeof(struct bch_member)) { unsigned u64s = DIV_ROUND_UP((sizeof(*mi) + sizeof(mi->_members[0]) * c->disk_sb.sb->nr_devices), 8); - mi = bch2_sb_resize_members_v2(&c->disk_sb, u64s); + mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s); if (!mi) return -BCH_ERR_ENOSPC_sb_members_v2; @@ -76,12 +76,12 @@ int bch2_members_v2_init(struct bch_fs *c) struct bch_sb_field_members_v1 *mi1; struct bch_sb_field_members_v2 *mi2; - if (!bch2_sb_get_members_v2(c->disk_sb.sb)) { - mi2 = bch2_sb_resize_members_v2(&c->disk_sb, + if (!bch2_sb_field_get(c->disk_sb.sb, members_v2)) { + mi2 = bch2_sb_field_resize(&c->disk_sb, members_v2, DIV_ROUND_UP(sizeof(*mi2) + sizeof(struct bch_member) * c->sb.nr_devices, sizeof(u64))); - mi1 = bch2_sb_get_members_v1(c->disk_sb.sb); + mi1 = bch2_sb_field_get(c->disk_sb.sb, members_v1); memcpy(&mi2->_members[0], &mi1->_members[0], BCH_MEMBER_V1_BYTES * c->sb.nr_devices); memset(&mi2->pad[0], 0, sizeof(mi2->pad)); @@ -96,13 +96,13 @@ int bch_members_cpy_v2_v1(struct bch_sb_handle *disk_sb) struct bch_sb_field_members_v1 *mi1; struct bch_sb_field_members_v2 *mi2; - mi1 = bch2_sb_resize_members_v1(disk_sb, + mi1 = bch2_sb_field_resize(disk_sb, members_v1, DIV_ROUND_UP(sizeof(*mi1) + BCH_MEMBER_V1_BYTES * disk_sb->sb->nr_devices, sizeof(u64))); if (!mi1) return -BCH_ERR_ENOSPC_sb_members; - mi2 = bch2_sb_get_members_v2(disk_sb->sb); + mi2 = bch2_sb_field_get(disk_sb->sb, members_v2); for (unsigned i = 0; i < disk_sb->sb->nr_devices; i++) memcpy(members_v1_get_mut(mi1, i), members_v2_get_mut(mi2, i), BCH_MEMBER_V1_BYTES); @@ -283,7 +283,7 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb, struct bch_sb_field *f) { struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1); - struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb); + struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); unsigned i; for (i = 0; i < sb->nr_devices; i++) { @@ -301,7 +301,7 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb, struct bch_sb_field *f) { struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2); - struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb); + struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); unsigned i; for (i = 0; i < sb->nr_devices; i++) { diff --git a/libbcachefs/snapshot.c b/libbcachefs/snapshot.c index 3ecc17b..4982468 100644 --- a/libbcachefs/snapshot.c +++ b/libbcachefs/snapshot.c @@ -1288,6 +1288,9 @@ static inline u32 bch2_snapshot_nth_parent_skip(struct bch_fs *c, u32 id, u32 n, snapshot_id_list *skip) { rcu_read_lock(); + while (snapshot_list_has_id(skip, id)) + id = __bch2_snapshot_parent(c, id); + while (n--) { do { id = __bch2_snapshot_parent(c, id); @@ -1444,6 +1447,8 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) } } + down_write(&c->snapshot_create_lock); + for_each_btree_key(trans, iter, BTREE_ID_snapshots, POS_MIN, 0, k, ret) { u32 snapshot = k.k->p.offset; @@ -1454,6 +1459,9 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) } bch2_trans_iter_exit(trans, &iter); + if (ret) + goto err_create_lock; + /* * Fixing children of deleted snapshots can't be done completely * atomically, if we crash between here and when we delete the interior @@ -1464,14 +1472,14 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) NULL, NULL, BTREE_INSERT_NOFAIL, bch2_fix_child_of_deleted_snapshot(trans, &iter, k, &deleted_interior)); if (ret) - goto err; + goto err_create_lock; darray_for_each(deleted, i) { ret = commit_do(trans, NULL, NULL, 0, bch2_snapshot_node_delete(trans, *i)); if (ret) { bch_err_msg(c, ret, "deleting snapshot %u", *i); - goto err; + goto err_create_lock; } } @@ -1480,11 +1488,13 @@ int bch2_delete_dead_snapshots(struct bch_fs *c) bch2_snapshot_node_delete(trans, *i)); if (ret) { bch_err_msg(c, ret, "deleting snapshot %u", *i); - goto err; + goto err_create_lock; } } clear_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags); +err_create_lock: + up_write(&c->snapshot_create_lock); err: darray_exit(&deleted_interior); darray_exit(&deleted); diff --git a/libbcachefs/super-io.c b/libbcachefs/super-io.c index 4498e24..332d41e 100644 --- a/libbcachefs/super-io.c +++ b/libbcachefs/super-io.c @@ -96,7 +96,7 @@ const char * const bch2_sb_fields[] = { static int bch2_sb_field_validate(struct bch_sb *, struct bch_sb_field *, struct printbuf *); -struct bch_sb_field *bch2_sb_field_get(struct bch_sb *sb, +struct bch_sb_field *bch2_sb_field_get_id(struct bch_sb *sb, enum bch_sb_field_type type) { struct bch_sb_field *f; @@ -151,7 +151,7 @@ static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb_handle *sb, void bch2_sb_field_delete(struct bch_sb_handle *sb, enum bch_sb_field_type type) { - struct bch_sb_field *f = bch2_sb_field_get(sb->sb, type); + struct bch_sb_field *f = bch2_sb_field_get_id(sb->sb, type); if (f) __bch2_sb_field_resize(sb, f, 0); @@ -225,11 +225,11 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) return 0; } -struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb, +struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *sb, enum bch_sb_field_type type, unsigned u64s) { - struct bch_sb_field *f = bch2_sb_field_get(sb->sb, type); + struct bch_sb_field *f = bch2_sb_field_get_id(sb->sb, type); ssize_t old_u64s = f ? le32_to_cpu(f->u64s) : 0; ssize_t d = -old_u64s + u64s; @@ -255,7 +255,7 @@ struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb, } } - f = bch2_sb_field_get(sb->sb, type); + f = bch2_sb_field_get_id(sb->sb, type); f = __bch2_sb_field_resize(sb, f, u64s); if (f) f->type = cpu_to_le32(type); @@ -458,7 +458,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out, } /* members must be validated first: */ - mi = bch2_sb_get_members_v1(sb); + mi = bch2_sb_field_get(sb, members_v1); if (!mi) { prt_printf(out, "Invalid superblock: member info area missing"); return -BCH_ERR_invalid_sb_members_missing; @@ -546,8 +546,8 @@ static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) if ((1U << i) & BCH_SINGLE_DEVICE_SB_FIELDS) continue; - src_f = bch2_sb_field_get(src, i); - dst_f = bch2_sb_field_get(dst, i); + src_f = bch2_sb_field_get_id(src, i); + dst_f = bch2_sb_field_get_id(dst, i); d = (src_f ? le32_to_cpu(src_f->u64s) : 0) - (dst_f ? le32_to_cpu(dst_f->u64s) : 0); @@ -559,7 +559,7 @@ static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) return ret; dst = dst_handle->sb; - dst_f = bch2_sb_field_get(dst, i); + dst_f = bch2_sb_field_get_id(dst, i); } dst_f = __bch2_sb_field_resize(dst_handle, dst_f, diff --git a/libbcachefs/super-io.h b/libbcachefs/super-io.h index f7e9099..b0d8584 100644 --- a/libbcachefs/super-io.h +++ b/libbcachefs/super-io.h @@ -23,31 +23,19 @@ u64 bch2_upgrade_recovery_passes(struct bch_fs *c, unsigned, unsigned); -struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type); -struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *, - enum bch_sb_field_type, unsigned); -void bch2_sb_field_delete(struct bch_sb_handle *, enum bch_sb_field_type); - #define field_to_type(_f, _name) \ container_of_or_null(_f, struct bch_sb_field_##_name, field) -#define x(_name, _nr) \ -static inline struct bch_sb_field_##_name * \ -bch2_sb_get_##_name(struct bch_sb *sb) \ -{ \ - return field_to_type(bch2_sb_field_get(sb, \ - BCH_SB_FIELD_##_name), _name); \ -} \ - \ -static inline struct bch_sb_field_##_name * \ -bch2_sb_resize_##_name(struct bch_sb_handle *sb, unsigned u64s) \ -{ \ - return field_to_type(bch2_sb_field_resize(sb, \ - BCH_SB_FIELD_##_name, u64s), _name); \ -} +struct bch_sb_field *bch2_sb_field_get_id(struct bch_sb *, enum bch_sb_field_type); +#define bch2_sb_field_get(_sb, _name) \ + field_to_type(bch2_sb_field_get_id(_sb, BCH_SB_FIELD_##_name), _name) -BCH_SB_FIELDS() -#undef x +struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *, + enum bch_sb_field_type, unsigned); +#define bch2_sb_field_resize(_sb, _name, _u64s) \ + field_to_type(bch2_sb_field_resize_id(_sb, BCH_SB_FIELD_##_name, _u64s), _name) + +void bch2_sb_field_delete(struct bch_sb_handle *, enum bch_sb_field_type); extern const char * const bch2_sb_fields[]; diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 2014f78..0e85c22 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -720,6 +720,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) mutex_init(&c->bio_bounce_pages_lock); mutex_init(&c->snapshot_table_lock); + init_rwsem(&c->snapshot_create_lock); spin_lock_init(&c->btree_write_error_lock); @@ -1630,9 +1631,9 @@ int bch2_dev_add(struct bch_fs *c, const char *path) goto err_unlock; } - mi = bch2_sb_get_members_v2(ca->disk_sb.sb); + mi = bch2_sb_field_get(ca->disk_sb.sb, members_v2); - if (!bch2_sb_resize_members_v2(&ca->disk_sb, + if (!bch2_sb_field_resize(&ca->disk_sb, members_v2, le32_to_cpu(mi->field.u64s) + sizeof(dev_mi) / sizeof(u64))) { ret = -BCH_ERR_ENOSPC_sb_members; @@ -1656,7 +1657,7 @@ have_slot: u64s = DIV_ROUND_UP(sizeof(struct bch_sb_field_members_v2) + le16_to_cpu(mi->member_bytes) * nr_devices, sizeof(u64)); - mi = bch2_sb_resize_members_v2(&c->disk_sb, u64s); + mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s); if (!mi) { ret = -BCH_ERR_ENOSPC_sb_members; bch_err_msg(c, ret, "setting up new superblock"); diff --git a/libbcachefs/super_types.h b/libbcachefs/super_types.h index 597a8db..78d6138 100644 --- a/libbcachefs/super_types.h +++ b/libbcachefs/super_types.h @@ -46,7 +46,7 @@ struct bch_disk_group_cpu { struct bch_disk_groups_cpu { struct rcu_head rcu; unsigned nr; - struct bch_disk_group_cpu entries[]; + struct bch_disk_group_cpu entries[] __counted_by(nr); }; #endif /* _BCACHEFS_SUPER_TYPES_H */ diff --git a/rust-src/bch_bindgen/src/bcachefs.rs b/rust-src/bch_bindgen/src/bcachefs.rs index fa8dbde..8e897c0 100644 --- a/rust-src/bch_bindgen/src/bcachefs.rs +++ b/rust-src/bch_bindgen/src/bcachefs.rs @@ -43,7 +43,7 @@ impl PartialEq for bch_sb { impl bch_sb { pub fn crypt(&self) -> Option<&bch_sb_field_crypt> { unsafe { - let ptr = bch2_sb_field_get( + let ptr = bch2_sb_field_get_id( self as *const _ as *mut _, bch_sb_field_type::BCH_SB_FIELD_crypt, ) as *const u8; -- 2.39.2