Skip to content

Commit 0301dae

Browse files
yhrcmaiolino
authored andcommitted
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>
1 parent 94deac9 commit 0301dae

File tree

1 file changed

+62
-60
lines changed

1 file changed

+62
-60
lines changed

fs/xfs/xfs_zone_alloc.c

Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -493,64 +493,64 @@ xfs_try_open_zone(
493493
return oz;
494494
}
495495

496+
enum xfs_zone_alloc_score {
497+
/* Any open zone will do it, we're desperate */
498+
XFS_ZONE_ALLOC_ANY = 0,
499+
500+
/* It better fit somehow */
501+
XFS_ZONE_ALLOC_OK = 1,
502+
503+
/* Only reuse a zone if it fits really well. */
504+
XFS_ZONE_ALLOC_GOOD = 2,
505+
};
506+
496507
/*
497-
* For data with short or medium lifetime, try to colocated it into an
498-
* already open zone with a matching temperature.
508+
* Life time hint co-location matrix. Fields not set default to 0
509+
* aka XFS_ZONE_ALLOC_ANY.
499510
*/
500-
static bool
501-
xfs_colocate_eagerly(
502-
enum rw_hint file_hint)
503-
{
504-
switch (file_hint) {
505-
case WRITE_LIFE_MEDIUM:
506-
case WRITE_LIFE_SHORT:
507-
case WRITE_LIFE_NONE:
508-
return true;
509-
default:
510-
return false;
511-
}
512-
}
513-
514-
static bool
515-
xfs_good_hint_match(
516-
struct xfs_open_zone *oz,
517-
enum rw_hint file_hint)
518-
{
519-
switch (oz->oz_write_hint) {
520-
case WRITE_LIFE_LONG:
521-
case WRITE_LIFE_EXTREME:
522-
/* colocate long and extreme */
523-
if (file_hint == WRITE_LIFE_LONG ||
524-
file_hint == WRITE_LIFE_EXTREME)
525-
return true;
526-
break;
527-
case WRITE_LIFE_MEDIUM:
528-
/* colocate medium with medium */
529-
if (file_hint == WRITE_LIFE_MEDIUM)
530-
return true;
531-
break;
532-
case WRITE_LIFE_SHORT:
533-
case WRITE_LIFE_NONE:
534-
case WRITE_LIFE_NOT_SET:
535-
/* colocate short and none */
536-
if (file_hint <= WRITE_LIFE_SHORT)
537-
return true;
538-
break;
539-
}
540-
return false;
541-
}
511+
static const unsigned int
512+
xfs_zoned_hint_score[WRITE_LIFE_HINT_NR][WRITE_LIFE_HINT_NR] = {
513+
[WRITE_LIFE_NOT_SET] = {
514+
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_OK,
515+
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_OK,
516+
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_OK,
517+
},
518+
[WRITE_LIFE_NONE] = {
519+
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_OK,
520+
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_GOOD,
521+
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_GOOD,
522+
},
523+
[WRITE_LIFE_SHORT] = {
524+
[WRITE_LIFE_NOT_SET] = XFS_ZONE_ALLOC_GOOD,
525+
[WRITE_LIFE_NONE] = XFS_ZONE_ALLOC_GOOD,
526+
[WRITE_LIFE_SHORT] = XFS_ZONE_ALLOC_GOOD,
527+
},
528+
[WRITE_LIFE_MEDIUM] = {
529+
[WRITE_LIFE_MEDIUM] = XFS_ZONE_ALLOC_GOOD,
530+
},
531+
[WRITE_LIFE_LONG] = {
532+
[WRITE_LIFE_LONG] = XFS_ZONE_ALLOC_OK,
533+
[WRITE_LIFE_EXTREME] = XFS_ZONE_ALLOC_OK,
534+
},
535+
[WRITE_LIFE_EXTREME] = {
536+
[WRITE_LIFE_LONG] = XFS_ZONE_ALLOC_OK,
537+
[WRITE_LIFE_EXTREME] = XFS_ZONE_ALLOC_OK,
538+
},
539+
};
542540

543541
static bool
544542
xfs_try_use_zone(
545543
struct xfs_zone_info *zi,
546544
enum rw_hint file_hint,
547545
struct xfs_open_zone *oz,
548-
bool lowspace)
546+
unsigned int goodness)
549547
{
550548
if (oz->oz_allocated == rtg_blocks(oz->oz_rtg))
551549
return false;
552-
if (!lowspace && !xfs_good_hint_match(oz, file_hint))
550+
551+
if (xfs_zoned_hint_score[oz->oz_write_hint][file_hint] < goodness)
553552
return false;
553+
554554
if (!atomic_inc_not_zero(&oz->oz_ref))
555555
return false;
556556

@@ -581,14 +581,14 @@ static struct xfs_open_zone *
581581
xfs_select_open_zone_lru(
582582
struct xfs_zone_info *zi,
583583
enum rw_hint file_hint,
584-
bool lowspace)
584+
unsigned int goodness)
585585
{
586586
struct xfs_open_zone *oz;
587587

588588
lockdep_assert_held(&zi->zi_open_zones_lock);
589589

590590
list_for_each_entry(oz, &zi->zi_open_zones, oz_entry)
591-
if (xfs_try_use_zone(zi, file_hint, oz, lowspace))
591+
if (xfs_try_use_zone(zi, file_hint, oz, goodness))
592592
return oz;
593593

594594
cond_resched_lock(&zi->zi_open_zones_lock);
@@ -651,9 +651,11 @@ xfs_select_zone_nowait(
651651
* data.
652652
*/
653653
spin_lock(&zi->zi_open_zones_lock);
654-
if (xfs_colocate_eagerly(write_hint))
655-
oz = xfs_select_open_zone_lru(zi, write_hint, false);
656-
else if (pack_tight)
654+
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_GOOD);
655+
if (oz)
656+
goto out_unlock;
657+
658+
if (pack_tight)
657659
oz = xfs_select_open_zone_mru(zi, write_hint);
658660
if (oz)
659661
goto out_unlock;
@@ -667,16 +669,16 @@ xfs_select_zone_nowait(
667669
goto out_unlock;
668670

669671
/*
670-
* Try to colocate cold data with other cold data if we failed to open a
671-
* new zone for it.
672+
* Try to find an zone that is an ok match to colocate data with.
673+
*/
674+
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_OK);
675+
if (oz)
676+
goto out_unlock;
677+
678+
/*
679+
* Pick the least recently used zone, regardless of hint match
672680
*/
673-
if (write_hint != WRITE_LIFE_NOT_SET &&
674-
!xfs_colocate_eagerly(write_hint))
675-
oz = xfs_select_open_zone_lru(zi, write_hint, false);
676-
if (!oz)
677-
oz = xfs_select_open_zone_lru(zi, WRITE_LIFE_NOT_SET, false);
678-
if (!oz)
679-
oz = xfs_select_open_zone_lru(zi, WRITE_LIFE_NOT_SET, true);
681+
oz = xfs_select_open_zone_lru(zi, write_hint, XFS_ZONE_ALLOC_ANY);
680682
out_unlock:
681683
spin_unlock(&zi->zi_open_zones_lock);
682684
return oz;

0 commit comments

Comments
 (0)