bcachefs: check for inode.bi_sectors underflow
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 1 May 2025 03:56:00 +0000 (23:56 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 1 May 2025 10:19:58 +0000 (06:19 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/io_write.c
fs/bcachefs/sb-errors_format.h

index a418fa6..c1237da 100644 (file)
@@ -255,6 +255,27 @@ static inline int bch2_extent_update_i_size_sectors(struct btree_trans *trans,
        }
 
        if (i_sectors_delta) {
+               s64 bi_sectors = le64_to_cpu(inode->v.bi_sectors);
+               if (unlikely(bi_sectors + i_sectors_delta < 0)) {
+                       struct bch_fs *c = trans->c;
+                       struct printbuf buf = PRINTBUF;
+                       bch2_log_msg_start(c, &buf);
+                       prt_printf(&buf, "inode %llu i_sectors underflow: %lli + %lli < 0",
+                                  extent_iter->pos.inode, bi_sectors, i_sectors_delta);
+
+                       bool repeat = false, print = false, suppress = false;
+                       bch2_count_fsck_err(c, inode_i_sectors_underflow, buf.buf,
+                                           &repeat, &print, &suppress);
+                       if (print)
+                               bch2_print_str(c, buf.buf);
+                       printbuf_exit(&buf);
+
+                       if (i_sectors_delta < 0)
+                               i_sectors_delta = -bi_sectors;
+                       else
+                               i_sectors_delta = 0;
+               }
+
                le64_add_cpu(&inode->v.bi_sectors, i_sectors_delta);
                inode_update_flags = 0;
        }
index 582e77c..822a0b4 100644 (file)
@@ -236,6 +236,7 @@ enum bch_fsck_flags {
        x(inode_has_child_snapshots_wrong,                      287,    0)              \
        x(inode_unreachable,                                    210,    FSCK_AUTOFIX)   \
        x(inode_journal_seq_in_future,                          299,    FSCK_AUTOFIX)   \
+       x(inode_i_sectors_underflow,                            312,    FSCK_AUTOFIX)   \
        x(vfs_inode_i_blocks_underflow,                         311,    FSCK_AUTOFIX)   \
        x(deleted_inode_but_clean,                              211,    FSCK_AUTOFIX)   \
        x(deleted_inode_missing,                                212,    FSCK_AUTOFIX)   \
@@ -320,7 +321,7 @@ enum bch_fsck_flags {
        x(dirent_stray_data_after_cf_name,                      305,    0)              \
        x(rebalance_work_incorrectly_set,                       309,    FSCK_AUTOFIX)   \
        x(rebalance_work_incorrectly_unset,                     310,    FSCK_AUTOFIX)   \
-       x(MAX,                                                  312,    0)
+       x(MAX,                                                  313,    0)
 
 enum bch_sb_error_id {
 #define x(t, n, ...) BCH_FSCK_ERR_##t = n,