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/io_misc.c | |
parent | 1e2d399970ca1d66fa1c715f4d80a0251f2a122e (diff) | |
download | linux-37fad9497f5d37d89ed06faa64d580d1451be664.tar.gz linux-37fad9497f5d37d89ed06faa64d580d1451be664.tar.bz2 linux-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/io_misc.c')
-rw-r--r-- | fs/bcachefs/io_misc.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c index 32432bdddac4..119834cb8f9e 100644 --- a/fs/bcachefs/io_misc.c +++ b/fs/bcachefs/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; } |