diff --git a/fs/xfs/scrub/xfarray.c b/fs/xfs/scrub/xfarray.c index 2ce24bfe4c0f..5ea3ce4bf8d8 100644 --- a/fs/xfs/scrub/xfarray.c +++ b/fs/xfs/scrub/xfarray.c @@ -794,6 +794,46 @@ xfarray_sort_scan_done( si->folio = NULL; } +static int +xfarray_sort_load_folio( + struct xfarray_sortinfo *si, + xfarray_idx_t idx, + loff_t idx_pos) +{ + struct folio *folio; + loff_t next_pos; + + folio = xfile_get_folio(si->array->xfile, idx_pos, si->array->obj_size, + XFILE_ALLOC); + if (IS_ERR(folio)) + return PTR_ERR(folio); + si->folio = folio; + + /* No folio? Get the caller to read into the scratchpad. */ + if (!si->folio) + return 0; + + si->first_folio_idx = xfarray_idx(si->array, + folio_pos(si->folio) + si->array->obj_size - 1); + + next_pos = folio_next_pos(si->folio); + si->last_folio_idx = xfarray_idx(si->array, next_pos - 1); + if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos) + si->last_folio_idx--; + + /* + * If this folio still doesn't cover the desired element, it must cross + * a folio boundary. Get the caller to read into the scratchpad. + */ + if (idx < si->first_folio_idx || idx > si->last_folio_idx) { + xfarray_sort_scan_done(si); + return 0; + } + + trace_xfarray_sort_scan(si, idx); + return 0; +} + /* * Cache the folio backing the start of the given array element. If the array * element is contained entirely within the folio, return a pointer to the @@ -819,33 +859,18 @@ xfarray_sort_scan( (idx < si->first_folio_idx || idx > si->last_folio_idx)) xfarray_sort_scan_done(si); - /* Grab the first folio that backs this array element. */ + /* Grab the folio that backs this array element. */ if (!si->folio) { - struct folio *folio; - loff_t next_pos; - - folio = xfile_get_folio(si->array->xfile, idx_pos, - si->array->obj_size, XFILE_ALLOC); - if (IS_ERR(folio)) - return PTR_ERR(folio); - si->folio = folio; - - si->first_folio_idx = xfarray_idx(si->array, - folio_pos(si->folio) + si->array->obj_size - 1); - - next_pos = folio_next_pos(si->folio); - si->last_folio_idx = xfarray_idx(si->array, next_pos - 1); - if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos) - si->last_folio_idx--; - - trace_xfarray_sort_scan(si, idx); + error = xfarray_sort_load_folio(si, idx, idx_pos); + if (error) + return error; } /* - * If this folio still doesn't cover the desired element, it must cross - * a folio boundary. Read into the scratchpad and we're done. + * If we don't have a folio mapping the entire array element, read into + * the scratchpad and we're done. */ - if (idx < si->first_folio_idx || idx > si->last_folio_idx) { + if (!si->folio) { void *temp = xfarray_scratch(si->array); error = xfile_load(si->array->xfile, temp, si->array->obj_size,