Merge tag 'for-5.17-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Feb 2022 17:14:05 +0000 (09:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Feb 2022 17:14:05 +0000 (09:14 -0800)
Pull btrfs fixes from David Sterba:

 - yield CPU more often when defragmenting a large file

 - skip defragmenting extents already under writeback

 - improve error message when send fails to write file data

 - get rid of warning when mounted with 'flushoncommit'

* tag 'for-5.17-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: send: in case of IO error log it
  btrfs: get rid of warning on transaction commit when using flushoncommit
  btrfs: defrag: don't try to defrag extents which are under writeback
  btrfs: don't hold CPU for too long when defragging a file

fs/btrfs/ioctl.c
fs/btrfs/send.c
fs/btrfs/transaction.c

index 33eda39..927771d 100644 (file)
@@ -1210,6 +1210,10 @@ static int defrag_collect_targets(struct btrfs_inode *inode,
                if (em->generation < newer_than)
                        goto next;
 
+               /* This em is under writeback, no need to defrag */
+               if (em->generation == (u64)-1)
+                       goto next;
+
                /*
                 * Our start offset might be in the middle of an existing extent
                 * map, so take that into account.
@@ -1629,6 +1633,7 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
                        ret = 0;
                        break;
                }
+               cond_resched();
        }
 
        if (ra_allocated)
index d8ccb62..201eb26 100644 (file)
@@ -4999,6 +4999,10 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
                        lock_page(page);
                        if (!PageUptodate(page)) {
                                unlock_page(page);
+                               btrfs_err(fs_info,
+                       "send: IO error at offset %llu for inode %llu root %llu",
+                                       page_offset(page), sctx->cur_ino,
+                                       sctx->send_root->root_key.objectid);
                                put_page(page);
                                ret = -EIO;
                                break;
index c43bbc7..c3cfdfd 100644 (file)
@@ -1981,16 +1981,24 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
 static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
 {
        /*
-        * We use writeback_inodes_sb here because if we used
+        * We use try_to_writeback_inodes_sb() here because if we used
         * btrfs_start_delalloc_roots we would deadlock with fs freeze.
         * Currently are holding the fs freeze lock, if we do an async flush
         * we'll do btrfs_join_transaction() and deadlock because we need to
         * wait for the fs freeze lock.  Using the direct flushing we benefit
         * from already being in a transaction and our join_transaction doesn't
         * have to re-take the fs freeze lock.
+        *
+        * Note that try_to_writeback_inodes_sb() will only trigger writeback
+        * if it can read lock sb->s_umount. It will always be able to lock it,
+        * except when the filesystem is being unmounted or being frozen, but in
+        * those cases sync_filesystem() is called, which results in calling
+        * writeback_inodes_sb() while holding a write lock on sb->s_umount.
+        * Note that we don't call writeback_inodes_sb() directly, because it
+        * will emit a warning if sb->s_umount is not locked.
         */
        if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
-               writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC);
+               try_to_writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC);
        return 0;
 }