xref: /linux/fs/xfs/scrub/xfarray.c (revision 8c4f172c246717b1420f138a159ed15c315a58bd)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2021-2023 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <djwong@kernel.org>
5  */
6 #include "xfs_platform.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "scrub/scrub.h"
11 #include "scrub/xfile.h"
12 #include "scrub/xfarray.h"
13 #include "scrub/trace.h"
14 
15 /*
16  * Large Arrays of Fixed-Size Records
17  * ==================================
18  *
19  * This memory array uses an xfile (which itself is a shmem file) to store
20  * large numbers of fixed-size records in memory that can be paged out.  This
21  * puts less stress on the memory reclaim algorithms during an online repair
22  * because we don't have to pin so much memory.  However, array access is less
23  * direct than would be in a regular memory array.  Access to the array is
24  * performed via indexed load and store methods, and an append method is
25  * provided for convenience.  Array elements can be unset, which sets them to
26  * all zeroes.  Unset entries are skipped during iteration, though direct loads
27  * will return a zeroed buffer.  Callers are responsible for concurrency
28  * control.
29  */
30 
31 /*
32  * Pointer to scratch space.  Because we can't access the xfile data directly,
33  * we allocate a small amount of memory on the end of the xfarray structure to
34  * buffer array items when we need space to store values temporarily.
35  */
36 static inline void *xfarray_scratch(struct xfarray *array)
37 {
38 	return (array + 1);
39 }
40 
41 /* Compute array index given an xfile offset. */
42 static xfarray_idx_t
43 xfarray_idx(
44 	struct xfarray	*array,
45 	loff_t		pos)
46 {
47 	if (array->obj_size_log >= 0)
48 		return (xfarray_idx_t)pos >> array->obj_size_log;
49 
50 	return div_u64((xfarray_idx_t)pos, array->obj_size);
51 }
52 
53 /* Compute xfile offset of array element. */
54 static inline loff_t xfarray_pos(struct xfarray *array, xfarray_idx_t idx)
55 {
56 	if (array->obj_size_log >= 0)
57 		return idx << array->obj_size_log;
58 
59 	return idx * array->obj_size;
60 }
61 
62 /*
63  * Initialize a big memory array.  Array records cannot be larger than a
64  * page, and the array cannot span more bytes than the page cache supports.
65  * If @required_capacity is nonzero, the maximum array size will be set to this
66  * quantity and the array creation will fail if the underlying storage cannot
67  * support that many records.
68  */
69 int
70 xfarray_create(
71 	const char		*description,
72 	unsigned long long	required_capacity,
73 	size_t			obj_size,
74 	struct xfarray		**arrayp)
75 {
76 	struct xfarray		*array;
77 	struct xfile		*xfile;
78 	int			error;
79 
80 	ASSERT(obj_size < PAGE_SIZE);
81 
82 	error = xfile_create(description, 0, &xfile);
83 	if (error)
84 		return error;
85 
86 	error = -ENOMEM;
87 	array = kzalloc(sizeof(struct xfarray) + obj_size, XCHK_GFP_FLAGS);
88 	if (!array)
89 		goto out_xfile;
90 
91 	array->xfile = xfile;
92 	array->obj_size = obj_size;
93 
94 	if (is_power_of_2(obj_size))
95 		array->obj_size_log = ilog2(obj_size);
96 	else
97 		array->obj_size_log = -1;
98 
99 	array->max_nr = xfarray_idx(array, MAX_LFS_FILESIZE);
100 	trace_xfarray_create(array, required_capacity);
101 
102 	if (required_capacity > 0) {
103 		if (array->max_nr < required_capacity) {
104 			error = -ENOMEM;
105 			goto out_xfarray;
106 		}
107 		array->max_nr = required_capacity;
108 	}
109 
110 	*arrayp = array;
111 	return 0;
112 
113 out_xfarray:
114 	kfree(array);
115 out_xfile:
116 	xfile_destroy(xfile);
117 	return error;
118 }
119 
120 /* Destroy the array. */
121 void
122 xfarray_destroy(
123 	struct xfarray	*array)
124 {
125 	xfile_destroy(array->xfile);
126 	kfree(array);
127 }
128 
129 /* Load an element from the array. */
130 int
131 xfarray_load(
132 	struct xfarray	*array,
133 	xfarray_idx_t	idx,
134 	void		*ptr)
135 {
136 	if (idx >= array->nr)
137 		return -ENODATA;
138 
139 	return xfile_load(array->xfile, ptr, array->obj_size,
140 			xfarray_pos(array, idx));
141 }
142 
143 /* Remove the elements at the end of an array. */
144 int
145 xfarray_trim(
146 	struct xfarray		*array,
147 	unsigned long long	nr)
148 {
149 	loff_t			new_eof;
150 
151 	if (nr > array->nr)
152 		return -ENODATA;
153 
154 	array->nr -= nr;
155 	if (!array->nr)
156 		array->possibly_sparse = false;
157 
158 	new_eof = xfarray_pos(array, array->nr);
159 	xfile_discard(array->xfile, new_eof, MAX_LFS_FILESIZE - new_eof);
160 	return 0;
161 }
162 
163 /*
164  * Store an element in the array.  The element must not be completely zeroed,
165  * because those are considered unset sparse elements.
166  */
167 int
168 xfarray_store(
169 	struct xfarray	*array,
170 	xfarray_idx_t	idx,
171 	const void	*ptr)
172 {
173 	int		ret;
174 
175 	if (idx >= array->max_nr)
176 		return -EFBIG;
177 
178 	ASSERT(!xfarray_element_is_null(array, ptr));
179 
180 	ret = xfile_store(array->xfile, ptr, array->obj_size,
181 			xfarray_pos(array, idx));
182 	if (ret)
183 		return ret;
184 
185 	if (idx > array->nr)
186 		array->possibly_sparse = true;
187 	array->nr = max(array->nr, idx + 1);
188 	return 0;
189 }
190 
191 /* Is this array element NULL? */
192 bool
193 xfarray_element_is_null(
194 	struct xfarray	*array,
195 	const void	*ptr)
196 {
197 	return !memchr_inv(ptr, 0, array->obj_size);
198 }
199 
200 /* Return length of array. */
201 uint64_t
202 xfarray_length(
203 	struct xfarray	*array)
204 {
205 	return array->nr;
206 }
207 
208 /*
209  * Decide which array item we're going to read as part of an _iter_get.
210  * @cur is the array index, and @pos is the file offset of that array index in
211  * the backing xfile.  Returns ENODATA if we reach the end of the records.
212  *
213  * Reading from a hole in a sparse xfile causes page instantiation, so for
214  * iterating a (possibly sparse) array we need to figure out if the cursor is
215  * pointing at a totally uninitialized hole and move the cursor up if
216  * necessary.
217  */
218 static inline int
219 xfarray_find_data(
220 	struct xfarray	*array,
221 	xfarray_idx_t	*cur,
222 	loff_t		*pos)
223 {
224 	unsigned int	pgoff = offset_in_page(*pos);
225 	loff_t		end_pos = *pos + array->obj_size - 1;
226 	loff_t		new_pos;
227 
228 	/*
229 	 * If the current array record is not adjacent to a page boundary, we
230 	 * are in the middle of the page.  We do not need to move the cursor.
231 	 */
232 	if (pgoff != 0 && pgoff + array->obj_size - 1 < PAGE_SIZE)
233 		return 0;
234 
235 	/*
236 	 * Call SEEK_DATA on the last byte in the record we're about to read.
237 	 * If the record ends at (or crosses) the end of a page then we know
238 	 * that the first byte of the record is backed by pages and don't need
239 	 * to query it.  If instead the record begins at the start of the page
240 	 * then we know that querying the last byte is just as good as querying
241 	 * the first byte, since records cannot be larger than a page.
242 	 *
243 	 * If the call returns the same file offset, we know this record is
244 	 * backed by real pages.  We do not need to move the cursor.
245 	 */
246 	new_pos = xfile_seek_data(array->xfile, end_pos);
247 	if (new_pos == -ENXIO)
248 		return -ENODATA;
249 	if (new_pos < 0)
250 		return new_pos;
251 	if (new_pos == end_pos)
252 		return 0;
253 
254 	/*
255 	 * Otherwise, SEEK_DATA told us how far up to move the file pointer to
256 	 * find more data.  Move the array index to the first record past the
257 	 * byte offset we were given.
258 	 */
259 	new_pos = roundup_64(new_pos, array->obj_size);
260 	*cur = xfarray_idx(array, new_pos);
261 	*pos = xfarray_pos(array, *cur);
262 	return 0;
263 }
264 
265 /*
266  * Starting at *idx, fetch the next non-null array entry and advance the index
267  * to set up the next _load_next call.  Returns ENODATA if we reach the end of
268  * the array.  Callers must set @*idx to XFARRAY_CURSOR_INIT before the first
269  * call to this function.
270  */
271 int
272 xfarray_load_next(
273 	struct xfarray	*array,
274 	xfarray_idx_t	*idx,
275 	void		*rec)
276 {
277 	xfarray_idx_t	cur = *idx;
278 	loff_t		pos = xfarray_pos(array, cur);
279 	int		error;
280 
281 	do {
282 		if (cur >= array->nr)
283 			return -ENODATA;
284 
285 		/*
286 		 * Ask the backing store for the location of next possible
287 		 * written record, then retrieve that record.
288 		 */
289 		error = xfarray_find_data(array, &cur, &pos);
290 		if (error)
291 			return error;
292 		error = xfarray_load(array, cur, rec);
293 		if (error)
294 			return error;
295 
296 		cur++;
297 		pos += array->obj_size;
298 	} while (xfarray_element_is_null(array, rec));
299 
300 	*idx = cur;
301 	return 0;
302 }
303 
304 /* Sorting functions */
305 
306 #ifdef DEBUG
307 # define xfarray_sort_bump_loads(si)	do { (si)->loads++; } while (0)
308 # define xfarray_sort_bump_stores(si)	do { (si)->stores++; } while (0)
309 # define xfarray_sort_bump_compares(si)	do { (si)->compares++; } while (0)
310 # define xfarray_sort_bump_heapsorts(si) do { (si)->heapsorts++; } while (0)
311 #else
312 # define xfarray_sort_bump_loads(si)
313 # define xfarray_sort_bump_stores(si)
314 # define xfarray_sort_bump_compares(si)
315 # define xfarray_sort_bump_heapsorts(si)
316 #endif /* DEBUG */
317 
318 /* Load an array element for sorting. */
319 static inline int
320 xfarray_sort_load(
321 	struct xfarray_sortinfo	*si,
322 	xfarray_idx_t		idx,
323 	void			*ptr)
324 {
325 	xfarray_sort_bump_loads(si);
326 	return xfarray_load(si->array, idx, ptr);
327 }
328 
329 /* Store an array element for sorting. */
330 static inline int
331 xfarray_sort_store(
332 	struct xfarray_sortinfo	*si,
333 	xfarray_idx_t		idx,
334 	void			*ptr)
335 {
336 	xfarray_sort_bump_stores(si);
337 	return xfarray_store(si->array, idx, ptr);
338 }
339 
340 /* Compare an array element for sorting. */
341 static inline int
342 xfarray_sort_cmp(
343 	struct xfarray_sortinfo	*si,
344 	const void		*a,
345 	const void		*b)
346 {
347 	xfarray_sort_bump_compares(si);
348 	return si->cmp_fn(a, b);
349 }
350 
351 /* Return a pointer to the low index stack for quicksort partitioning. */
352 static inline xfarray_idx_t *xfarray_sortinfo_lo(struct xfarray_sortinfo *si)
353 {
354 	return (xfarray_idx_t *)(si + 1);
355 }
356 
357 /* Return a pointer to the high index stack for quicksort partitioning. */
358 static inline xfarray_idx_t *xfarray_sortinfo_hi(struct xfarray_sortinfo *si)
359 {
360 	return xfarray_sortinfo_lo(si) + si->max_stack_depth;
361 }
362 
363 /* Size of each element in the quicksort pivot array. */
364 static inline size_t
365 xfarray_pivot_rec_sz(
366 	struct xfarray		*array)
367 {
368 	return round_up(array->obj_size, 8) + sizeof(xfarray_idx_t);
369 }
370 
371 /* Allocate memory to handle the sort. */
372 static inline int
373 xfarray_sortinfo_alloc(
374 	struct xfarray		*array,
375 	xfarray_cmp_fn		cmp_fn,
376 	unsigned int		flags,
377 	struct xfarray_sortinfo	**infop)
378 {
379 	struct xfarray_sortinfo	*si;
380 	size_t			nr_bytes = sizeof(struct xfarray_sortinfo);
381 	size_t			pivot_rec_sz = xfarray_pivot_rec_sz(array);
382 	int			max_stack_depth;
383 
384 	/*
385 	 * The median-of-nine pivot algorithm doesn't work if a subset has
386 	 * fewer than 9 items.  Make sure the in-memory sort will always take
387 	 * over for subsets where this wouldn't be the case.
388 	 */
389 	BUILD_BUG_ON(XFARRAY_QSORT_PIVOT_NR >= XFARRAY_ISORT_NR);
390 
391 	/*
392 	 * Tail-call recursion during the partitioning phase means that
393 	 * quicksort will never recurse more than log2(nr) times.  We need one
394 	 * extra level of stack to hold the initial parameters.  In-memory
395 	 * sort will always take care of the last few levels of recursion for
396 	 * us, so we can reduce the stack depth by that much.
397 	 */
398 	max_stack_depth = ilog2(array->nr) + 1 - (XFARRAY_ISORT_SHIFT - 1);
399 	if (max_stack_depth < 1)
400 		max_stack_depth = 1;
401 
402 	/* Each level of quicksort uses a lo and a hi index */
403 	nr_bytes += max_stack_depth * sizeof(xfarray_idx_t) * 2;
404 
405 	/* Scratchpad for in-memory sort, or finding the pivot */
406 	nr_bytes += max_t(size_t,
407 			(XFARRAY_QSORT_PIVOT_NR + 1) * pivot_rec_sz,
408 			XFARRAY_ISORT_NR * array->obj_size);
409 
410 	si = kvzalloc(nr_bytes, XCHK_GFP_FLAGS);
411 	if (!si)
412 		return -ENOMEM;
413 
414 	si->array = array;
415 	si->cmp_fn = cmp_fn;
416 	si->flags = flags;
417 	si->max_stack_depth = max_stack_depth;
418 	si->max_stack_used = 1;
419 
420 	xfarray_sortinfo_lo(si)[0] = 0;
421 	xfarray_sortinfo_hi(si)[0] = array->nr - 1;
422 	si->relax = INIT_XCHK_RELAX;
423 	si->relax.killable = !!(flags & XFARRAY_SORT_KILLABLE);
424 
425 	trace_xfarray_sort(si, nr_bytes);
426 	*infop = si;
427 	return 0;
428 }
429 
430 /* Should this sort be terminated by a fatal signal? */
431 static inline bool
432 xfarray_sort_terminated(
433 	struct xfarray_sortinfo	*si,
434 	int			*error)
435 {
436 	/*
437 	 * If preemption is disabled, we need to yield to the scheduler every
438 	 * few seconds so that we don't run afoul of the soft lockup watchdog
439 	 * or RCU stall detector.
440 	 */
441 	if (xchk_maybe_relax(&si->relax)) {
442 		if (*error == 0)
443 			*error = -EINTR;
444 		return true;
445 	}
446 	return false;
447 }
448 
449 /* Do we want an in-memory sort? */
450 static inline bool
451 xfarray_want_isort(
452 	struct xfarray_sortinfo *si,
453 	xfarray_idx_t		start,
454 	xfarray_idx_t		end)
455 {
456 	/*
457 	 * For array subsets that fit in the scratchpad, it's much faster to
458 	 * use the kernel's heapsort than quicksort's stack machine.
459 	 */
460 	return (end - start) < XFARRAY_ISORT_NR;
461 }
462 
463 /* Return the scratch space within the sortinfo structure. */
464 static inline void *xfarray_sortinfo_isort_scratch(struct xfarray_sortinfo *si)
465 {
466 	return xfarray_sortinfo_hi(si) + si->max_stack_depth;
467 }
468 
469 /*
470  * Sort a small number of array records using scratchpad memory.  The records
471  * need not be contiguous in the xfile's memory pages.
472  */
473 STATIC int
474 xfarray_isort(
475 	struct xfarray_sortinfo	*si,
476 	xfarray_idx_t		lo,
477 	xfarray_idx_t		hi)
478 {
479 	void			*scratch = xfarray_sortinfo_isort_scratch(si);
480 	loff_t			lo_pos = xfarray_pos(si->array, lo);
481 	loff_t			len = xfarray_pos(si->array, hi - lo + 1);
482 	int			error;
483 
484 	trace_xfarray_isort(si, lo, hi);
485 
486 	xfarray_sort_bump_loads(si);
487 	error = xfile_load(si->array->xfile, scratch, len, lo_pos);
488 	if (error)
489 		return error;
490 
491 	xfarray_sort_bump_heapsorts(si);
492 	sort(scratch, hi - lo + 1, si->array->obj_size, si->cmp_fn, NULL);
493 
494 	xfarray_sort_bump_stores(si);
495 	return xfile_store(si->array->xfile, scratch, len, lo_pos);
496 }
497 
498 /*
499  * Sort the records from lo to hi (inclusive) if they are all backed by the
500  * same memory folio.  Returns 1 if it sorted, 0 if it did not, or a negative
501  * errno.
502  */
503 STATIC int
504 xfarray_foliosort(
505 	struct xfarray_sortinfo	*si,
506 	xfarray_idx_t		lo,
507 	xfarray_idx_t		hi)
508 {
509 	struct folio		*folio;
510 	void			*startp;
511 	loff_t			lo_pos = xfarray_pos(si->array, lo);
512 	uint64_t		len = xfarray_pos(si->array, hi - lo + 1);
513 
514 	/* No single folio could back this many records. */
515 	if (len > XFILE_MAX_FOLIO_SIZE)
516 		return 0;
517 
518 	xfarray_sort_bump_loads(si);
519 	folio = xfile_get_folio(si->array->xfile, lo_pos, len, XFILE_ALLOC);
520 	if (IS_ERR(folio))
521 		return PTR_ERR(folio);
522 	if (!folio)
523 		return 0;
524 
525 	trace_xfarray_foliosort(si, lo, hi);
526 
527 	xfarray_sort_bump_heapsorts(si);
528 	startp = folio_address(folio) + offset_in_folio(folio, lo_pos);
529 	sort(startp, hi - lo + 1, si->array->obj_size, si->cmp_fn, NULL);
530 
531 	xfarray_sort_bump_stores(si);
532 	xfile_put_folio(si->array->xfile, folio);
533 	return 1;
534 }
535 
536 /* Return a pointer to the xfarray pivot record within the sortinfo struct. */
537 static inline void *xfarray_sortinfo_pivot(struct xfarray_sortinfo *si)
538 {
539 	return xfarray_sortinfo_hi(si) + si->max_stack_depth;
540 }
541 
542 /* Return a pointer to the start of the pivot array. */
543 static inline void *
544 xfarray_sortinfo_pivot_array(
545 	struct xfarray_sortinfo	*si)
546 {
547 	return xfarray_sortinfo_pivot(si) + si->array->obj_size;
548 }
549 
550 /* The xfarray record is stored at the start of each pivot array element. */
551 static inline void *
552 xfarray_pivot_array_rec(
553 	void			*pa,
554 	size_t			pa_recsz,
555 	unsigned int		pa_idx)
556 {
557 	return pa + (pa_recsz * pa_idx);
558 }
559 
560 /* The xfarray index is stored at the end of each pivot array element. */
561 static inline xfarray_idx_t *
562 xfarray_pivot_array_idx(
563 	void			*pa,
564 	size_t			pa_recsz,
565 	unsigned int		pa_idx)
566 {
567 	return xfarray_pivot_array_rec(pa, pa_recsz, pa_idx + 1) -
568 			sizeof(xfarray_idx_t);
569 }
570 
571 /*
572  * Find a pivot value for quicksort partitioning, swap it with a[lo], and save
573  * the cached pivot record for the next step.
574  *
575  * Load evenly-spaced records within the given range into memory, sort them,
576  * and choose the pivot from the median record.  Using multiple points will
577  * improve the quality of the pivot selection, and hopefully avoid the worst
578  * quicksort behavior, since our array values are nearly always evenly sorted.
579  */
580 STATIC int
581 xfarray_qsort_pivot(
582 	struct xfarray_sortinfo	*si,
583 	xfarray_idx_t		lo,
584 	xfarray_idx_t		hi)
585 {
586 	void			*pivot = xfarray_sortinfo_pivot(si);
587 	void			*parray = xfarray_sortinfo_pivot_array(si);
588 	void			*recp;
589 	xfarray_idx_t		*idxp;
590 	xfarray_idx_t		step = (hi - lo) / (XFARRAY_QSORT_PIVOT_NR - 1);
591 	size_t			pivot_rec_sz = xfarray_pivot_rec_sz(si->array);
592 	int			i, j;
593 	int			error;
594 
595 	ASSERT(step > 0);
596 
597 	/*
598 	 * Load the xfarray indexes of the records we intend to sample into the
599 	 * pivot array.
600 	 */
601 	idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz, 0);
602 	*idxp = lo;
603 	for (i = 1; i < XFARRAY_QSORT_PIVOT_NR - 1; i++) {
604 		idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz, i);
605 		*idxp = lo + (i * step);
606 	}
607 	idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz,
608 			XFARRAY_QSORT_PIVOT_NR - 1);
609 	*idxp = hi;
610 
611 	/* Load the selected xfarray records into the pivot array. */
612 	for (i = 0; i < XFARRAY_QSORT_PIVOT_NR; i++) {
613 		recp = xfarray_pivot_array_rec(parray, pivot_rec_sz, i);
614 		idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz, i);
615 
616 		error = xfarray_sort_load(si, *idxp, recp);
617 		if (error)
618 			return error;
619 	}
620 
621 	xfarray_sort_bump_heapsorts(si);
622 	sort(parray, XFARRAY_QSORT_PIVOT_NR, pivot_rec_sz, si->cmp_fn, NULL);
623 
624 	/*
625 	 * We sorted the pivot array records (which includes the xfarray
626 	 * indices) in xfarray record order.  The median element of the pivot
627 	 * array contains the xfarray record that we will use as the pivot.
628 	 * Copy that xfarray record to the designated space.
629 	 */
630 	recp = xfarray_pivot_array_rec(parray, pivot_rec_sz,
631 			XFARRAY_QSORT_PIVOT_NR / 2);
632 	memcpy(pivot, recp, si->array->obj_size);
633 
634 	/* If the pivot record we chose was already in a[lo] then we're done. */
635 	idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz,
636 			XFARRAY_QSORT_PIVOT_NR / 2);
637 	if (*idxp == lo)
638 		return 0;
639 
640 	/*
641 	 * Find the cached copy of a[lo] in the pivot array so that we can swap
642 	 * a[lo] and a[pivot].
643 	 */
644 	for (i = 0, j = -1; i < XFARRAY_QSORT_PIVOT_NR; i++) {
645 		idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz, i);
646 		if (*idxp == lo)
647 			j = i;
648 	}
649 	if (j < 0) {
650 		ASSERT(j >= 0);
651 		return -EFSCORRUPTED;
652 	}
653 
654 	/* Swap a[lo] and a[pivot]. */
655 	error = xfarray_sort_store(si, lo, pivot);
656 	if (error)
657 		return error;
658 
659 	recp = xfarray_pivot_array_rec(parray, pivot_rec_sz, j);
660 	idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz,
661 			XFARRAY_QSORT_PIVOT_NR / 2);
662 	return xfarray_sort_store(si, *idxp, recp);
663 }
664 
665 /*
666  * Set up the pointers for the next iteration.  We push onto the stack all of
667  * the unsorted values between a[lo + 1] and a[end[i]], and we tweak the
668  * current stack frame to point to the unsorted values between a[beg[i]] and
669  * a[lo] so that those values will be sorted when we pop the stack.
670  */
671 static inline int
672 xfarray_qsort_push(
673 	struct xfarray_sortinfo	*si,
674 	xfarray_idx_t		*si_lo,
675 	xfarray_idx_t		*si_hi,
676 	xfarray_idx_t		lo,
677 	xfarray_idx_t		hi)
678 {
679 	/* Check for stack overflows */
680 	if (si->stack_depth >= si->max_stack_depth - 1) {
681 		ASSERT(si->stack_depth < si->max_stack_depth - 1);
682 		return -EFSCORRUPTED;
683 	}
684 
685 	/*
686 	 * Avoid the integer underflow below in (lo - 1).  This shouldn't
687 	 * be possible because the pivot is the median of nine distinct
688 	 * filesystem metadata records, so at least four records will be less
689 	 * than the pivot, which means the pivot will not be in the low end of
690 	 * the range by the time we get here.
691 	 */
692 	if (lo == 0) {
693 		ASSERT(lo != 0);
694 		return -EFSCORRUPTED;
695 	}
696 
697 	si->max_stack_used = max_t(uint8_t, si->max_stack_used,
698 					    si->stack_depth + 2);
699 
700 	si_lo[si->stack_depth + 1] = lo + 1;
701 	si_hi[si->stack_depth + 1] = si_hi[si->stack_depth];
702 	si_hi[si->stack_depth++] = lo - 1;
703 
704 	/*
705 	 * Always start with the smaller of the two partitions to keep the
706 	 * amount of recursion in check.
707 	 */
708 	if (si_hi[si->stack_depth]     - si_lo[si->stack_depth] >
709 	    si_hi[si->stack_depth - 1] - si_lo[si->stack_depth - 1]) {
710 		swap(si_lo[si->stack_depth], si_lo[si->stack_depth - 1]);
711 		swap(si_hi[si->stack_depth], si_hi[si->stack_depth - 1]);
712 	}
713 
714 	return 0;
715 }
716 
717 static inline void
718 xfarray_sort_scan_done(
719 	struct xfarray_sortinfo	*si)
720 {
721 	if (si->folio)
722 		xfile_put_folio(si->array->xfile, si->folio);
723 	si->folio = NULL;
724 }
725 
726 static int
727 xfarray_sort_load_folio(
728 	struct xfarray_sortinfo	*si,
729 	xfarray_idx_t		idx,
730 	loff_t			idx_pos)
731 {
732 	struct folio		*folio;
733 	loff_t			next_pos;
734 
735 	folio = xfile_get_folio(si->array->xfile, idx_pos, si->array->obj_size,
736 			XFILE_ALLOC);
737 	if (IS_ERR(folio))
738 		return PTR_ERR(folio);
739 	si->folio = folio;
740 
741 	/* No folio?  Get the caller to read into the scratchpad. */
742 	if (!si->folio)
743 		return 0;
744 
745 	si->first_folio_idx = xfarray_idx(si->array,
746 			folio_pos(si->folio) + si->array->obj_size - 1);
747 
748 	next_pos = folio_next_pos(si->folio);
749 	si->last_folio_idx = xfarray_idx(si->array, next_pos - 1);
750 	if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos)
751 		si->last_folio_idx--;
752 
753 	/*
754 	 * If this folio still doesn't cover the desired element, it must cross
755 	 * a folio boundary.  Get the caller to read into the scratchpad.
756 	 */
757 	if (idx < si->first_folio_idx || idx > si->last_folio_idx) {
758 		xfarray_sort_scan_done(si);
759 		return 0;
760 	}
761 
762 	trace_xfarray_sort_scan(si, idx);
763 	return 0;
764 }
765 
766 /*
767  * Cache the folio backing the start of the given array element.  If the array
768  * element is contained entirely within the folio, return a pointer to the
769  * cached folio.  Otherwise, load the element into the scratchpad and return a
770  * pointer to the scratchpad.
771  */
772 static inline int
773 xfarray_sort_scan(
774 	struct xfarray_sortinfo	*si,
775 	xfarray_idx_t		idx,
776 	void			**ptrp)
777 {
778 	loff_t			idx_pos = xfarray_pos(si->array, idx);
779 	int			error = 0;
780 
781 	if (xfarray_sort_terminated(si, &error))
782 		return error;
783 
784 	trace_xfarray_sort_scan(si, idx);
785 
786 	/* If the cached folio doesn't cover this index, release it. */
787 	if (si->folio &&
788 	    (idx < si->first_folio_idx || idx > si->last_folio_idx))
789 		xfarray_sort_scan_done(si);
790 
791 	/* Grab the folio that backs this array element. */
792 	if (!si->folio) {
793 		error = xfarray_sort_load_folio(si, idx, idx_pos);
794 		if (error)
795 			return error;
796 	}
797 
798 	/*
799 	 * If we don't have a folio mapping the entire array element, read into
800 	 * the scratchpad and we're done.
801 	 */
802 	if (!si->folio) {
803 		void		*temp = xfarray_scratch(si->array);
804 
805 		error = xfile_load(si->array->xfile, temp, si->array->obj_size,
806 				idx_pos);
807 		if (error)
808 			return error;
809 
810 		*ptrp = temp;
811 		return 0;
812 	}
813 
814 	/* Otherwise return a pointer to the array element in the folio. */
815 	*ptrp = folio_address(si->folio) + offset_in_folio(si->folio, idx_pos);
816 	return 0;
817 }
818 
819 /*
820  * Sort the array elements via quicksort.  This implementation incorporates
821  * four optimizations discussed in Sedgewick:
822  *
823  * 1. Use an explicit stack of array indices to store the next array partition
824  *    to sort.  This helps us to avoid recursion in the call stack, which is
825  *    particularly expensive in the kernel.
826  *
827  * 2. For arrays with records in arbitrary or user-controlled order, choose the
828  *    pivot element using a median-of-nine decision tree.  This reduces the
829  *    probability of selecting a bad pivot value which causes worst case
830  *    behavior (i.e. partition sizes of 1).
831  *
832  * 3. The smaller of the two sub-partitions is pushed onto the stack to start
833  *    the next level of recursion, and the larger sub-partition replaces the
834  *    current stack frame.  This guarantees that we won't need more than
835  *    log2(nr) stack space.
836  *
837  * 4. For small sets, load the records into the scratchpad and run heapsort on
838  *    them because that is very fast.  In the author's experience, this yields
839  *    a ~10% reduction in runtime.
840  *
841  *    If a small set is contained entirely within a single xfile memory page,
842  *    map the page directly and run heap sort directly on the xfile page
843  *    instead of using the load/store interface.  This halves the runtime.
844  *
845  * 5. This optimization is specific to the implementation.  When converging lo
846  *    and hi after selecting a pivot, we will try to retain the xfile memory
847  *    page between load calls, which reduces run time by 50%.
848  */
849 
850 /*
851  * Due to the use of signed indices, we can only support up to 2^63 records.
852  * Files can only grow to 2^63 bytes, so this is not much of a limitation.
853  */
854 #define QSORT_MAX_RECS		(1ULL << 63)
855 
856 int
857 xfarray_sort(
858 	struct xfarray		*array,
859 	xfarray_cmp_fn		cmp_fn,
860 	unsigned int		flags)
861 {
862 	struct xfarray_sortinfo	*si;
863 	xfarray_idx_t		*si_lo, *si_hi;
864 	void			*pivot;
865 	void			*scratch = xfarray_scratch(array);
866 	xfarray_idx_t		lo, hi;
867 	int			error = 0;
868 
869 	if (array->nr < 2)
870 		return 0;
871 	if (array->nr >= QSORT_MAX_RECS)
872 		return -E2BIG;
873 	if (array->possibly_sparse) {
874 		/*
875 		 * What does it mean to sort an array with holes in it?
876 		 * Currently none of the users need this ability.
877 		 */
878 		ASSERT(!array->possibly_sparse);
879 		return -EINVAL;
880 	}
881 
882 	error = xfarray_sortinfo_alloc(array, cmp_fn, flags, &si);
883 	if (error)
884 		return error;
885 	si_lo = xfarray_sortinfo_lo(si);
886 	si_hi = xfarray_sortinfo_hi(si);
887 	pivot = xfarray_sortinfo_pivot(si);
888 
889 	while (si->stack_depth >= 0) {
890 		int		ret;
891 
892 		lo = si_lo[si->stack_depth];
893 		hi = si_hi[si->stack_depth];
894 
895 		trace_xfarray_qsort(si, lo, hi);
896 
897 		/* Nothing left in this partition to sort; pop stack. */
898 		if (lo >= hi) {
899 			si->stack_depth--;
900 			continue;
901 		}
902 
903 		/*
904 		 * If directly mapping the folio and sorting can solve our
905 		 * problems, we're done.
906 		 */
907 		ret = xfarray_foliosort(si, lo, hi);
908 		if (ret < 0) {
909 			error = ret;
910 			goto out_free;
911 		}
912 		if (ret == 1) {
913 			si->stack_depth--;
914 			continue;
915 		}
916 
917 		/* If insertion sort can solve our problems, we're done. */
918 		if (xfarray_want_isort(si, lo, hi)) {
919 			error = xfarray_isort(si, lo, hi);
920 			if (error)
921 				goto out_free;
922 			si->stack_depth--;
923 			continue;
924 		}
925 
926 		/* Pick a pivot, move it to a[lo] and stash it. */
927 		error = xfarray_qsort_pivot(si, lo, hi);
928 		if (error)
929 			goto out_free;
930 
931 		/*
932 		 * Rearrange a[lo..hi] such that everything smaller than the
933 		 * pivot is on the left side of the range and everything larger
934 		 * than the pivot is on the right side of the range.
935 		 */
936 		while (lo < hi) {
937 			void	*p;
938 
939 			/*
940 			 * Decrement hi until it finds an a[hi] less than the
941 			 * pivot value.
942 			 */
943 			error = xfarray_sort_scan(si, hi, &p);
944 			if (error)
945 				goto out_free;
946 			while (xfarray_sort_cmp(si, p, pivot) >= 0 && lo < hi) {
947 				hi--;
948 				error = xfarray_sort_scan(si, hi, &p);
949 				if (error)
950 					goto out_free;
951 			}
952 			if (p != scratch)
953 				memcpy(scratch, p, si->array->obj_size);
954 			xfarray_sort_scan_done(si);
955 			if (xfarray_sort_terminated(si, &error))
956 				goto out_free;
957 
958 			/* Copy that item (a[hi]) to a[lo]. */
959 			if (lo < hi) {
960 				error = xfarray_sort_store(si, lo++, scratch);
961 				if (error)
962 					goto out_free;
963 			}
964 
965 			/*
966 			 * Increment lo until it finds an a[lo] greater than
967 			 * the pivot value.
968 			 */
969 			error = xfarray_sort_scan(si, lo, &p);
970 			if (error)
971 				goto out_free;
972 			while (xfarray_sort_cmp(si, p, pivot) <= 0 && lo < hi) {
973 				lo++;
974 				error = xfarray_sort_scan(si, lo, &p);
975 				if (error)
976 					goto out_free;
977 			}
978 			if (p != scratch)
979 				memcpy(scratch, p, si->array->obj_size);
980 			xfarray_sort_scan_done(si);
981 			if (xfarray_sort_terminated(si, &error))
982 				goto out_free;
983 
984 			/* Copy that item (a[lo]) to a[hi]. */
985 			if (lo < hi) {
986 				error = xfarray_sort_store(si, hi--, scratch);
987 				if (error)
988 					goto out_free;
989 			}
990 
991 			if (xfarray_sort_terminated(si, &error))
992 				goto out_free;
993 		}
994 
995 		/*
996 		 * Put our pivot value in the correct place at a[lo].  All
997 		 * values between a[beg[i]] and a[lo - 1] should be less than
998 		 * the pivot; and all values between a[lo + 1] and a[end[i]-1]
999 		 * should be greater than the pivot.
1000 		 */
1001 		error = xfarray_sort_store(si, lo, pivot);
1002 		if (error)
1003 			goto out_free;
1004 
1005 		/* Set up the stack frame to process the two partitions. */
1006 		error = xfarray_qsort_push(si, si_lo, si_hi, lo, hi);
1007 		if (error)
1008 			goto out_free;
1009 
1010 		if (xfarray_sort_terminated(si, &error))
1011 			goto out_free;
1012 	}
1013 
1014 out_free:
1015 	trace_xfarray_sort_stats(si, error);
1016 	xfarray_sort_scan_done(si);
1017 	kvfree(si);
1018 	return error;
1019 }
1020 
1021 /* How many bytes is this array consuming? */
1022 unsigned long long
1023 xfarray_bytes(
1024 	struct xfarray		*array)
1025 {
1026 	return xfile_bytes(array->xfile);
1027 }
1028 
1029 /* Empty the entire array. */
1030 void
1031 xfarray_truncate(
1032 	struct xfarray	*array)
1033 {
1034 	xfile_discard(array->xfile, 0, MAX_LFS_FILESIZE);
1035 	array->nr = 0;
1036 	array->possibly_sparse = false;
1037 }
1038