History

Merge tag 'for-6.4-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba: - handle memory allocation error in checksumming helper (reported by syzbot) - fix lockdep splat when aborting a transaction, add NOFS protection around invalidate_inode_pages2 that could allocate with GFP_KERNEL - reduce chances to hit an ENOSPC during scrub with RAID56 profiles * tag 'for-6.4-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: use nofs when cleaning up aborted transactions btrfs: handle memory allocation failure in btrfs_csum_one_bio btrfs: scrub: try harder to mark RAID56 block groups read-only

Linus Torvalds committed 3 years ago

Commit b158dd92 parents b83ac44 597441b4 files · +32 −4Browse files

Unified · Split

4 files
  1. fs/btrfs/block-group.c +12 −2
  2. fs/btrfs/disk-io.c +9 −0
  3. fs/btrfs/file-item.c +3 −1
  4. fs/btrfs/scrub.c +8 −1
fs/btrfs/block-group.c+12−2
@@ -2818,10 +2818,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache, · 2817 unmodified lines
28182818 }
28192819
28202820 ret = inc_block_group_ro(cache, 0);
2821− if (!do_chunk_alloc || ret == -ETXTBSY)
2822− goto unlock_out;
28232821 if (!ret)
28242822 goto out;
2823+ if (ret == -ETXTBSY)
2824+ goto unlock_out;
2825+
2826+ /*
2827+ * Skip chunk alloction if the bg is SYSTEM, this is to avoid system
2828+ * chunk allocation storm to exhaust the system chunk array. Otherwise
2829+ * we still want to try our best to mark the block group read-only.
2830+ */
2831+ if (!do_chunk_alloc && ret == -ENOSPC &&
2832+ (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
2833+ goto unlock_out;
2834+
28252835 alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
28262836 ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
28272837 if (ret < 0)
fs/btrfs/disk-io.c+9−0
@@ -4936,7 +4936,11 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root) · 4935 unmodified lines
49364936 */
49374937 inode = igrab(&btrfs_inode->vfs_inode);
49384938 if (inode) {
4939+ unsigned int nofs_flag;
4940+
4941+ nofs_flag = memalloc_nofs_save();
49394942 invalidate_inode_pages2(inode->i_mapping);
4943+ memalloc_nofs_restore(nofs_flag);
49404944 iput(inode);
49414945 }
49424946 spin_lock(&root->delalloc_lock);
@@ -5042,7 +5046,12 @@ static void btrfs_cleanup_bg_io(struct btrfs_block_group *cache) · 99 unmodified lines
50425046
50435047 inode = cache->io_ctl.inode;
50445048 if (inode) {
5049+ unsigned int nofs_flag;
5050+
5051+ nofs_flag = memalloc_nofs_save();
50455052 invalidate_inode_pages2(inode->i_mapping);
5053+ memalloc_nofs_restore(nofs_flag);
5054+
50465055 BTRFS_I(inode)->generation = 0;
50475056 cache->io_ctl.inode = NULL;
50485057 iput(inode);
fs/btrfs/file-item.c+3−1
@@ -792,7 +792,9 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio) · 791 unmodified lines
792792 sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
793793 bytes_left), GFP_KERNEL);
794794 memalloc_nofs_restore(nofs_flag);
795− BUG_ON(!sums); /* -ENOMEM */
795+ if (!sums)
796+ return BLK_STS_RESOURCE;
797+
796798 sums->len = bytes_left;
797799 ordered = btrfs_lookup_ordered_extent(inode,
798800 offset);
fs/btrfs/scrub.c+8−1
@@ -2518,13 +2518,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx, · 2517 unmodified lines
25182518
25192519 if (ret == 0) {
25202520 ro_set = 1;
2521− } else if (ret == -ENOSPC && !sctx->is_dev_replace) {
2521+ } else if (ret == -ENOSPC && !sctx->is_dev_replace &&
2522+ !(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
25222523 /*
25232524 * btrfs_inc_block_group_ro return -ENOSPC when it
25242525 * failed in creating new chunk for metadata.
25252526 * It is not a problem for scrub, because
25262527 * metadata are always cowed, and our scrub paused
25272528 * commit_transactions.
2529+ *
2530+ * For RAID56 chunks, we have to mark them read-only
2531+ * for scrub, as later we would use our own cache
2532+ * out of RAID56 realm.
2533+ * Thus we want the RAID56 bg to be marked RO to
2534+ * prevent RMW from screwing up out cache.
25282535 */
25292536 ro_set = 0;
25302537 } else if (ret == -ETXTBSY) {