Commit 74a63255 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - fix potential endless loop when discarding a block group when
   disabling discard

 - reinstate message when setting a large value of mount option 'commit'

 - fix a folio leak when async extent submission fails

* tag 'for-6.15-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: add back warning for mount option commit values exceeding 300
  btrfs: fix folio leak in submit_one_async_extent()
  btrfs: fix discard worker infinite loop after disabling discard
parents c94d59a1 4ce2affc
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -94,8 +94,6 @@ static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
				  struct btrfs_block_group *block_group)
{
	lockdep_assert_held(&discard_ctl->lock);
	if (!btrfs_run_discard_work(discard_ctl))
		return;

	if (list_empty(&block_group->discard_list) ||
	    block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) {
@@ -118,6 +116,9 @@ static void add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
	if (!btrfs_is_block_group_data_only(block_group))
		return;

	if (!btrfs_run_discard_work(discard_ctl))
		return;

	spin_lock(&discard_ctl->lock);
	__add_to_discard_list(discard_ctl, block_group);
	spin_unlock(&discard_ctl->lock);
@@ -244,6 +245,18 @@ static struct btrfs_block_group *peek_discard_list(
		    block_group->used != 0) {
			if (btrfs_is_block_group_data_only(block_group)) {
				__add_to_discard_list(discard_ctl, block_group);
				/*
				 * The block group must have been moved to other
				 * discard list even if discard was disabled in
				 * the meantime or a transaction abort happened,
				 * otherwise we can end up in an infinite loop,
				 * always jumping into the 'again' label and
				 * keep getting this block group over and over
				 * in case there are no other block groups in
				 * the discard lists.
				 */
				ASSERT(block_group->discard_index !=
				       BTRFS_DISCARD_INDEX_UNUSED);
			} else {
				list_del_init(&block_group->discard_list);
				btrfs_put_block_group(block_group);
+1 −0
Original line number Diff line number Diff line
@@ -300,6 +300,7 @@ enum {
#define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR		0ULL

#define BTRFS_DEFAULT_COMMIT_INTERVAL	(30)
#define BTRFS_WARNING_COMMIT_INTERVAL	(300)
#define BTRFS_DEFAULT_MAX_INLINE	(2048)

struct btrfs_dev_replace {
+7 −0
Original line number Diff line number Diff line
@@ -1109,6 +1109,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
	struct extent_state *cached = NULL;
	struct extent_map *em;
	int ret = 0;
	bool free_pages = false;
	u64 start = async_extent->start;
	u64 end = async_extent->start + async_extent->ram_size - 1;

@@ -1129,7 +1130,10 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
	}

	if (async_extent->compress_type == BTRFS_COMPRESS_NONE) {
		ASSERT(!async_extent->folios);
		ASSERT(async_extent->nr_folios == 0);
		submit_uncompressed_range(inode, async_extent, locked_folio);
		free_pages = true;
		goto done;
	}

@@ -1145,6 +1149,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
		 * fall back to uncompressed.
		 */
		submit_uncompressed_range(inode, async_extent, locked_folio);
		free_pages = true;
		goto done;
	}

@@ -1186,6 +1191,8 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
done:
	if (async_chunk->blkcg_css)
		kthread_associate_blkcg(NULL);
	if (free_pages)
		free_async_extent_pages(async_extent);
	kfree(async_extent);
	return;

+4 −0
Original line number Diff line number Diff line
@@ -569,6 +569,10 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
		break;
	case Opt_commit_interval:
		ctx->commit_interval = result.uint_32;
		if (ctx->commit_interval > BTRFS_WARNING_COMMIT_INTERVAL) {
			btrfs_warn(NULL, "excessive commit interval %u, use with care",
				   ctx->commit_interval);
		}
		if (ctx->commit_interval == 0)
			ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
		break;