mirror of https://github.com/torvalds/linux.git
xfs: refactor hint based zone allocation
Replace the co-location code with a matrix that makes it more clear on how the decisions are made. The matrix contains scores for zone/file hint combinations. A "GOOD" score for an open zone will result in immediate co-location while "OK" combinations will only be picked if we cannot open a new zone. Signed-off-by: Hans Holmberg <hans.holmberg@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
94deac977f
commit
0301dae732
|
|
@ -493,64 +493,64 @@ xfs_try_open_zone(
|
|||
return oz;
|
||||
}
|
||||
|
||||
/*
|
||||
* For data with short or medium lifetime, try to colocated it into an
|
||||
* already open zone with a matching temperature.
|
||||
*/
|
||||
static bool
|
||||
xfs_colocate_eagerly(
|
||||
enum rw_hint file_hint)
|
||||
{
|
||||
switch (file_hint) {
|
||||
case WRITE_LIFE_MEDIUM:
|
||||
case WRITE_LIFE_SHORT:
|
||||
case WRITE_LIFE_NONE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
enum xfs_zone_alloc_score {
|
||||
/* Any open zone will do it, we're desperate */
|
||||
XFS_ZONE_ALLOC_ANY = 0,
|
||||
|
||||
static bool
|
||||
xfs_good_hint_match(
|
||||
struct xfs_open_zone *oz,
|
||||
enum rw_hint file_hint)
|
||||
{
|
||||
switch (oz->oz_write_hint) {
|
||||
case WRITE_LIFE_LONG:
|
||||
case WRITE_LIFE_EXTREME:
|
||||
/* colocate long and extreme */
|
||||
if (file_hint == WRITE_LIFE_LONG ||
|
||||
file_hint == WRITE_LIFE_EXTREME)
|
||||
return true;
|
||||
break;
|
||||
case WRITE_LIFE_MEDIUM:
|
||||
/* colocate medium with medium */
|
||||
if (file_hint == WRITE_LIFE_MEDIUM)
|
||||
return true;
|
||||
break;
|
||||
case WRITE_LIFE_SHORT:
|
||||
case WRITE_LIFE_NONE:
|
||||
case WRITE_LIFE_NOT_SET:
|
||||
/* colocate short and none */
|
||||
if (file_hint <= WRITE_LIFE_SHORT)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* It better fit somehow */
|
||||
XFS_ZONE_ALLOC_OK = 1,
|
||||
|
||||
/* Only reuse a zone if it fits really well. */
|
||||
XFS_ZONE_ALLOC_GOOD = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* Life time hint co-location matrix. Fields not set default to 0
|
||||
* aka XFS_ZONE_ALLOC_ANY.
|
||||
*/
|
||||
static const unsigned int
|
||||
xfs_zoned_hint_score[WRITE_LIFE_HINT_NR][WRITE_LIFE_HINT_NR] = {
|
||||
[WRITE_LIFE_NOT_SET] = {
|
||||
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_OK,
|
||||
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_OK,
|
||||
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_OK,
|
||||
},
|
||||
[WRITE_LIFE_NONE] = {
|
||||
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_OK,
|
||||
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_GOOD,
|
||||
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_GOOD,
|
||||
},
|
||||
[WRITE_LIFE_SHORT] = {
|
||||
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_GOOD,
|
||||
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_GOOD,
|
||||
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_GOOD,
|
||||
},
|
||||
[WRITE_LIFE_MEDIUM] = {
|
||||
[WRITE_LIFE_MEDIUM] = XFS_ZONE_ALLOC_GOOD,
|
||||
},
|
||||
[WRITE_LIFE_LONG] = {
|
||||
[WRITE_LIFE_LONG] = XFS_ZONE_ALLOC_OK,
|
||||
[WRITE_LIFE_EXTREME] = XFS_ZONE_ALLOC_OK,
|
||||
},
|
||||
[WRITE_LIFE_EXTREME] = {
|
||||
[WRITE_LIFE_LONG] = XFS_ZONE_ALLOC_OK,
|
||||
[WRITE_LIFE_EXTREME] = XFS_ZONE_ALLOC_OK,
|
||||
},
|
||||
};
|
||||
|
||||
static bool
|
||||
xfs_try_use_zone(
|
||||
struct xfs_zone_info *zi,
|
||||
enum rw_hint file_hint,
|
||||
struct xfs_open_zone *oz,
|
||||
bool lowspace)
|
||||
unsigned int goodness)
|
||||
{
|
||||
if (oz->oz_allocated == rtg_blocks(oz->oz_rtg))
|
||||
return false;
|
||||
if (!lowspace && !xfs_good_hint_match(oz, file_hint))
|
||||
|
||||
if (xfs_zoned_hint_score[oz->oz_write_hint][file_hint] < goodness)
|
||||
return false;
|
||||
|
||||
if (!atomic_inc_not_zero(&oz->oz_ref))
|
||||
return false;
|
||||
|
||||
|
|
@ -581,14 +581,14 @@ static struct xfs_open_zone *
|
|||
xfs_select_open_zone_lru(
|
||||
struct xfs_zone_info *zi,
|
||||
enum rw_hint file_hint,
|
||||
bool lowspace)
|
||||
unsigned int goodness)
|
||||
{
|
||||
struct xfs_open_zone *oz;
|
||||
|
||||
lockdep_assert_held(&zi->zi_open_zones_lock);
|
||||
|
||||
list_for_each_entry(oz, &zi->zi_open_zones, oz_entry)
|
||||
if (xfs_try_use_zone(zi, file_hint, oz, lowspace))
|
||||
if (xfs_try_use_zone(zi, file_hint, oz, goodness))
|
||||
return oz;
|
||||
|
||||
cond_resched_lock(&zi->zi_open_zones_lock);
|
||||
|
|
@ -651,9 +651,11 @@ xfs_select_zone_nowait(
|
|||
* data.
|
||||
*/
|
||||
spin_lock(&zi->zi_open_zones_lock);
|
||||
if (xfs_colocate_eagerly(write_hint))
|
||||
oz = xfs_select_open_zone_lru(zi, write_hint, false);
|
||||
else if (pack_tight)
|
||||
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_GOOD);
|
||||
if (oz)
|
||||
goto out_unlock;
|
||||
|
||||
if (pack_tight)
|
||||
oz = xfs_select_open_zone_mru(zi, write_hint);
|
||||
if (oz)
|
||||
goto out_unlock;
|
||||
|
|
@ -667,16 +669,16 @@ xfs_select_zone_nowait(
|
|||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Try to colocate cold data with other cold data if we failed to open a
|
||||
* new zone for it.
|
||||
* Try to find an zone that is an ok match to colocate data with.
|
||||
*/
|
||||
if (write_hint != WRITE_LIFE_NOT_SET &&
|
||||
!xfs_colocate_eagerly(write_hint))
|
||||
oz = xfs_select_open_zone_lru(zi, write_hint, false);
|
||||
if (!oz)
|
||||
oz = xfs_select_open_zone_lru(zi, WRITE_LIFE_NOT_SET, false);
|
||||
if (!oz)
|
||||
oz = xfs_select_open_zone_lru(zi, WRITE_LIFE_NOT_SET, true);
|
||||
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_OK);
|
||||
if (oz)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Pick the least recently used zone, regardless of hint match
|
||||
*/
|
||||
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_ANY);
|
||||
out_unlock:
|
||||
spin_unlock(&zi->zi_open_zones_lock);
|
||||
return oz;
|
||||
|
|
|
|||
Loading…
Reference in New Issue