Merge tag 'for-5.15-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Sep 2021 21:39:41 +0000 (14:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Sep 2021 21:39:41 +0000 (14:39 -0700)
Pull btrfs fixes from David Sterba:

 - regression fix for leak of transaction handle after verity rollback
   failure

 - properly reset device last error between mounts

 - improve one error handling case when checksumming bios

 - fixup confusing displayed size of space info free space

* tag 'for-5.15-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: prevent __btrfs_dump_space_info() to underflow its free space
  btrfs: fix mount failure due to past and transient device flush error
  btrfs: fix transaction handle leak after verity rollback failure
  btrfs: replace BUG_ON() in btrfs_csum_one_bio() with proper error handling

fs/btrfs/file-item.c
fs/btrfs/space-info.c
fs/btrfs/verity.c
fs/btrfs/volumes.c

index 2673c6ba7a4e30eb70a4feae2c7e86feae2c16f4..0b9401a5afd3335e8cd108f5006284e74a81a340 100644 (file)
@@ -665,7 +665,18 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
 
                if (!ordered) {
                        ordered = btrfs_lookup_ordered_extent(inode, offset);
-                       BUG_ON(!ordered); /* Logic error */
+                       /*
+                        * The bio range is not covered by any ordered extent,
+                        * must be a code logic error.
+                        */
+                       if (unlikely(!ordered)) {
+                               WARN(1, KERN_WARNING
+                       "no ordered extent for root %llu ino %llu offset %llu\n",
+                                    inode->root->root_key.objectid,
+                                    btrfs_ino(inode), offset);
+                               kvfree(sums);
+                               return BLK_STS_IOERR;
+                       }
                }
 
                nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
index 5ada02e0e629fe8b43437b6296b27a8ffa167b7f..aa5be0b24987ad4366854d6d4ad59c2d096321a0 100644 (file)
@@ -414,9 +414,10 @@ static void __btrfs_dump_space_info(struct btrfs_fs_info *fs_info,
 {
        lockdep_assert_held(&info->lock);
 
-       btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull",
+       /* The free space could be negative in case of overcommit */
+       btrfs_info(fs_info, "space_info %llu has %lld free, is %sfull",
                   info->flags,
-                  info->total_bytes - btrfs_space_info_used(info, true),
+                  (s64)(info->total_bytes - btrfs_space_info_used(info, true)),
                   info->full ? "" : "not ");
        btrfs_info(fs_info,
                "space_info total=%llu, used=%llu, pinned=%llu, reserved=%llu, may_use=%llu, readonly=%llu zone_unusable=%llu",
index 28d443d3ef93ad710fe887fa97040bb8b5998f15..4968535dfff0aebb0801d440d2417b69dffeb34f 100644 (file)
@@ -451,7 +451,7 @@ static int del_orphan(struct btrfs_trans_handle *trans, struct btrfs_inode *inod
  */
 static int rollback_verity(struct btrfs_inode *inode)
 {
-       struct btrfs_trans_handle *trans;
+       struct btrfs_trans_handle *trans = NULL;
        struct btrfs_root *root = inode->root;
        int ret;
 
@@ -473,6 +473,7 @@ static int rollback_verity(struct btrfs_inode *inode)
        trans = btrfs_start_transaction(root, 2);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
+               trans = NULL;
                btrfs_handle_fs_error(root->fs_info, ret,
                        "failed to start transaction in verity rollback %llu",
                        (u64)inode->vfs_inode.i_ino);
@@ -490,8 +491,9 @@ static int rollback_verity(struct btrfs_inode *inode)
                btrfs_abort_transaction(trans, ret);
                goto out;
        }
-       btrfs_end_transaction(trans);
 out:
+       if (trans)
+               btrfs_end_transaction(trans);
        return ret;
 }
 
index 464485aa7318e6da914412a6908d3e571475ee97..2ec3b8ac8fa357772ce59892b6b1d9d3e1d3cf1d 100644 (file)
@@ -1137,6 +1137,19 @@ static void btrfs_close_one_device(struct btrfs_device *device)
        atomic_set(&device->dev_stats_ccnt, 0);
        extent_io_tree_release(&device->alloc_state);
 
+       /*
+        * Reset the flush error record. We might have a transient flush error
+        * in this mount, and if so we aborted the current transaction and set
+        * the fs to an error state, guaranteeing no super blocks can be further
+        * committed. However that error might be transient and if we unmount the
+        * filesystem and mount it again, we should allow the mount to succeed
+        * (btrfs_check_rw_degradable() should not fail) - if after mounting the
+        * filesystem again we still get flush errors, then we will again abort
+        * any transaction and set the error state, guaranteeing no commits of
+        * unsafe super blocks.
+        */
+       device->last_flush_error = 0;
+
        /* Verify the device is back in a pristine state  */
        ASSERT(!test_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state));
        ASSERT(!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state));