summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-12-03 14:27:20 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2020-12-16 15:29:10 -0500
commitb37e02c2894c6447d3770a004beae9d9446f6452 (patch)
tree5c92eef47336739f8deec41b99a5436804103639
parent6110a147794e3f8b1a201f0cb4dc41b39533780c (diff)
bcachefs: Flag inodes that had btree update errors
On write error, the vfs inode's i_size may be inconsistent with the btree inode's i_size - flag this so we don't have spurious assertions. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/fs-io.c13
-rw-r--r--fs/bcachefs/fs.c1
-rw-r--r--fs/bcachefs/fs.h7
3 files changed, 19 insertions, 2 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 1a3eeb83af67..1de7b92dec9c 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -1033,6 +1033,8 @@ static void bch2_writepage_io_done(struct closure *cl)
unsigned i;
if (io->op.error) {
+ set_bit(EI_INODE_ERROR, &io->inode->ei_flags);
+
bio_for_each_segment_all(bvec, bio, iter) {
struct bch_page_state *s;
@@ -1922,7 +1924,13 @@ loop:
bio_for_each_segment_all(bv, bio, iter)
put_page(bv->bv_page);
- if (!dio->iter.count || dio->op.error)
+
+ if (dio->op.error) {
+ set_bit(EI_INODE_ERROR, &inode->ei_flags);
+ break;
+ }
+
+ if (!dio->iter.count)
break;
bio_reset(bio);
@@ -2310,7 +2318,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
if (ret)
goto err;
- BUG_ON(inode->v.i_size < inode_u.bi_size);
+ WARN_ON(!test_bit(EI_INODE_ERROR, &inode->ei_flags) &&
+ inode->v.i_size < inode_u.bi_size);
if (iattr->ia_size > inode->v.i_size) {
ret = bch2_extend(inode, &inode_u, iattr);
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index f3f6fe6c776a..e3edca4d265b 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -1151,6 +1151,7 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
inode->v.i_generation = bi->bi_generation;
inode->v.i_size = bi->bi_size;
+ inode->ei_flags = 0;
inode->ei_journal_seq = 0;
inode->ei_quota_reserved = 0;
inode->ei_str_hash = bch2_hash_info_init(c, bi);
diff --git a/fs/bcachefs/fs.h b/fs/bcachefs/fs.h
index 4ee1ac994420..3df85ffb450c 100644
--- a/fs/bcachefs/fs.h
+++ b/fs/bcachefs/fs.h
@@ -33,6 +33,7 @@ void bch2_pagecache_block_get(struct pagecache_lock *);
struct bch_inode_info {
struct inode v;
+ unsigned long ei_flags;
struct mutex ei_update_lock;
u64 ei_journal_seq;
@@ -50,6 +51,12 @@ struct bch_inode_info {
struct bch_inode_unpacked ei_inode;
};
+/*
+ * Set if we've gotten a btree error for this inode, and thus the vfs inode and
+ * btree inode may be inconsistent:
+ */
+#define EI_INODE_ERROR 0
+
#define to_bch_ei(_inode) \
container_of_or_null(_inode, struct bch_inode_info, v)