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