bcachefs: Flag inodes that had btree update errors
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 3 Dec 2020 19:27:20 +0000 (14:27 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:49 +0000 (17:08 -0400)
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>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs-io.c
fs/bcachefs/fs.c
fs/bcachefs/fs.h

index c10192e2a688058f838657fcf71b61080e7da91e..2d31547446ace60d15fbf719442b91f8660c6274 100644 (file)
@@ -994,6 +994,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;
 
@@ -1916,7 +1918,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, NULL, REQ_OP_WRITE);
@@ -2306,7 +2314,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);
index a3810493826b1681975accaa46669381f870117d..7cd3f243d1ed32a79c5bc285401b03cb1852ff1f 100644 (file)
@@ -1161,6 +1161,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);
index 7c095b856b056673d17ed1655941670ff06f8278..8c2796aa7abf5ee5737dc384d4a1af35f2b98810 100644 (file)
@@ -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;
@@ -49,6 +50,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)