18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#ifndef _BCACHE_UTIL_H 48c2ecf20Sopenharmony_ci#define _BCACHE_UTIL_H 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 78c2ecf20Sopenharmony_ci#include <linux/errno.h> 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/sched/clock.h> 108c2ecf20Sopenharmony_ci#include <linux/llist.h> 118c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 128c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 138c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 148c2ecf20Sopenharmony_ci#include <linux/crc64.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "closure.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define PAGE_SECTORS (PAGE_SIZE / 512) 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct closure; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#ifdef CONFIG_BCACHE_DEBUG 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define EBUG_ON(cond) BUG_ON(cond) 258c2ecf20Sopenharmony_ci#define atomic_dec_bug(v) BUG_ON(atomic_dec_return(v) < 0) 268c2ecf20Sopenharmony_ci#define atomic_inc_bug(v, i) BUG_ON(atomic_inc_return(v) <= i) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#else /* DEBUG */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define EBUG_ON(cond) do { if (cond); } while (0) 318c2ecf20Sopenharmony_ci#define atomic_dec_bug(v) atomic_dec(v) 328c2ecf20Sopenharmony_ci#define atomic_inc_bug(v, i) atomic_inc(v) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#endif 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define DECLARE_HEAP(type, name) \ 378c2ecf20Sopenharmony_ci struct { \ 388c2ecf20Sopenharmony_ci size_t size, used; \ 398c2ecf20Sopenharmony_ci type *data; \ 408c2ecf20Sopenharmony_ci } name 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define init_heap(heap, _size, gfp) \ 438c2ecf20Sopenharmony_ci({ \ 448c2ecf20Sopenharmony_ci size_t _bytes; \ 458c2ecf20Sopenharmony_ci (heap)->used = 0; \ 468c2ecf20Sopenharmony_ci (heap)->size = (_size); \ 478c2ecf20Sopenharmony_ci _bytes = (heap)->size * sizeof(*(heap)->data); \ 488c2ecf20Sopenharmony_ci (heap)->data = kvmalloc(_bytes, (gfp) & GFP_KERNEL); \ 498c2ecf20Sopenharmony_ci (heap)->data; \ 508c2ecf20Sopenharmony_ci}) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define free_heap(heap) \ 538c2ecf20Sopenharmony_cido { \ 548c2ecf20Sopenharmony_ci kvfree((heap)->data); \ 558c2ecf20Sopenharmony_ci (heap)->data = NULL; \ 568c2ecf20Sopenharmony_ci} while (0) 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define heap_swap(h, i, j) swap((h)->data[i], (h)->data[j]) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define heap_sift(h, i, cmp) \ 618c2ecf20Sopenharmony_cido { \ 628c2ecf20Sopenharmony_ci size_t _r, _j = i; \ 638c2ecf20Sopenharmony_ci \ 648c2ecf20Sopenharmony_ci for (; _j * 2 + 1 < (h)->used; _j = _r) { \ 658c2ecf20Sopenharmony_ci _r = _j * 2 + 1; \ 668c2ecf20Sopenharmony_ci if (_r + 1 < (h)->used && \ 678c2ecf20Sopenharmony_ci cmp((h)->data[_r], (h)->data[_r + 1])) \ 688c2ecf20Sopenharmony_ci _r++; \ 698c2ecf20Sopenharmony_ci \ 708c2ecf20Sopenharmony_ci if (cmp((h)->data[_r], (h)->data[_j])) \ 718c2ecf20Sopenharmony_ci break; \ 728c2ecf20Sopenharmony_ci heap_swap(h, _r, _j); \ 738c2ecf20Sopenharmony_ci } \ 748c2ecf20Sopenharmony_ci} while (0) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define heap_sift_down(h, i, cmp) \ 778c2ecf20Sopenharmony_cido { \ 788c2ecf20Sopenharmony_ci while (i) { \ 798c2ecf20Sopenharmony_ci size_t p = (i - 1) / 2; \ 808c2ecf20Sopenharmony_ci if (cmp((h)->data[i], (h)->data[p])) \ 818c2ecf20Sopenharmony_ci break; \ 828c2ecf20Sopenharmony_ci heap_swap(h, i, p); \ 838c2ecf20Sopenharmony_ci i = p; \ 848c2ecf20Sopenharmony_ci } \ 858c2ecf20Sopenharmony_ci} while (0) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define heap_add(h, d, cmp) \ 888c2ecf20Sopenharmony_ci({ \ 898c2ecf20Sopenharmony_ci bool _r = !heap_full(h); \ 908c2ecf20Sopenharmony_ci if (_r) { \ 918c2ecf20Sopenharmony_ci size_t _i = (h)->used++; \ 928c2ecf20Sopenharmony_ci (h)->data[_i] = d; \ 938c2ecf20Sopenharmony_ci \ 948c2ecf20Sopenharmony_ci heap_sift_down(h, _i, cmp); \ 958c2ecf20Sopenharmony_ci heap_sift(h, _i, cmp); \ 968c2ecf20Sopenharmony_ci } \ 978c2ecf20Sopenharmony_ci _r; \ 988c2ecf20Sopenharmony_ci}) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define heap_pop(h, d, cmp) \ 1018c2ecf20Sopenharmony_ci({ \ 1028c2ecf20Sopenharmony_ci bool _r = (h)->used; \ 1038c2ecf20Sopenharmony_ci if (_r) { \ 1048c2ecf20Sopenharmony_ci (d) = (h)->data[0]; \ 1058c2ecf20Sopenharmony_ci (h)->used--; \ 1068c2ecf20Sopenharmony_ci heap_swap(h, 0, (h)->used); \ 1078c2ecf20Sopenharmony_ci heap_sift(h, 0, cmp); \ 1088c2ecf20Sopenharmony_ci } \ 1098c2ecf20Sopenharmony_ci _r; \ 1108c2ecf20Sopenharmony_ci}) 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#define heap_peek(h) ((h)->used ? (h)->data[0] : NULL) 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#define heap_full(h) ((h)->used == (h)->size) 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define DECLARE_FIFO(type, name) \ 1178c2ecf20Sopenharmony_ci struct { \ 1188c2ecf20Sopenharmony_ci size_t front, back, size, mask; \ 1198c2ecf20Sopenharmony_ci type *data; \ 1208c2ecf20Sopenharmony_ci } name 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define fifo_for_each(c, fifo, iter) \ 1238c2ecf20Sopenharmony_ci for (iter = (fifo)->front; \ 1248c2ecf20Sopenharmony_ci c = (fifo)->data[iter], iter != (fifo)->back; \ 1258c2ecf20Sopenharmony_ci iter = (iter + 1) & (fifo)->mask) 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define __init_fifo(fifo, gfp) \ 1288c2ecf20Sopenharmony_ci({ \ 1298c2ecf20Sopenharmony_ci size_t _allocated_size, _bytes; \ 1308c2ecf20Sopenharmony_ci BUG_ON(!(fifo)->size); \ 1318c2ecf20Sopenharmony_ci \ 1328c2ecf20Sopenharmony_ci _allocated_size = roundup_pow_of_two((fifo)->size + 1); \ 1338c2ecf20Sopenharmony_ci _bytes = _allocated_size * sizeof(*(fifo)->data); \ 1348c2ecf20Sopenharmony_ci \ 1358c2ecf20Sopenharmony_ci (fifo)->mask = _allocated_size - 1; \ 1368c2ecf20Sopenharmony_ci (fifo)->front = (fifo)->back = 0; \ 1378c2ecf20Sopenharmony_ci \ 1388c2ecf20Sopenharmony_ci (fifo)->data = kvmalloc(_bytes, (gfp) & GFP_KERNEL); \ 1398c2ecf20Sopenharmony_ci (fifo)->data; \ 1408c2ecf20Sopenharmony_ci}) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define init_fifo_exact(fifo, _size, gfp) \ 1438c2ecf20Sopenharmony_ci({ \ 1448c2ecf20Sopenharmony_ci (fifo)->size = (_size); \ 1458c2ecf20Sopenharmony_ci __init_fifo(fifo, gfp); \ 1468c2ecf20Sopenharmony_ci}) 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci#define init_fifo(fifo, _size, gfp) \ 1498c2ecf20Sopenharmony_ci({ \ 1508c2ecf20Sopenharmony_ci (fifo)->size = (_size); \ 1518c2ecf20Sopenharmony_ci if ((fifo)->size > 4) \ 1528c2ecf20Sopenharmony_ci (fifo)->size = roundup_pow_of_two((fifo)->size) - 1; \ 1538c2ecf20Sopenharmony_ci __init_fifo(fifo, gfp); \ 1548c2ecf20Sopenharmony_ci}) 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define free_fifo(fifo) \ 1578c2ecf20Sopenharmony_cido { \ 1588c2ecf20Sopenharmony_ci kvfree((fifo)->data); \ 1598c2ecf20Sopenharmony_ci (fifo)->data = NULL; \ 1608c2ecf20Sopenharmony_ci} while (0) 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define fifo_used(fifo) (((fifo)->back - (fifo)->front) & (fifo)->mask) 1638c2ecf20Sopenharmony_ci#define fifo_free(fifo) ((fifo)->size - fifo_used(fifo)) 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci#define fifo_empty(fifo) (!fifo_used(fifo)) 1668c2ecf20Sopenharmony_ci#define fifo_full(fifo) (!fifo_free(fifo)) 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#define fifo_front(fifo) ((fifo)->data[(fifo)->front]) 1698c2ecf20Sopenharmony_ci#define fifo_back(fifo) \ 1708c2ecf20Sopenharmony_ci ((fifo)->data[((fifo)->back - 1) & (fifo)->mask]) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#define fifo_idx(fifo, p) (((p) - &fifo_front(fifo)) & (fifo)->mask) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#define fifo_push_back(fifo, i) \ 1758c2ecf20Sopenharmony_ci({ \ 1768c2ecf20Sopenharmony_ci bool _r = !fifo_full((fifo)); \ 1778c2ecf20Sopenharmony_ci if (_r) { \ 1788c2ecf20Sopenharmony_ci (fifo)->data[(fifo)->back++] = (i); \ 1798c2ecf20Sopenharmony_ci (fifo)->back &= (fifo)->mask; \ 1808c2ecf20Sopenharmony_ci } \ 1818c2ecf20Sopenharmony_ci _r; \ 1828c2ecf20Sopenharmony_ci}) 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#define fifo_pop_front(fifo, i) \ 1858c2ecf20Sopenharmony_ci({ \ 1868c2ecf20Sopenharmony_ci bool _r = !fifo_empty((fifo)); \ 1878c2ecf20Sopenharmony_ci if (_r) { \ 1888c2ecf20Sopenharmony_ci (i) = (fifo)->data[(fifo)->front++]; \ 1898c2ecf20Sopenharmony_ci (fifo)->front &= (fifo)->mask; \ 1908c2ecf20Sopenharmony_ci } \ 1918c2ecf20Sopenharmony_ci _r; \ 1928c2ecf20Sopenharmony_ci}) 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#define fifo_push_front(fifo, i) \ 1958c2ecf20Sopenharmony_ci({ \ 1968c2ecf20Sopenharmony_ci bool _r = !fifo_full((fifo)); \ 1978c2ecf20Sopenharmony_ci if (_r) { \ 1988c2ecf20Sopenharmony_ci --(fifo)->front; \ 1998c2ecf20Sopenharmony_ci (fifo)->front &= (fifo)->mask; \ 2008c2ecf20Sopenharmony_ci (fifo)->data[(fifo)->front] = (i); \ 2018c2ecf20Sopenharmony_ci } \ 2028c2ecf20Sopenharmony_ci _r; \ 2038c2ecf20Sopenharmony_ci}) 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#define fifo_pop_back(fifo, i) \ 2068c2ecf20Sopenharmony_ci({ \ 2078c2ecf20Sopenharmony_ci bool _r = !fifo_empty((fifo)); \ 2088c2ecf20Sopenharmony_ci if (_r) { \ 2098c2ecf20Sopenharmony_ci --(fifo)->back; \ 2108c2ecf20Sopenharmony_ci (fifo)->back &= (fifo)->mask; \ 2118c2ecf20Sopenharmony_ci (i) = (fifo)->data[(fifo)->back] \ 2128c2ecf20Sopenharmony_ci } \ 2138c2ecf20Sopenharmony_ci _r; \ 2148c2ecf20Sopenharmony_ci}) 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci#define fifo_push(fifo, i) fifo_push_back(fifo, (i)) 2178c2ecf20Sopenharmony_ci#define fifo_pop(fifo, i) fifo_pop_front(fifo, (i)) 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#define fifo_swap(l, r) \ 2208c2ecf20Sopenharmony_cido { \ 2218c2ecf20Sopenharmony_ci swap((l)->front, (r)->front); \ 2228c2ecf20Sopenharmony_ci swap((l)->back, (r)->back); \ 2238c2ecf20Sopenharmony_ci swap((l)->size, (r)->size); \ 2248c2ecf20Sopenharmony_ci swap((l)->mask, (r)->mask); \ 2258c2ecf20Sopenharmony_ci swap((l)->data, (r)->data); \ 2268c2ecf20Sopenharmony_ci} while (0) 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define fifo_move(dest, src) \ 2298c2ecf20Sopenharmony_cido { \ 2308c2ecf20Sopenharmony_ci typeof(*((dest)->data)) _t; \ 2318c2ecf20Sopenharmony_ci while (!fifo_full(dest) && \ 2328c2ecf20Sopenharmony_ci fifo_pop(src, _t)) \ 2338c2ecf20Sopenharmony_ci fifo_push(dest, _t); \ 2348c2ecf20Sopenharmony_ci} while (0) 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/* 2378c2ecf20Sopenharmony_ci * Simple array based allocator - preallocates a number of elements and you can 2388c2ecf20Sopenharmony_ci * never allocate more than that, also has no locking. 2398c2ecf20Sopenharmony_ci * 2408c2ecf20Sopenharmony_ci * Handy because if you know you only need a fixed number of elements you don't 2418c2ecf20Sopenharmony_ci * have to worry about memory allocation failure, and sometimes a mempool isn't 2428c2ecf20Sopenharmony_ci * what you want. 2438c2ecf20Sopenharmony_ci * 2448c2ecf20Sopenharmony_ci * We treat the free elements as entries in a singly linked list, and the 2458c2ecf20Sopenharmony_ci * freelist as a stack - allocating and freeing push and pop off the freelist. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci#define DECLARE_ARRAY_ALLOCATOR(type, name, size) \ 2498c2ecf20Sopenharmony_ci struct { \ 2508c2ecf20Sopenharmony_ci type *freelist; \ 2518c2ecf20Sopenharmony_ci type data[size]; \ 2528c2ecf20Sopenharmony_ci } name 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci#define array_alloc(array) \ 2558c2ecf20Sopenharmony_ci({ \ 2568c2ecf20Sopenharmony_ci typeof((array)->freelist) _ret = (array)->freelist; \ 2578c2ecf20Sopenharmony_ci \ 2588c2ecf20Sopenharmony_ci if (_ret) \ 2598c2ecf20Sopenharmony_ci (array)->freelist = *((typeof((array)->freelist) *) _ret);\ 2608c2ecf20Sopenharmony_ci \ 2618c2ecf20Sopenharmony_ci _ret; \ 2628c2ecf20Sopenharmony_ci}) 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#define array_free(array, ptr) \ 2658c2ecf20Sopenharmony_cido { \ 2668c2ecf20Sopenharmony_ci typeof((array)->freelist) _ptr = ptr; \ 2678c2ecf20Sopenharmony_ci \ 2688c2ecf20Sopenharmony_ci *((typeof((array)->freelist) *) _ptr) = (array)->freelist; \ 2698c2ecf20Sopenharmony_ci (array)->freelist = _ptr; \ 2708c2ecf20Sopenharmony_ci} while (0) 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci#define array_allocator_init(array) \ 2738c2ecf20Sopenharmony_cido { \ 2748c2ecf20Sopenharmony_ci typeof((array)->freelist) _i; \ 2758c2ecf20Sopenharmony_ci \ 2768c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof((array)->data[0]) < sizeof(void *)); \ 2778c2ecf20Sopenharmony_ci (array)->freelist = NULL; \ 2788c2ecf20Sopenharmony_ci \ 2798c2ecf20Sopenharmony_ci for (_i = (array)->data; \ 2808c2ecf20Sopenharmony_ci _i < (array)->data + ARRAY_SIZE((array)->data); \ 2818c2ecf20Sopenharmony_ci _i++) \ 2828c2ecf20Sopenharmony_ci array_free(array, _i); \ 2838c2ecf20Sopenharmony_ci} while (0) 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#define array_freelist_empty(array) ((array)->freelist == NULL) 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci#define ANYSINT_MAX(t) \ 2888c2ecf20Sopenharmony_ci ((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1) 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ciint bch_strtoint_h(const char *cp, int *res); 2918c2ecf20Sopenharmony_ciint bch_strtouint_h(const char *cp, unsigned int *res); 2928c2ecf20Sopenharmony_ciint bch_strtoll_h(const char *cp, long long *res); 2938c2ecf20Sopenharmony_ciint bch_strtoull_h(const char *cp, unsigned long long *res); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic inline int bch_strtol_h(const char *cp, long *res) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32 2988c2ecf20Sopenharmony_ci return bch_strtoint_h(cp, (int *) res); 2998c2ecf20Sopenharmony_ci#else 3008c2ecf20Sopenharmony_ci return bch_strtoll_h(cp, (long long *) res); 3018c2ecf20Sopenharmony_ci#endif 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic inline int bch_strtoul_h(const char *cp, long *res) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32 3078c2ecf20Sopenharmony_ci return bch_strtouint_h(cp, (unsigned int *) res); 3088c2ecf20Sopenharmony_ci#else 3098c2ecf20Sopenharmony_ci return bch_strtoull_h(cp, (unsigned long long *) res); 3108c2ecf20Sopenharmony_ci#endif 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci#define strtoi_h(cp, res) \ 3148c2ecf20Sopenharmony_ci (__builtin_types_compatible_p(typeof(*res), int) \ 3158c2ecf20Sopenharmony_ci ? bch_strtoint_h(cp, (void *) res) \ 3168c2ecf20Sopenharmony_ci : __builtin_types_compatible_p(typeof(*res), long) \ 3178c2ecf20Sopenharmony_ci ? bch_strtol_h(cp, (void *) res) \ 3188c2ecf20Sopenharmony_ci : __builtin_types_compatible_p(typeof(*res), long long) \ 3198c2ecf20Sopenharmony_ci ? bch_strtoll_h(cp, (void *) res) \ 3208c2ecf20Sopenharmony_ci : __builtin_types_compatible_p(typeof(*res), unsigned int) \ 3218c2ecf20Sopenharmony_ci ? bch_strtouint_h(cp, (void *) res) \ 3228c2ecf20Sopenharmony_ci : __builtin_types_compatible_p(typeof(*res), unsigned long) \ 3238c2ecf20Sopenharmony_ci ? bch_strtoul_h(cp, (void *) res) \ 3248c2ecf20Sopenharmony_ci : __builtin_types_compatible_p(typeof(*res), unsigned long long)\ 3258c2ecf20Sopenharmony_ci ? bch_strtoull_h(cp, (void *) res) : -EINVAL) 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci#define strtoul_safe(cp, var) \ 3288c2ecf20Sopenharmony_ci({ \ 3298c2ecf20Sopenharmony_ci unsigned long _v; \ 3308c2ecf20Sopenharmony_ci int _r = kstrtoul(cp, 10, &_v); \ 3318c2ecf20Sopenharmony_ci if (!_r) \ 3328c2ecf20Sopenharmony_ci var = _v; \ 3338c2ecf20Sopenharmony_ci _r; \ 3348c2ecf20Sopenharmony_ci}) 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci#define strtoul_safe_clamp(cp, var, min, max) \ 3378c2ecf20Sopenharmony_ci({ \ 3388c2ecf20Sopenharmony_ci unsigned long _v; \ 3398c2ecf20Sopenharmony_ci int _r = kstrtoul(cp, 10, &_v); \ 3408c2ecf20Sopenharmony_ci if (!_r) \ 3418c2ecf20Sopenharmony_ci var = clamp_t(typeof(var), _v, min, max); \ 3428c2ecf20Sopenharmony_ci _r; \ 3438c2ecf20Sopenharmony_ci}) 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci#define snprint(buf, size, var) \ 3468c2ecf20Sopenharmony_ci snprintf(buf, size, \ 3478c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), int) \ 3488c2ecf20Sopenharmony_ci ? "%i\n" : \ 3498c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), unsigned int) \ 3508c2ecf20Sopenharmony_ci ? "%u\n" : \ 3518c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), long) \ 3528c2ecf20Sopenharmony_ci ? "%li\n" : \ 3538c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), unsigned long)\ 3548c2ecf20Sopenharmony_ci ? "%lu\n" : \ 3558c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), int64_t) \ 3568c2ecf20Sopenharmony_ci ? "%lli\n" : \ 3578c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), uint64_t) \ 3588c2ecf20Sopenharmony_ci ? "%llu\n" : \ 3598c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(var), const char *) \ 3608c2ecf20Sopenharmony_ci ? "%s\n" : "%i\n", var) 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cissize_t bch_hprint(char *buf, int64_t v); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cibool bch_is_zero(const char *p, size_t n); 3658c2ecf20Sopenharmony_ciint bch_parse_uuid(const char *s, char *uuid); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistruct time_stats { 3688c2ecf20Sopenharmony_ci spinlock_t lock; 3698c2ecf20Sopenharmony_ci /* 3708c2ecf20Sopenharmony_ci * all fields are in nanoseconds, averages are ewmas stored left shifted 3718c2ecf20Sopenharmony_ci * by 8 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci uint64_t max_duration; 3748c2ecf20Sopenharmony_ci uint64_t average_duration; 3758c2ecf20Sopenharmony_ci uint64_t average_frequency; 3768c2ecf20Sopenharmony_ci uint64_t last; 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_civoid bch_time_stats_update(struct time_stats *stats, uint64_t time); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic inline unsigned int local_clock_us(void) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci return local_clock() >> 10; 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci#define NSEC_PER_ns 1L 3878c2ecf20Sopenharmony_ci#define NSEC_PER_us NSEC_PER_USEC 3888c2ecf20Sopenharmony_ci#define NSEC_PER_ms NSEC_PER_MSEC 3898c2ecf20Sopenharmony_ci#define NSEC_PER_sec NSEC_PER_SEC 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci#define __print_time_stat(stats, name, stat, units) \ 3928c2ecf20Sopenharmony_ci sysfs_print(name ## _ ## stat ## _ ## units, \ 3938c2ecf20Sopenharmony_ci div_u64((stats)->stat >> 8, NSEC_PER_ ## units)) 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci#define sysfs_print_time_stats(stats, name, \ 3968c2ecf20Sopenharmony_ci frequency_units, \ 3978c2ecf20Sopenharmony_ci duration_units) \ 3988c2ecf20Sopenharmony_cido { \ 3998c2ecf20Sopenharmony_ci __print_time_stat(stats, name, \ 4008c2ecf20Sopenharmony_ci average_frequency, frequency_units); \ 4018c2ecf20Sopenharmony_ci __print_time_stat(stats, name, \ 4028c2ecf20Sopenharmony_ci average_duration, duration_units); \ 4038c2ecf20Sopenharmony_ci sysfs_print(name ## _ ##max_duration ## _ ## duration_units, \ 4048c2ecf20Sopenharmony_ci div_u64((stats)->max_duration, \ 4058c2ecf20Sopenharmony_ci NSEC_PER_ ## duration_units)); \ 4068c2ecf20Sopenharmony_ci \ 4078c2ecf20Sopenharmony_ci sysfs_print(name ## _last_ ## frequency_units, (stats)->last \ 4088c2ecf20Sopenharmony_ci ? div_s64(local_clock() - (stats)->last, \ 4098c2ecf20Sopenharmony_ci NSEC_PER_ ## frequency_units) \ 4108c2ecf20Sopenharmony_ci : -1LL); \ 4118c2ecf20Sopenharmony_ci} while (0) 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci#define sysfs_time_stats_attribute(name, \ 4148c2ecf20Sopenharmony_ci frequency_units, \ 4158c2ecf20Sopenharmony_ci duration_units) \ 4168c2ecf20Sopenharmony_ciread_attribute(name ## _average_frequency_ ## frequency_units); \ 4178c2ecf20Sopenharmony_ciread_attribute(name ## _average_duration_ ## duration_units); \ 4188c2ecf20Sopenharmony_ciread_attribute(name ## _max_duration_ ## duration_units); \ 4198c2ecf20Sopenharmony_ciread_attribute(name ## _last_ ## frequency_units) 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci#define sysfs_time_stats_attribute_list(name, \ 4228c2ecf20Sopenharmony_ci frequency_units, \ 4238c2ecf20Sopenharmony_ci duration_units) \ 4248c2ecf20Sopenharmony_ci&sysfs_ ## name ## _average_frequency_ ## frequency_units, \ 4258c2ecf20Sopenharmony_ci&sysfs_ ## name ## _average_duration_ ## duration_units, \ 4268c2ecf20Sopenharmony_ci&sysfs_ ## name ## _max_duration_ ## duration_units, \ 4278c2ecf20Sopenharmony_ci&sysfs_ ## name ## _last_ ## frequency_units, 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci#define ewma_add(ewma, val, weight, factor) \ 4308c2ecf20Sopenharmony_ci({ \ 4318c2ecf20Sopenharmony_ci (ewma) *= (weight) - 1; \ 4328c2ecf20Sopenharmony_ci (ewma) += (val) << factor; \ 4338c2ecf20Sopenharmony_ci (ewma) /= (weight); \ 4348c2ecf20Sopenharmony_ci (ewma) >> factor; \ 4358c2ecf20Sopenharmony_ci}) 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistruct bch_ratelimit { 4388c2ecf20Sopenharmony_ci /* Next time we want to do some work, in nanoseconds */ 4398c2ecf20Sopenharmony_ci uint64_t next; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci /* 4428c2ecf20Sopenharmony_ci * Rate at which we want to do work, in units per second 4438c2ecf20Sopenharmony_ci * The units here correspond to the units passed to bch_next_delay() 4448c2ecf20Sopenharmony_ci */ 4458c2ecf20Sopenharmony_ci atomic_long_t rate; 4468c2ecf20Sopenharmony_ci}; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic inline void bch_ratelimit_reset(struct bch_ratelimit *d) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci d->next = local_clock(); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ciuint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci#define __DIV_SAFE(n, d, zero) \ 4568c2ecf20Sopenharmony_ci({ \ 4578c2ecf20Sopenharmony_ci typeof(n) _n = (n); \ 4588c2ecf20Sopenharmony_ci typeof(d) _d = (d); \ 4598c2ecf20Sopenharmony_ci _d ? _n / _d : zero; \ 4608c2ecf20Sopenharmony_ci}) 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci#define DIV_SAFE(n, d) __DIV_SAFE(n, d, 0) 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci#define container_of_or_null(ptr, type, member) \ 4658c2ecf20Sopenharmony_ci({ \ 4668c2ecf20Sopenharmony_ci typeof(ptr) _ptr = ptr; \ 4678c2ecf20Sopenharmony_ci _ptr ? container_of(_ptr, type, member) : NULL; \ 4688c2ecf20Sopenharmony_ci}) 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci#define RB_INSERT(root, new, member, cmp) \ 4718c2ecf20Sopenharmony_ci({ \ 4728c2ecf20Sopenharmony_ci __label__ dup; \ 4738c2ecf20Sopenharmony_ci struct rb_node **n = &(root)->rb_node, *parent = NULL; \ 4748c2ecf20Sopenharmony_ci typeof(new) this; \ 4758c2ecf20Sopenharmony_ci int res, ret = -1; \ 4768c2ecf20Sopenharmony_ci \ 4778c2ecf20Sopenharmony_ci while (*n) { \ 4788c2ecf20Sopenharmony_ci parent = *n; \ 4798c2ecf20Sopenharmony_ci this = container_of(*n, typeof(*(new)), member); \ 4808c2ecf20Sopenharmony_ci res = cmp(new, this); \ 4818c2ecf20Sopenharmony_ci if (!res) \ 4828c2ecf20Sopenharmony_ci goto dup; \ 4838c2ecf20Sopenharmony_ci n = res < 0 \ 4848c2ecf20Sopenharmony_ci ? &(*n)->rb_left \ 4858c2ecf20Sopenharmony_ci : &(*n)->rb_right; \ 4868c2ecf20Sopenharmony_ci } \ 4878c2ecf20Sopenharmony_ci \ 4888c2ecf20Sopenharmony_ci rb_link_node(&(new)->member, parent, n); \ 4898c2ecf20Sopenharmony_ci rb_insert_color(&(new)->member, root); \ 4908c2ecf20Sopenharmony_ci ret = 0; \ 4918c2ecf20Sopenharmony_cidup: \ 4928c2ecf20Sopenharmony_ci ret; \ 4938c2ecf20Sopenharmony_ci}) 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci#define RB_SEARCH(root, search, member, cmp) \ 4968c2ecf20Sopenharmony_ci({ \ 4978c2ecf20Sopenharmony_ci struct rb_node *n = (root)->rb_node; \ 4988c2ecf20Sopenharmony_ci typeof(&(search)) this, ret = NULL; \ 4998c2ecf20Sopenharmony_ci int res; \ 5008c2ecf20Sopenharmony_ci \ 5018c2ecf20Sopenharmony_ci while (n) { \ 5028c2ecf20Sopenharmony_ci this = container_of(n, typeof(search), member); \ 5038c2ecf20Sopenharmony_ci res = cmp(&(search), this); \ 5048c2ecf20Sopenharmony_ci if (!res) { \ 5058c2ecf20Sopenharmony_ci ret = this; \ 5068c2ecf20Sopenharmony_ci break; \ 5078c2ecf20Sopenharmony_ci } \ 5088c2ecf20Sopenharmony_ci n = res < 0 \ 5098c2ecf20Sopenharmony_ci ? n->rb_left \ 5108c2ecf20Sopenharmony_ci : n->rb_right; \ 5118c2ecf20Sopenharmony_ci } \ 5128c2ecf20Sopenharmony_ci ret; \ 5138c2ecf20Sopenharmony_ci}) 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci#define RB_GREATER(root, search, member, cmp) \ 5168c2ecf20Sopenharmony_ci({ \ 5178c2ecf20Sopenharmony_ci struct rb_node *n = (root)->rb_node; \ 5188c2ecf20Sopenharmony_ci typeof(&(search)) this, ret = NULL; \ 5198c2ecf20Sopenharmony_ci int res; \ 5208c2ecf20Sopenharmony_ci \ 5218c2ecf20Sopenharmony_ci while (n) { \ 5228c2ecf20Sopenharmony_ci this = container_of(n, typeof(search), member); \ 5238c2ecf20Sopenharmony_ci res = cmp(&(search), this); \ 5248c2ecf20Sopenharmony_ci if (res < 0) { \ 5258c2ecf20Sopenharmony_ci ret = this; \ 5268c2ecf20Sopenharmony_ci n = n->rb_left; \ 5278c2ecf20Sopenharmony_ci } else \ 5288c2ecf20Sopenharmony_ci n = n->rb_right; \ 5298c2ecf20Sopenharmony_ci } \ 5308c2ecf20Sopenharmony_ci ret; \ 5318c2ecf20Sopenharmony_ci}) 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci#define RB_FIRST(root, type, member) \ 5348c2ecf20Sopenharmony_ci container_of_or_null(rb_first(root), type, member) 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci#define RB_LAST(root, type, member) \ 5378c2ecf20Sopenharmony_ci container_of_or_null(rb_last(root), type, member) 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci#define RB_NEXT(ptr, member) \ 5408c2ecf20Sopenharmony_ci container_of_or_null(rb_next(&(ptr)->member), typeof(*ptr), member) 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci#define RB_PREV(ptr, member) \ 5438c2ecf20Sopenharmony_ci container_of_or_null(rb_prev(&(ptr)->member), typeof(*ptr), member) 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_cistatic inline uint64_t bch_crc64(const void *p, size_t len) 5468c2ecf20Sopenharmony_ci{ 5478c2ecf20Sopenharmony_ci uint64_t crc = 0xffffffffffffffffULL; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci crc = crc64_be(crc, p, len); 5508c2ecf20Sopenharmony_ci return crc ^ 0xffffffffffffffffULL; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic inline uint64_t bch_crc64_update(uint64_t crc, 5548c2ecf20Sopenharmony_ci const void *p, 5558c2ecf20Sopenharmony_ci size_t len) 5568c2ecf20Sopenharmony_ci{ 5578c2ecf20Sopenharmony_ci crc = crc64_be(crc, p, len); 5588c2ecf20Sopenharmony_ci return crc; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci/* 5628c2ecf20Sopenharmony_ci * A stepwise-linear pseudo-exponential. This returns 1 << (x >> 5638c2ecf20Sopenharmony_ci * frac_bits), with the less-significant bits filled in by linear 5648c2ecf20Sopenharmony_ci * interpolation. 5658c2ecf20Sopenharmony_ci * 5668c2ecf20Sopenharmony_ci * This can also be interpreted as a floating-point number format, 5678c2ecf20Sopenharmony_ci * where the low frac_bits are the mantissa (with implicit leading 5688c2ecf20Sopenharmony_ci * 1 bit), and the more significant bits are the exponent. 5698c2ecf20Sopenharmony_ci * The return value is 1.mantissa * 2^exponent. 5708c2ecf20Sopenharmony_ci * 5718c2ecf20Sopenharmony_ci * The way this is used, fract_bits is 6 and the largest possible 5728c2ecf20Sopenharmony_ci * input is CONGESTED_MAX-1 = 1023 (exponent 16, mantissa 0x1.fc), 5738c2ecf20Sopenharmony_ci * so the maximum output is 0x1fc00. 5748c2ecf20Sopenharmony_ci */ 5758c2ecf20Sopenharmony_cistatic inline unsigned int fract_exp_two(unsigned int x, 5768c2ecf20Sopenharmony_ci unsigned int fract_bits) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci unsigned int mantissa = 1 << fract_bits; /* Implicit bit */ 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci mantissa += x & (mantissa - 1); 5818c2ecf20Sopenharmony_ci x >>= fract_bits; /* The exponent */ 5828c2ecf20Sopenharmony_ci /* Largest intermediate value 0x7f0000 */ 5838c2ecf20Sopenharmony_ci return mantissa << x >> fract_bits; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_civoid bch_bio_map(struct bio *bio, void *base); 5878c2ecf20Sopenharmony_ciint bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic inline sector_t bdev_sectors(struct block_device *bdev) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci return bdev->bd_inode->i_size >> 9; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci#endif /* _BCACHE_UTIL_H */ 594