xref: /openbmc/linux/fs/xfs/scrub/xfarray.h (revision c390c6450318345b3caa1996a4ef1367477a5aa8)
13934e8ebSDarrick J. Wong /* SPDX-License-Identifier: GPL-2.0-or-later */
23934e8ebSDarrick J. Wong /*
33934e8ebSDarrick J. Wong  * Copyright (C) 2021-2023 Oracle.  All Rights Reserved.
43934e8ebSDarrick J. Wong  * Author: Darrick J. Wong <djwong@kernel.org>
53934e8ebSDarrick J. Wong  */
63934e8ebSDarrick J. Wong #ifndef __XFS_SCRUB_XFARRAY_H__
73934e8ebSDarrick J. Wong #define __XFS_SCRUB_XFARRAY_H__
83934e8ebSDarrick J. Wong 
93934e8ebSDarrick J. Wong /* xfile array index type, along with cursor initialization */
103934e8ebSDarrick J. Wong typedef uint64_t		xfarray_idx_t;
113934e8ebSDarrick J. Wong #define XFARRAY_CURSOR_INIT	((__force xfarray_idx_t)0)
123934e8ebSDarrick J. Wong 
133934e8ebSDarrick J. Wong /* Iterate each index of an xfile array. */
143934e8ebSDarrick J. Wong #define foreach_xfarray_idx(array, idx) \
153934e8ebSDarrick J. Wong 	for ((idx) = XFARRAY_CURSOR_INIT; \
163934e8ebSDarrick J. Wong 	     (idx) < xfarray_length(array); \
173934e8ebSDarrick J. Wong 	     (idx)++)
183934e8ebSDarrick J. Wong 
193934e8ebSDarrick J. Wong struct xfarray {
203934e8ebSDarrick J. Wong 	/* Underlying file that backs the array. */
213934e8ebSDarrick J. Wong 	struct xfile	*xfile;
223934e8ebSDarrick J. Wong 
233934e8ebSDarrick J. Wong 	/* Number of array elements. */
243934e8ebSDarrick J. Wong 	xfarray_idx_t	nr;
253934e8ebSDarrick J. Wong 
263934e8ebSDarrick J. Wong 	/* Maximum possible array size. */
273934e8ebSDarrick J. Wong 	xfarray_idx_t	max_nr;
283934e8ebSDarrick J. Wong 
293934e8ebSDarrick J. Wong 	/* Number of unset slots in the array below @nr. */
303934e8ebSDarrick J. Wong 	uint64_t	unset_slots;
313934e8ebSDarrick J. Wong 
323934e8ebSDarrick J. Wong 	/* Size of an array element. */
333934e8ebSDarrick J. Wong 	size_t		obj_size;
343934e8ebSDarrick J. Wong 
353934e8ebSDarrick J. Wong 	/* log2 of array element size, if possible. */
363934e8ebSDarrick J. Wong 	int		obj_size_log;
373934e8ebSDarrick J. Wong };
383934e8ebSDarrick J. Wong 
393934e8ebSDarrick J. Wong int xfarray_create(const char *descr, unsigned long long required_capacity,
403934e8ebSDarrick J. Wong 		size_t obj_size, struct xfarray **arrayp);
413934e8ebSDarrick J. Wong void xfarray_destroy(struct xfarray *array);
423934e8ebSDarrick J. Wong int xfarray_load(struct xfarray *array, xfarray_idx_t idx, void *ptr);
433934e8ebSDarrick J. Wong int xfarray_unset(struct xfarray *array, xfarray_idx_t idx);
443934e8ebSDarrick J. Wong int xfarray_store(struct xfarray *array, xfarray_idx_t idx, const void *ptr);
453934e8ebSDarrick J. Wong int xfarray_store_anywhere(struct xfarray *array, const void *ptr);
463934e8ebSDarrick J. Wong bool xfarray_element_is_null(struct xfarray *array, const void *ptr);
473934e8ebSDarrick J. Wong 
483934e8ebSDarrick J. Wong /* Append an element to the array. */
493934e8ebSDarrick J. Wong static inline int xfarray_append(struct xfarray *array, const void *ptr)
503934e8ebSDarrick J. Wong {
513934e8ebSDarrick J. Wong 	return xfarray_store(array, array->nr, ptr);
523934e8ebSDarrick J. Wong }
533934e8ebSDarrick J. Wong 
543934e8ebSDarrick J. Wong uint64_t xfarray_length(struct xfarray *array);
553934e8ebSDarrick J. Wong int xfarray_load_next(struct xfarray *array, xfarray_idx_t *idx, void *rec);
563934e8ebSDarrick J. Wong 
57232ea052SDarrick J. Wong /* Declarations for xfile array sort functionality. */
58232ea052SDarrick J. Wong 
59232ea052SDarrick J. Wong typedef cmp_func_t xfarray_cmp_fn;
60232ea052SDarrick J. Wong 
61*c390c645SDarrick J. Wong /* Perform an in-memory heapsort for small subsets. */
62*c390c645SDarrick J. Wong #define XFARRAY_ISORT_SHIFT		(4)
63*c390c645SDarrick J. Wong #define XFARRAY_ISORT_NR		(1U << XFARRAY_ISORT_SHIFT)
64*c390c645SDarrick J. Wong 
65232ea052SDarrick J. Wong struct xfarray_sortinfo {
66232ea052SDarrick J. Wong 	struct xfarray		*array;
67232ea052SDarrick J. Wong 
68232ea052SDarrick J. Wong 	/* Comparison function for the sort. */
69232ea052SDarrick J. Wong 	xfarray_cmp_fn		cmp_fn;
70232ea052SDarrick J. Wong 
71232ea052SDarrick J. Wong 	/* Maximum height of the partition stack. */
72232ea052SDarrick J. Wong 	uint8_t			max_stack_depth;
73232ea052SDarrick J. Wong 
74232ea052SDarrick J. Wong 	/* Current height of the partition stack. */
75232ea052SDarrick J. Wong 	int8_t			stack_depth;
76232ea052SDarrick J. Wong 
77232ea052SDarrick J. Wong 	/* Maximum stack depth ever used. */
78232ea052SDarrick J. Wong 	uint8_t			max_stack_used;
79232ea052SDarrick J. Wong 
80232ea052SDarrick J. Wong 	/* XFARRAY_SORT_* flags; see below. */
81232ea052SDarrick J. Wong 	unsigned int		flags;
82232ea052SDarrick J. Wong 
83232ea052SDarrick J. Wong #ifdef DEBUG
84232ea052SDarrick J. Wong 	/* Performance statistics. */
85232ea052SDarrick J. Wong 	uint64_t		loads;
86232ea052SDarrick J. Wong 	uint64_t		stores;
87232ea052SDarrick J. Wong 	uint64_t		compares;
88*c390c645SDarrick J. Wong 	uint64_t		heapsorts;
89232ea052SDarrick J. Wong #endif
90232ea052SDarrick J. Wong 
91232ea052SDarrick J. Wong 	/*
92232ea052SDarrick J. Wong 	 * Extra bytes are allocated beyond the end of the structure to store
93232ea052SDarrick J. Wong 	 * quicksort information.  C does not permit multiple VLAs per struct,
94232ea052SDarrick J. Wong 	 * so we document all of this in a comment.
95232ea052SDarrick J. Wong 	 *
96232ea052SDarrick J. Wong 	 * Pretend that we have a typedef for array records:
97232ea052SDarrick J. Wong 	 *
98232ea052SDarrick J. Wong 	 * typedef char[array->obj_size]	xfarray_rec_t;
99232ea052SDarrick J. Wong 	 *
100232ea052SDarrick J. Wong 	 * First comes the quicksort partition stack:
101232ea052SDarrick J. Wong 	 *
102232ea052SDarrick J. Wong 	 * xfarray_idx_t	lo[max_stack_depth];
103232ea052SDarrick J. Wong 	 * xfarray_idx_t	hi[max_stack_depth];
104232ea052SDarrick J. Wong 	 *
105232ea052SDarrick J. Wong 	 * union {
106232ea052SDarrick J. Wong 	 *
107*c390c645SDarrick J. Wong 	 * If for a given subset we decide to use an in-memory sort, we use a
108*c390c645SDarrick J. Wong 	 * block of scratchpad records here to compare items:
109232ea052SDarrick J. Wong 	 *
110*c390c645SDarrick J. Wong 	 * 	xfarray_rec_t	scratch[ISORT_NR];
111232ea052SDarrick J. Wong 	 *
112232ea052SDarrick J. Wong 	 * Otherwise, we want to partition the records to partition the array.
113232ea052SDarrick J. Wong 	 * We store the chosen pivot record here and use the xfarray scratchpad
114232ea052SDarrick J. Wong 	 * to rearrange the array around the pivot:
115232ea052SDarrick J. Wong 	 *
116232ea052SDarrick J. Wong 	 * 	xfarray_rec_t	pivot;
117232ea052SDarrick J. Wong 	 *
118232ea052SDarrick J. Wong 	 * }
119232ea052SDarrick J. Wong 	 */
120232ea052SDarrick J. Wong };
121232ea052SDarrick J. Wong 
122232ea052SDarrick J. Wong /* Sort can be interrupted by a fatal signal. */
123232ea052SDarrick J. Wong #define XFARRAY_SORT_KILLABLE	(1U << 0)
124232ea052SDarrick J. Wong 
125232ea052SDarrick J. Wong int xfarray_sort(struct xfarray *array, xfarray_cmp_fn cmp_fn,
126232ea052SDarrick J. Wong 		unsigned int flags);
127232ea052SDarrick J. Wong 
1283934e8ebSDarrick J. Wong #endif /* __XFS_SCRUB_XFARRAY_H__ */
129