diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-09-29 01:15:33 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:10:16 -0400 |
commit | 37fad9497f5d37d89ed06faa64d580d1451be664 (patch) | |
tree | d6d54fcf01befddf0534ca915a3bfb60383e1a38 /fs/bcachefs/snapshot.c | |
parent | 1e2d399970ca1d66fa1c715f4d80a0251f2a122e (diff) | |
download | lwn-37fad9497f5d37d89ed06faa64d580d1451be664.tar.gz lwn-37fad9497f5d37d89ed06faa64d580d1451be664.zip |
bcachefs: snapshot_create_lock
Add a new lock for snapshot creation - this addresses a few races with
logged operations and snapshot deletion.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/snapshot.c')
-rw-r--r-- | fs/bcachefs/snapshot.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index b8c32d1cbd76..4982468bfe11 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -1447,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; @@ -1457,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 @@ -1467,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; } } @@ -1483,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); |