Commit 01a28961 authored by Hans Holmberg's avatar Hans Holmberg Committed by Carlos Maiolino
Browse files

xfs: always allocate the free zone with the lowest index



Zones in the beginning of the address space are typically mapped to
higer bandwidth tracks on HDDs than those at the end of the address
space. So, in stead of allocating zones "round robin" across the whole
address space, always allocate the zone with the lowest index.

This increases average write bandwidth for overwrite workloads
when less than the full capacity is being used. At ~50% utilization
this improves bandwidth for a random file overwrite benchmark
with 128MiB files and 256MiB zone capacity by 30%.

Running the same benchmark with small 2-8 MiB files at 67% capacity
shows no significant difference in performance. Due to heavy
fragmentation the whole zone range is in use, greatly limiting the
number of free zones with high bw.

Signed-off-by: default avatarHans Holmberg <hans.holmberg@wdc.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent 4d6d335e
Loading
Loading
Loading
Loading
+17 −30
Original line number Diff line number Diff line
@@ -408,31 +408,6 @@ xfs_zone_free_blocks(
	return 0;
}

static struct xfs_group *
xfs_find_free_zone(
	struct xfs_mount	*mp,
	unsigned long		start,
	unsigned long		end)
{
	struct xfs_zone_info	*zi = mp->m_zone_info;
	XA_STATE		(xas, &mp->m_groups[XG_TYPE_RTG].xa, start);
	struct xfs_group	*xg;

	xas_lock(&xas);
	xas_for_each_marked(&xas, xg, end, XFS_RTG_FREE)
		if (atomic_inc_not_zero(&xg->xg_active_ref))
			goto found;
	xas_unlock(&xas);
	return NULL;

found:
	xas_clear_mark(&xas, XFS_RTG_FREE);
	atomic_dec(&zi->zi_nr_free_zones);
	zi->zi_free_zone_cursor = xg->xg_gno;
	xas_unlock(&xas);
	return xg;
}

static struct xfs_open_zone *
xfs_init_open_zone(
	struct xfs_rtgroup	*rtg,
@@ -472,14 +447,26 @@ xfs_open_zone(
	bool			is_gc)
{
	struct xfs_zone_info	*zi = mp->m_zone_info;
	XA_STATE		(xas, &mp->m_groups[XG_TYPE_RTG].xa, 0);
	struct xfs_group	*xg;

	xg = xfs_find_free_zone(mp, zi->zi_free_zone_cursor, ULONG_MAX);
	if (!xg)
		xg = xfs_find_free_zone(mp, 0, zi->zi_free_zone_cursor);
	if (!xg)
	/*
	 * Pick the free zone with lowest index. Zones in the beginning of the
	 * address space typically provides higher bandwidth than those at the
	 * end of the address space on HDDs.
	 */
	xas_lock(&xas);
	xas_for_each_marked(&xas, xg, ULONG_MAX, XFS_RTG_FREE)
		if (atomic_inc_not_zero(&xg->xg_active_ref))
			goto found;
	xas_unlock(&xas);
	return NULL;

found:
	xas_clear_mark(&xas, XFS_RTG_FREE);
	atomic_dec(&zi->zi_nr_free_zones);
	xas_unlock(&xas);

	set_current_state(TASK_RUNNING);
	return xfs_init_open_zone(to_rtg(xg), 0, write_hint, is_gc);
}
+0 −1
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ struct xfs_zone_info {
	/*
	 * Free zone search cursor and number of free zones:
	 */
	unsigned long		zi_free_zone_cursor;
	atomic_t		zi_nr_free_zones;

	/*