Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xfs: use a seprate member to track space availabe in the GC scatch buffer

When scratch_head wraps back to 0 and scratch_tail is also 0 because no
I/O has completed yet, the ring buffer could be mistaken for empty.

Fix this by introducing a separate scratch_available member in
struct xfs_zone_gc_data. This actually ends up simplifying the code as
well.

Reported-by: Chris Mason <clm@meta.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Christoph Hellwig and committed by
Carlos Maiolino
c17a1c03 692243ca

+9 -16
+9 -16
fs/xfs/xfs_zone_gc.c
··· 131 131 /* 132 132 * Scratchpad to buffer GC data, organized as a ring buffer over 133 133 * discontiguous folios. scratch_head is where the buffer is filled, 134 - * and scratch_tail tracks the buffer space freed. 134 + * scratch_tail tracks the buffer space freed, and scratch_available 135 + * counts the space available in the ring buffer between the head and 136 + * the tail. 135 137 */ 136 138 struct folio *scratch_folios[XFS_GC_NR_BUFS]; 137 139 unsigned int scratch_size; 140 + unsigned int scratch_available; 138 141 unsigned int scratch_head; 139 142 unsigned int scratch_tail; 140 143 ··· 215 212 goto out_free_scratch; 216 213 } 217 214 data->scratch_size = XFS_GC_BUF_SIZE * XFS_GC_NR_BUFS; 215 + data->scratch_available = data->scratch_size; 218 216 INIT_LIST_HEAD(&data->reading); 219 217 INIT_LIST_HEAD(&data->writing); 220 218 INIT_LIST_HEAD(&data->resetting); ··· 578 574 return oz; 579 575 } 580 576 581 - static unsigned int 582 - xfs_zone_gc_scratch_available( 583 - struct xfs_zone_gc_data *data) 584 - { 585 - if (!data->scratch_tail) 586 - return data->scratch_size - data->scratch_head; 587 - 588 - if (!data->scratch_head) 589 - return data->scratch_tail; 590 - return (data->scratch_size - data->scratch_head) + data->scratch_tail; 591 - } 592 - 593 577 static bool 594 578 xfs_zone_gc_space_available( 595 579 struct xfs_zone_gc_data *data) ··· 588 596 if (!oz) 589 597 return false; 590 598 return oz->oz_allocated < rtg_blocks(oz->oz_rtg) && 591 - xfs_zone_gc_scratch_available(data); 599 + data->scratch_available; 592 600 } 593 601 594 602 static void ··· 617 625 if (!oz) 618 626 return NULL; 619 627 620 - *count_fsb = min(*count_fsb, 621 - XFS_B_TO_FSB(mp, xfs_zone_gc_scratch_available(data))); 628 + *count_fsb = min(*count_fsb, XFS_B_TO_FSB(mp, data->scratch_available)); 622 629 623 630 /* 624 631 * Directly allocate GC blocks from the reserved pool. ··· 721 730 bio->bi_end_io = xfs_zone_gc_end_io; 722 731 xfs_zone_gc_add_data(chunk); 723 732 data->scratch_head = (data->scratch_head + len) % data->scratch_size; 733 + data->scratch_available -= len; 724 734 725 735 WRITE_ONCE(chunk->state, XFS_GC_BIO_NEW); 726 736 list_add_tail(&chunk->entry, &data->reading); ··· 854 862 855 863 data->scratch_tail = 856 864 (data->scratch_tail + chunk->len) % data->scratch_size; 865 + data->scratch_available += chunk->len; 857 866 858 867 /* 859 868 * Cycle through the iolock and wait for direct I/O and layouts to