From: Christoph Hellwig <hch@lst.de>
To: Carlos Maiolino <cem@kernel.org>
Cc: Damien Le Moal <dlemoal@kernel.org>,
Hans Holmberg <hans.holmberg@wdc.com>,
linux-xfs@vger.kernel.org, Carlos Maiolino <cmaiolino@redhat.com>
Subject: [PATCH 6/9] xfs: streamline GC zone selection
Date: Tue, 31 Mar 2026 17:27:28 +0200 [thread overview]
Message-ID: <20260331152751.4048218-7-hch@lst.de> (raw)
In-Reply-To: <20260331152751.4048218-1-hch@lst.de>
Currently picking of the GC target zone is a bit odd as it is done both
in the main "can we start new GC cycles" routine and in the low-level
block allocator for GC. This was mostly done to work around the rules
for when code in a waitqueue wait loop can sleep.
But with a trick to check if the process state has been set to running to
discover if the wait loop has to be retried, all this becomes much
simpler. We can select a GC zone just before writing, and bail out of
starting new work if we can't find a usable zone.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
---
fs/xfs/xfs_zone_gc.c | 95 +++++++++++++++++++-------------------------
1 file changed, 40 insertions(+), 55 deletions(-)
diff --git a/fs/xfs/xfs_zone_gc.c b/fs/xfs/xfs_zone_gc.c
index 0f62051b0acc..2c2fa924fecd 100644
--- a/fs/xfs/xfs_zone_gc.c
+++ b/fs/xfs/xfs_zone_gc.c
@@ -383,9 +383,6 @@ xfs_zone_gc_iter_irec(
struct xfs_rmap_irec *irec;
int error;
- if (!iter->victim_rtg)
- return false;
-
retry:
if (iter->rec_idx == iter->rec_count) {
error = xfs_zone_gc_query(mp, iter);
@@ -555,7 +552,7 @@ xfs_zone_gc_steal_open(
/*
* Ensure we have a valid open zone to write to.
*/
-static struct xfs_open_zone *
+static bool
xfs_zone_gc_select_target(
struct xfs_mount *mp)
{
@@ -568,14 +565,14 @@ xfs_zone_gc_select_target(
* zone.
*/
if (oz->oz_allocated < rtg_blocks(oz->oz_rtg))
- return oz;
+ return true;
/*
* Wait for all writes to the current zone to finish before
* picking a new one.
*/
if (oz->oz_written < rtg_blocks(oz->oz_rtg))
- return NULL;
+ return false;
}
/*
@@ -589,7 +586,7 @@ xfs_zone_gc_select_target(
spin_lock(&zi->zi_open_zones_lock);
zi->zi_open_gc_zone = oz;
spin_unlock(&zi->zi_open_zones_lock);
- return oz;
+ return !!oz;
}
static void
@@ -604,7 +601,7 @@ xfs_zone_gc_end_io(
wake_up_process(data->mp->m_zone_info->zi_gc_thread);
}
-static struct xfs_open_zone *
+static bool
xfs_zone_gc_alloc_blocks(
struct xfs_zone_gc_data *data,
xfs_extlen_t *count_fsb,
@@ -612,11 +609,7 @@ xfs_zone_gc_alloc_blocks(
bool *is_seq)
{
struct xfs_mount *mp = data->mp;
- struct xfs_open_zone *oz;
-
- oz = xfs_zone_gc_select_target(mp);
- if (!oz)
- return NULL;
+ struct xfs_open_zone *oz = mp->m_zone_info->zi_open_gc_zone;
*count_fsb = min(*count_fsb, XFS_B_TO_FSB(mp, data->scratch_available));
@@ -638,7 +631,7 @@ xfs_zone_gc_alloc_blocks(
spin_unlock(&mp->m_sb_lock);
if (!*count_fsb)
- return NULL;
+ return false;
*daddr = xfs_gbno_to_daddr(rtg_group(oz->oz_rtg), 0);
*is_seq = bdev_zone_is_seq(mp->m_rtdev_targp->bt_bdev, *daddr);
@@ -646,7 +639,7 @@ xfs_zone_gc_alloc_blocks(
*daddr += XFS_FSB_TO_BB(mp, oz->oz_allocated);
oz->oz_allocated += *count_fsb;
atomic_inc(&oz->oz_ref);
- return oz;
+ return true;
}
static void
@@ -671,6 +664,28 @@ xfs_zone_gc_add_data(
} while (len);
}
+static bool
+xfs_zone_gc_can_start_chunk(
+ struct xfs_zone_gc_data *data)
+{
+
+ if (xfs_is_shutdown(data->mp))
+ return false;
+ if (!data->scratch_available)
+ return false;
+
+ if (!data->iter.victim_rtg) {
+ if (kthread_should_stop() || kthread_should_park())
+ return false;
+ if (!xfs_zoned_need_gc(data->mp))
+ return false;
+ if (!xfs_zone_gc_select_victim(data))
+ return false;
+ }
+
+ return xfs_zone_gc_select_target(data->mp);
+}
+
static bool
xfs_zone_gc_start_chunk(
struct xfs_zone_gc_data *data)
@@ -678,7 +693,6 @@ xfs_zone_gc_start_chunk(
struct xfs_zone_gc_iter *iter = &data->iter;
struct xfs_mount *mp = data->mp;
struct block_device *bdev = mp->m_rtdev_targp->bt_bdev;
- struct xfs_open_zone *oz;
struct xfs_rmap_irec irec;
struct xfs_gc_bio *chunk;
struct xfs_inode *ip;
@@ -687,14 +701,15 @@ xfs_zone_gc_start_chunk(
unsigned int len;
bool is_seq;
- if (xfs_is_shutdown(mp))
+ if (!xfs_zone_gc_can_start_chunk(data))
return false;
+ set_current_state(TASK_RUNNING);
if (!xfs_zone_gc_iter_irec(mp, iter, &irec, &ip))
return false;
- oz = xfs_zone_gc_alloc_blocks(data, &irec.rm_blockcount, &daddr,
- &is_seq);
- if (!oz) {
+
+ if (!xfs_zone_gc_alloc_blocks(data, &irec.rm_blockcount, &daddr,
+ &is_seq)) {
xfs_irele(ip);
return false;
}
@@ -713,7 +728,7 @@ xfs_zone_gc_start_chunk(
chunk->new_daddr = daddr;
chunk->is_seq = is_seq;
chunk->data = data;
- chunk->oz = oz;
+ chunk->oz = mp->m_zone_info->zi_open_gc_zone;
chunk->victim_rtg = iter->victim_rtg;
atomic_inc(&rtg_group(chunk->victim_rtg)->xg_active_ref);
atomic_inc(&chunk->victim_rtg->rtg_gccount);
@@ -1007,33 +1022,6 @@ xfs_zone_gc_reset_zones(
} while (next);
}
-static bool
-xfs_zone_gc_should_start_new_work(
- struct xfs_zone_gc_data *data)
-{
- struct xfs_open_zone *oz;
-
- if (xfs_is_shutdown(data->mp))
- return false;
- if (!data->scratch_available)
- return false;
-
- oz = xfs_zone_gc_select_target(data->mp);
- if (!oz || oz->oz_allocated == rtg_blocks(oz->oz_rtg))
- return false;
-
- if (!data->iter.victim_rtg) {
- if (kthread_should_stop() || kthread_should_park())
- return false;
- if (!xfs_zoned_need_gc(data->mp))
- return false;
- if (!xfs_zone_gc_select_victim(data))
- return false;
- }
-
- return true;
-}
-
/*
* Handle the work to read and write data for GC and to reset the zones,
* including handling all completions.
@@ -1083,13 +1071,10 @@ xfs_zone_gc_handle_work(
}
blk_finish_plug(&plug);
- if (xfs_zone_gc_should_start_new_work(data)) {
- set_current_state(TASK_RUNNING);
- blk_start_plug(&plug);
- while (xfs_zone_gc_start_chunk(data))
- ;
- blk_finish_plug(&plug);
- }
+ blk_start_plug(&plug);
+ while (xfs_zone_gc_start_chunk(data))
+ ;
+ blk_finish_plug(&plug);
}
/*
--
2.47.3
next prev parent reply other threads:[~2026-03-31 15:28 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-31 15:27 cleanup open GC zone handling v2 Christoph Hellwig
2026-03-31 15:27 ` [PATCH 1/9] xfs: delay initial open of the GC zone Christoph Hellwig
2026-03-31 15:27 ` [PATCH 2/9] xfs: add a separate tracepoint for stealing an open zone for GC Christoph Hellwig
2026-03-31 15:27 ` [PATCH 3/9] xfs: put the open zone later xfs_open_zone_put Christoph Hellwig
2026-03-31 15:27 ` [PATCH 4/9] xfs: rename xfs_zone_gc_iter_next to xfs_zone_gc_iter_irec Christoph Hellwig
2026-03-31 15:27 ` [PATCH 5/9] xfs: refactor GC zone selection helpers Christoph Hellwig
2026-03-31 15:27 ` Christoph Hellwig [this message]
2026-03-31 15:27 ` [PATCH 7/9] xfs: reduce special casing for the open GC zone Christoph Hellwig
2026-03-31 15:27 ` [PATCH 8/9] xfs: expose the number of open zones in sysfs Christoph Hellwig
2026-03-31 19:45 ` Damien Le Moal
2026-04-01 13:10 ` Hans Holmberg
2026-03-31 15:27 ` [PATCH 9/9] xfs: untangle the open zones reporting in mountinfo Christoph Hellwig
2026-04-07 13:38 ` cleanup open GC zone handling v2 Carlos Maiolino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260331152751.4048218-7-hch@lst.de \
--to=hch@lst.de \
--cc=cem@kernel.org \
--cc=cmaiolino@redhat.com \
--cc=dlemoal@kernel.org \
--cc=hans.holmberg@wdc.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox