aboutsummaryrefslogtreecommitdiff
path: root/fs/bcachefs/io.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-11-03 22:35:34 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:16 -0400
commit1db84979c7b640c15abae8a013485546bcca3623 (patch)
tree2ea1805ad51b68add143e97838519c5a27018889 /fs/bcachefs/io.c
parent34d74830b25c7d0b4f6affda90225e4849296255 (diff)
bcachefs: Update inode on every write
This is going to be a performance regression until we get the btree key cache re-enabled - but it's needed for fixing fsync. Upcoming patches will record the journal_seq an inode was updated at in the inode itself. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/io.c')
-rw-r--r--fs/bcachefs/io.c76
1 files changed, 40 insertions, 36 deletions
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c
index bf04b61ae882..ca4e7a5a64b9 100644
--- a/fs/bcachefs/io.c
+++ b/fs/bcachefs/io.c
@@ -279,7 +279,10 @@ int bch2_extent_update(struct btree_trans *trans,
{
/* this must live until after bch2_trans_commit(): */
struct bkey_inode_buf inode_p;
+ struct btree_iter inode_iter = { NULL };
+ struct bch_inode_unpacked inode_u;
struct bpos next_pos;
+ struct bkey_s_c inode;
bool extending = false, usage_increasing;
s64 i_sectors_delta = 0, disk_sectors_delta = 0;
int ret;
@@ -298,6 +301,9 @@ int bch2_extent_update(struct btree_trans *trans,
if (ret)
return ret;
+ new_i_size = min(k->k.p.offset << 9, new_i_size);
+ next_pos = k->k.p;
+
ret = bch2_sum_sector_overwrites(trans, iter, k,
&extending,
&usage_increasing,
@@ -306,14 +312,11 @@ int bch2_extent_update(struct btree_trans *trans,
if (ret)
return ret;
- if (!usage_increasing)
- check_enospc = false;
-
if (disk_res &&
disk_sectors_delta > (s64) disk_res->sectors) {
ret = bch2_disk_reservation_add(trans->c, disk_res,
disk_sectors_delta - disk_res->sectors,
- !check_enospc
+ !check_enospc || !usage_increasing
? BCH_DISK_RESERVATION_NOFAIL : 0);
if (ret)
return ret;
@@ -323,26 +326,25 @@ int bch2_extent_update(struct btree_trans *trans,
? min(k->k.p.offset << 9, new_i_size)
: 0;
- if (i_sectors_delta || new_i_size) {
- struct btree_iter inode_iter;
- struct bch_inode_unpacked inode_u;
+ bch2_trans_iter_init(trans, &inode_iter, BTREE_ID_inodes,
+ SPOS(0, inum.inum, iter->snapshot),
+ BTREE_ITER_INTENT|
+ (trans->c->opts.inodes_use_key_cache
+ ? BTREE_ITER_CACHED
+ : 0));
+ inode = bch2_btree_iter_peek_slot(&inode_iter);
+ ret = bkey_err(inode);
+ if (ret)
+ goto err;
- ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inum,
- BTREE_ITER_INTENT);
- if (ret)
- return ret;
+ ret = inode.k->type == KEY_TYPE_inode ? 0 : -ENOENT;
+ if (ret)
+ goto err;
- /*
- * XXX:
- * writeback can race a bit with truncate, because truncate
- * first updates the inode then truncates the pagecache. This is
- * ugly, but lets us preserve the invariant that the in memory
- * i_size is always >= the on disk i_size.
- *
- BUG_ON(new_i_size > inode_u.bi_size &&
- (inode_u.bi_flags & BCH_INODE_I_SIZE_DIRTY));
- */
- BUG_ON(new_i_size > inode_u.bi_size && !extending);
+ if (i_sectors_delta || new_i_size) {
+ ret = bch2_inode_unpack(bkey_s_c_to_inode(inode), &inode_u);
+ if (ret)
+ goto err;
if (!(inode_u.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
new_i_size > inode_u.bi_size)
@@ -351,36 +353,38 @@ int bch2_extent_update(struct btree_trans *trans,
new_i_size = 0;
inode_u.bi_sectors += i_sectors_delta;
+ }
- if (i_sectors_delta || new_i_size) {
- bch2_inode_pack(trans->c, &inode_p, &inode_u);
-
- inode_p.inode.k.p.snapshot = iter->snapshot;
+ if (i_sectors_delta || new_i_size) {
+ bch2_inode_pack(trans->c, &inode_p, &inode_u);
- ret = bch2_trans_update(trans, &inode_iter,
- &inode_p.inode.k_i, 0);
- }
+ inode_p.inode.k.p.snapshot = iter->snapshot;
- bch2_trans_iter_exit(trans, &inode_iter);
+ ret = bch2_trans_update(trans, &inode_iter,
+ &inode_p.inode.k_i, 0);
+ } else {
+ bkey_reassemble(&inode_p.inode.k_i, inode);
+ ret = bch2_trans_update(trans, &inode_iter,
+ &inode_p.inode.k_i,
+ BTREE_UPDATE_NOJOURNAL);
if (ret)
- return ret;
+ goto err;
}
- next_pos = k->k.p;
-
ret = bch2_trans_update(trans, iter, k, 0) ?:
bch2_trans_commit(trans, disk_res, journal_seq,
BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL);
- BUG_ON(ret == -ENOSPC);
+err:
+ bch2_trans_iter_exit(trans, &inode_iter);
if (ret)
return ret;
- bch2_btree_iter_set_pos(iter, next_pos);
-
if (i_sectors_delta_total)
*i_sectors_delta_total += i_sectors_delta;
+ bch2_btree_iter_set_pos(iter, next_pos);
+
return 0;
}