summaryrefslogtreecommitdiff
path: root/fs/bcachefs/io_misc.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-09-10 16:42:30 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:10:12 -0400
commitb030e262b517b6bddc4bfa88ed8d335ef9de7671 (patch)
treeb0a1aea8f9773b926352e091f9d4a2c8ef31fcf5 /fs/bcachefs/io_misc.c
parentaaad530ac6b1c836de4a29d227ab68be97e39a73 (diff)
bcachefs: Log truncate operations
Previously, we guaranteed atomicity of truncate after unclean shutdown with the BCH_INODE_I_SIZE_DIRTY flag - which required a full scan of the inodes btree. Recently the deleted inodes btree was added so that we no longer have to scan for deleted inodes, but truncate was unfinished and that change left it broken. This patch uses the new logged operations btree to fix truncate atomicity; we now log an operation that can be replayed at the start of a truncate. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/io_misc.c')
-rw-r--r--fs/bcachefs/io_misc.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c
index 1afea613df4a..327b3dd642de 100644
--- a/fs/bcachefs/io_misc.c
+++ b/fs/bcachefs/io_misc.c
@@ -15,6 +15,7 @@
#include "inode.h"
#include "io_misc.h"
#include "io_write.h"
+#include "logged_ops.h"
#include "subvolume.h"
/* Overwrites whatever was present with zeroes: */
@@ -217,6 +218,17 @@ int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
return ret;
}
+/* truncate: */
+
+void bch2_logged_op_truncate_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
+{
+ struct bkey_s_c_logged_op_truncate op = bkey_s_c_to_logged_op_truncate(k);
+
+ prt_printf(out, "subvol=%u", le32_to_cpu(op.v->subvol));
+ prt_printf(out, " inum=%llu", le64_to_cpu(op.v->inum));
+ prt_printf(out, " new_i_size=%llu", le64_to_cpu(op.v->new_i_size));
+}
+
static int truncate_set_isize(struct btree_trans *trans,
subvol_inum inum,
u64 new_i_size)
@@ -233,36 +245,54 @@ static int truncate_set_isize(struct btree_trans *trans,
return ret;
}
-int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sectors_delta)
+static int __bch2_resume_logged_op_truncate(struct btree_trans *trans,
+ struct bkey_i *op_k,
+ u64 *i_sectors_delta)
{
- struct btree_trans trans;
+ struct bch_fs *c = trans->c;
struct btree_iter fpunch_iter;
+ struct bkey_i_logged_op_truncate *op = bkey_i_to_logged_op_truncate(op_k);
+ subvol_inum inum = { le32_to_cpu(op->v.subvol), le64_to_cpu(op->v.inum) };
+ u64 new_i_size = le64_to_cpu(op->v.new_i_size);
int ret;
- bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
- bch2_trans_iter_init(&trans, &fpunch_iter, BTREE_ID_extents,
- POS(inum.inum, round_up(new_i_size, block_bytes(c)) >> 9),
- BTREE_ITER_INTENT);
-
- ret = commit_do(&trans, NULL, NULL, BTREE_INSERT_NOFAIL,
- truncate_set_isize(&trans, inum, new_i_size));
+ ret = commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
+ truncate_set_isize(trans, inum, new_i_size));
if (ret)
goto err;
- ret = bch2_fpunch_at(&trans, &fpunch_iter, inum, U64_MAX, i_sectors_delta);
+ bch2_trans_iter_init(trans, &fpunch_iter, BTREE_ID_extents,
+ POS(inum.inum, round_up(new_i_size, block_bytes(c)) >> 9),
+ BTREE_ITER_INTENT);
+ ret = bch2_fpunch_at(trans, &fpunch_iter, inum, U64_MAX, i_sectors_delta);
+ bch2_trans_iter_exit(trans, &fpunch_iter);
+
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0;
- if (ret)
- goto err;
err:
- bch2_trans_iter_exit(&trans, &fpunch_iter);
- bch2_trans_exit(&trans);
-
- bch2_fs_fatal_err_on(ret, c, "%s: error truncating %u:%llu: %s",
- __func__, inum.subvol, inum.inum, bch2_err_str(ret));
+ bch2_logged_op_finish(trans, op_k);
return ret;
}
+int bch2_resume_logged_op_truncate(struct btree_trans *trans, struct bkey_i *op_k)
+{
+ return __bch2_resume_logged_op_truncate(trans, op_k, NULL);
+}
+
+int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sectors_delta)
+{
+ struct bkey_i_logged_op_truncate op;
+
+ bkey_logged_op_truncate_init(&op.k_i);
+ op.v.subvol = cpu_to_le32(inum.subvol);
+ op.v.inum = cpu_to_le64(inum.inum);
+ op.v.new_i_size = cpu_to_le64(new_i_size);
+
+ return bch2_trans_run(c,
+ bch2_logged_op_start(&trans, &op.k_i) ?:
+ __bch2_resume_logged_op_truncate(&trans, &op.k_i, i_sectors_delta));
+}
+
static int adjust_i_size(struct btree_trans *trans, subvol_inum inum, u64 offset, s64 len)
{
struct btree_iter iter;