aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-10-18 21:57:11 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-18 22:14:53 -0400
commit6a34032417d9bb90ead6f3b7bf891347bc4a1ed3 (patch)
treef2c1cf29f8651cc5ac41504a441a15d39b22f807
parent9f98746bfcd5159307237f7a491fd79db02d8bf3 (diff)
downloadbcachefs-tools-6a34032417d9bb90ead6f3b7bf891347bc4a1ed3.tar.gz
Update bcachefs sources to a180af9dd349 bcachefs: Refactor memcpy into direct assignment
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--.bcachefs_revision2
-rw-r--r--cmd_format.c2
-rw-r--r--cmd_key.c4
-rw-r--r--crypto.c4
-rw-r--r--include/linux/compiler.h1
-rw-r--r--libbcachefs.c4
-rw-r--r--libbcachefs/alloc_background.c6
-rw-r--r--libbcachefs/bcachefs.h1
-rw-r--r--libbcachefs/bkey_methods.c1
-rw-r--r--libbcachefs/buckets.c5
-rw-r--r--libbcachefs/checksum.c9
-rw-r--r--libbcachefs/counters.c6
-rw-r--r--libbcachefs/disk_groups.c15
-rw-r--r--libbcachefs/extents.h9
-rw-r--r--libbcachefs/fs-ioctl.c14
-rw-r--r--libbcachefs/io_misc.c22
-rw-r--r--libbcachefs/journal.c4
-rw-r--r--libbcachefs/journal_sb.c2
-rw-r--r--libbcachefs/journal_seq_blacklist.c16
-rw-r--r--libbcachefs/quota.c6
-rw-r--r--libbcachefs/recovery.c30
-rw-r--r--libbcachefs/replicas.c16
-rw-r--r--libbcachefs/sb-clean.c4
-rw-r--r--libbcachefs/sb-members.c24
-rw-r--r--libbcachefs/snapshot.c16
-rw-r--r--libbcachefs/super-io.c18
-rw-r--r--libbcachefs/super-io.h30
-rw-r--r--libbcachefs/super.c7
-rw-r--r--libbcachefs/super_types.h2
-rw-r--r--rust-src/bch_bindgen/src/bcachefs.rs2
30 files changed, 156 insertions, 126 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index 48318a75..6f98bb84 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-7bf1ac0d46ebede68561e0476f7af9c07ac21de8
+a180af9dd349d9819b13af43f877bea4f94c1c79
diff --git a/cmd_format.c b/cmd_format.c
index 42f3fc6c..954d40fe 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 d3e5d7bd..96206c4c 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 4e4d15a9..32671bd8 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 b9486dbe..61beee94 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 499badb1..577ccac1 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 d1c323fd..2d516207 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 e9d07f9f..53ffa88c 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 be9f012f..d9fb1fc8 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 46b6406d..a1a4b5fe 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 839f00dc..3c761ad6 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 26eb3d82..02a996e0 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 43aad8ba..e00133b6 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 7ee8d031..879e7d21 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 0679b2f7..6040bd3f 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 32432bdd..119834cb 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 fc3dd5be..0e7a9ffa 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 3c5a95e2..ae4fb8c3 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 1e1a7940..f9d9aa95 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 36de2f07..cb68ae44 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 cd037f2e..4cd66065 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 a9a694fb..cef2a044 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 a3695e56..61203d7c 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 04bde1aa..6dd85bb9 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 3ecc17b8..4982468b 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 4498e24d..332d41e1 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 f7e90999..b0d8584f 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 2014f781..0e85c226 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 597a8db7..78d6138d 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 fa8dbdeb..8e897c08 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;