1f6bb2a2cSMatthew Wilcox /* SPDX-License-Identifier: GPL-2.0+ */ 2f6bb2a2cSMatthew Wilcox #ifndef _LINUX_XARRAY_H 3f6bb2a2cSMatthew Wilcox #define _LINUX_XARRAY_H 4f6bb2a2cSMatthew Wilcox /* 5f6bb2a2cSMatthew Wilcox * eXtensible Arrays 6f6bb2a2cSMatthew Wilcox * Copyright (c) 2017 Microsoft Corporation 73d0186bbSMatthew Wilcox * Author: Matthew Wilcox <[email protected]> 83159f943SMatthew Wilcox * 93159f943SMatthew Wilcox * See Documentation/core-api/xarray.rst for how to use the XArray. 10f6bb2a2cSMatthew Wilcox */ 11f6bb2a2cSMatthew Wilcox 123159f943SMatthew Wilcox #include <linux/bug.h> 13*f8d5d0ccSMatthew Wilcox #include <linux/compiler.h> 14*f8d5d0ccSMatthew Wilcox #include <linux/kconfig.h> 15f6bb2a2cSMatthew Wilcox #include <linux/spinlock.h> 163159f943SMatthew Wilcox #include <linux/types.h> 173159f943SMatthew Wilcox 183159f943SMatthew Wilcox /* 193159f943SMatthew Wilcox * The bottom two bits of the entry determine how the XArray interprets 203159f943SMatthew Wilcox * the contents: 213159f943SMatthew Wilcox * 223159f943SMatthew Wilcox * 00: Pointer entry 233159f943SMatthew Wilcox * 10: Internal entry 243159f943SMatthew Wilcox * x1: Value entry or tagged pointer 253159f943SMatthew Wilcox * 263159f943SMatthew Wilcox * Attempting to store internal entries in the XArray is a bug. 2702c02bf1SMatthew Wilcox * 2802c02bf1SMatthew Wilcox * Most internal entries are pointers to the next node in the tree. 2902c02bf1SMatthew Wilcox * The following internal entries have a special meaning: 3002c02bf1SMatthew Wilcox * 3102c02bf1SMatthew Wilcox * 0-62: Sibling entries 3202c02bf1SMatthew Wilcox * 256: Retry entry 333159f943SMatthew Wilcox */ 343159f943SMatthew Wilcox 353159f943SMatthew Wilcox #define BITS_PER_XA_VALUE (BITS_PER_LONG - 1) 363159f943SMatthew Wilcox 373159f943SMatthew Wilcox /** 383159f943SMatthew Wilcox * xa_mk_value() - Create an XArray entry from an integer. 393159f943SMatthew Wilcox * @v: Value to store in XArray. 403159f943SMatthew Wilcox * 413159f943SMatthew Wilcox * Context: Any context. 423159f943SMatthew Wilcox * Return: An entry suitable for storing in the XArray. 433159f943SMatthew Wilcox */ 443159f943SMatthew Wilcox static inline void *xa_mk_value(unsigned long v) 453159f943SMatthew Wilcox { 463159f943SMatthew Wilcox WARN_ON((long)v < 0); 473159f943SMatthew Wilcox return (void *)((v << 1) | 1); 483159f943SMatthew Wilcox } 493159f943SMatthew Wilcox 503159f943SMatthew Wilcox /** 513159f943SMatthew Wilcox * xa_to_value() - Get value stored in an XArray entry. 523159f943SMatthew Wilcox * @entry: XArray entry. 533159f943SMatthew Wilcox * 543159f943SMatthew Wilcox * Context: Any context. 553159f943SMatthew Wilcox * Return: The value stored in the XArray entry. 563159f943SMatthew Wilcox */ 573159f943SMatthew Wilcox static inline unsigned long xa_to_value(const void *entry) 583159f943SMatthew Wilcox { 593159f943SMatthew Wilcox return (unsigned long)entry >> 1; 603159f943SMatthew Wilcox } 613159f943SMatthew Wilcox 623159f943SMatthew Wilcox /** 633159f943SMatthew Wilcox * xa_is_value() - Determine if an entry is a value. 643159f943SMatthew Wilcox * @entry: XArray entry. 653159f943SMatthew Wilcox * 663159f943SMatthew Wilcox * Context: Any context. 673159f943SMatthew Wilcox * Return: True if the entry is a value, false if it is a pointer. 683159f943SMatthew Wilcox */ 693159f943SMatthew Wilcox static inline bool xa_is_value(const void *entry) 703159f943SMatthew Wilcox { 713159f943SMatthew Wilcox return (unsigned long)entry & 1; 723159f943SMatthew Wilcox } 733159f943SMatthew Wilcox 743159f943SMatthew Wilcox /** 753159f943SMatthew Wilcox * xa_tag_pointer() - Create an XArray entry for a tagged pointer. 763159f943SMatthew Wilcox * @p: Plain pointer. 773159f943SMatthew Wilcox * @tag: Tag value (0, 1 or 3). 783159f943SMatthew Wilcox * 793159f943SMatthew Wilcox * If the user of the XArray prefers, they can tag their pointers instead 803159f943SMatthew Wilcox * of storing value entries. Three tags are available (0, 1 and 3). 813159f943SMatthew Wilcox * These are distinct from the xa_mark_t as they are not replicated up 823159f943SMatthew Wilcox * through the array and cannot be searched for. 833159f943SMatthew Wilcox * 843159f943SMatthew Wilcox * Context: Any context. 853159f943SMatthew Wilcox * Return: An XArray entry. 863159f943SMatthew Wilcox */ 873159f943SMatthew Wilcox static inline void *xa_tag_pointer(void *p, unsigned long tag) 883159f943SMatthew Wilcox { 893159f943SMatthew Wilcox return (void *)((unsigned long)p | tag); 903159f943SMatthew Wilcox } 913159f943SMatthew Wilcox 923159f943SMatthew Wilcox /** 933159f943SMatthew Wilcox * xa_untag_pointer() - Turn an XArray entry into a plain pointer. 943159f943SMatthew Wilcox * @entry: XArray entry. 953159f943SMatthew Wilcox * 963159f943SMatthew Wilcox * If you have stored a tagged pointer in the XArray, call this function 973159f943SMatthew Wilcox * to get the untagged version of the pointer. 983159f943SMatthew Wilcox * 993159f943SMatthew Wilcox * Context: Any context. 1003159f943SMatthew Wilcox * Return: A pointer. 1013159f943SMatthew Wilcox */ 1023159f943SMatthew Wilcox static inline void *xa_untag_pointer(void *entry) 1033159f943SMatthew Wilcox { 1043159f943SMatthew Wilcox return (void *)((unsigned long)entry & ~3UL); 1053159f943SMatthew Wilcox } 1063159f943SMatthew Wilcox 1073159f943SMatthew Wilcox /** 1083159f943SMatthew Wilcox * xa_pointer_tag() - Get the tag stored in an XArray entry. 1093159f943SMatthew Wilcox * @entry: XArray entry. 1103159f943SMatthew Wilcox * 1113159f943SMatthew Wilcox * If you have stored a tagged pointer in the XArray, call this function 1123159f943SMatthew Wilcox * to get the tag of that pointer. 1133159f943SMatthew Wilcox * 1143159f943SMatthew Wilcox * Context: Any context. 1153159f943SMatthew Wilcox * Return: A tag. 1163159f943SMatthew Wilcox */ 1173159f943SMatthew Wilcox static inline unsigned int xa_pointer_tag(void *entry) 1183159f943SMatthew Wilcox { 1193159f943SMatthew Wilcox return (unsigned long)entry & 3UL; 1203159f943SMatthew Wilcox } 121f6bb2a2cSMatthew Wilcox 12202c02bf1SMatthew Wilcox /* 12302c02bf1SMatthew Wilcox * xa_mk_internal() - Create an internal entry. 12402c02bf1SMatthew Wilcox * @v: Value to turn into an internal entry. 12502c02bf1SMatthew Wilcox * 12602c02bf1SMatthew Wilcox * Context: Any context. 12702c02bf1SMatthew Wilcox * Return: An XArray internal entry corresponding to this value. 12802c02bf1SMatthew Wilcox */ 12902c02bf1SMatthew Wilcox static inline void *xa_mk_internal(unsigned long v) 13002c02bf1SMatthew Wilcox { 13102c02bf1SMatthew Wilcox return (void *)((v << 2) | 2); 13202c02bf1SMatthew Wilcox } 13302c02bf1SMatthew Wilcox 13402c02bf1SMatthew Wilcox /* 13502c02bf1SMatthew Wilcox * xa_to_internal() - Extract the value from an internal entry. 13602c02bf1SMatthew Wilcox * @entry: XArray entry. 13702c02bf1SMatthew Wilcox * 13802c02bf1SMatthew Wilcox * Context: Any context. 13902c02bf1SMatthew Wilcox * Return: The value which was stored in the internal entry. 14002c02bf1SMatthew Wilcox */ 14102c02bf1SMatthew Wilcox static inline unsigned long xa_to_internal(const void *entry) 14202c02bf1SMatthew Wilcox { 14302c02bf1SMatthew Wilcox return (unsigned long)entry >> 2; 14402c02bf1SMatthew Wilcox } 14502c02bf1SMatthew Wilcox 14602c02bf1SMatthew Wilcox /* 14702c02bf1SMatthew Wilcox * xa_is_internal() - Is the entry an internal entry? 14802c02bf1SMatthew Wilcox * @entry: XArray entry. 14902c02bf1SMatthew Wilcox * 15002c02bf1SMatthew Wilcox * Context: Any context. 15102c02bf1SMatthew Wilcox * Return: %true if the entry is an internal entry. 15202c02bf1SMatthew Wilcox */ 15302c02bf1SMatthew Wilcox static inline bool xa_is_internal(const void *entry) 15402c02bf1SMatthew Wilcox { 15502c02bf1SMatthew Wilcox return ((unsigned long)entry & 3) == 2; 15602c02bf1SMatthew Wilcox } 15702c02bf1SMatthew Wilcox 158*f8d5d0ccSMatthew Wilcox /** 159*f8d5d0ccSMatthew Wilcox * struct xarray - The anchor of the XArray. 160*f8d5d0ccSMatthew Wilcox * @xa_lock: Lock that protects the contents of the XArray. 161*f8d5d0ccSMatthew Wilcox * 162*f8d5d0ccSMatthew Wilcox * To use the xarray, define it statically or embed it in your data structure. 163*f8d5d0ccSMatthew Wilcox * It is a very small data structure, so it does not usually make sense to 164*f8d5d0ccSMatthew Wilcox * allocate it separately and keep a pointer to it in your data structure. 165*f8d5d0ccSMatthew Wilcox * 166*f8d5d0ccSMatthew Wilcox * You may use the xa_lock to protect your own data structures as well. 167*f8d5d0ccSMatthew Wilcox */ 168*f8d5d0ccSMatthew Wilcox /* 169*f8d5d0ccSMatthew Wilcox * If all of the entries in the array are NULL, @xa_head is a NULL pointer. 170*f8d5d0ccSMatthew Wilcox * If the only non-NULL entry in the array is at index 0, @xa_head is that 171*f8d5d0ccSMatthew Wilcox * entry. If any other entry in the array is non-NULL, @xa_head points 172*f8d5d0ccSMatthew Wilcox * to an @xa_node. 173*f8d5d0ccSMatthew Wilcox */ 174*f8d5d0ccSMatthew Wilcox struct xarray { 175*f8d5d0ccSMatthew Wilcox spinlock_t xa_lock; 176*f8d5d0ccSMatthew Wilcox /* private: The rest of the data structure is not to be used directly. */ 177*f8d5d0ccSMatthew Wilcox gfp_t xa_flags; 178*f8d5d0ccSMatthew Wilcox void __rcu * xa_head; 179*f8d5d0ccSMatthew Wilcox }; 180*f8d5d0ccSMatthew Wilcox 181*f8d5d0ccSMatthew Wilcox #define XARRAY_INIT(name, flags) { \ 182*f8d5d0ccSMatthew Wilcox .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \ 183*f8d5d0ccSMatthew Wilcox .xa_flags = flags, \ 184*f8d5d0ccSMatthew Wilcox .xa_head = NULL, \ 185*f8d5d0ccSMatthew Wilcox } 186*f8d5d0ccSMatthew Wilcox 187*f8d5d0ccSMatthew Wilcox /** 188*f8d5d0ccSMatthew Wilcox * DEFINE_XARRAY_FLAGS() - Define an XArray with custom flags. 189*f8d5d0ccSMatthew Wilcox * @name: A string that names your XArray. 190*f8d5d0ccSMatthew Wilcox * @flags: XA_FLAG values. 191*f8d5d0ccSMatthew Wilcox * 192*f8d5d0ccSMatthew Wilcox * This is intended for file scope definitions of XArrays. It declares 193*f8d5d0ccSMatthew Wilcox * and initialises an empty XArray with the chosen name and flags. It is 194*f8d5d0ccSMatthew Wilcox * equivalent to calling xa_init_flags() on the array, but it does the 195*f8d5d0ccSMatthew Wilcox * initialisation at compiletime instead of runtime. 196*f8d5d0ccSMatthew Wilcox */ 197*f8d5d0ccSMatthew Wilcox #define DEFINE_XARRAY_FLAGS(name, flags) \ 198*f8d5d0ccSMatthew Wilcox struct xarray name = XARRAY_INIT(name, flags) 199*f8d5d0ccSMatthew Wilcox 200*f8d5d0ccSMatthew Wilcox /** 201*f8d5d0ccSMatthew Wilcox * DEFINE_XARRAY() - Define an XArray. 202*f8d5d0ccSMatthew Wilcox * @name: A string that names your XArray. 203*f8d5d0ccSMatthew Wilcox * 204*f8d5d0ccSMatthew Wilcox * This is intended for file scope definitions of XArrays. It declares 205*f8d5d0ccSMatthew Wilcox * and initialises an empty XArray with the chosen name. It is equivalent 206*f8d5d0ccSMatthew Wilcox * to calling xa_init() on the array, but it does the initialisation at 207*f8d5d0ccSMatthew Wilcox * compiletime instead of runtime. 208*f8d5d0ccSMatthew Wilcox */ 209*f8d5d0ccSMatthew Wilcox #define DEFINE_XARRAY(name) DEFINE_XARRAY_FLAGS(name, 0) 210*f8d5d0ccSMatthew Wilcox 211*f8d5d0ccSMatthew Wilcox void xa_init_flags(struct xarray *, gfp_t flags); 212*f8d5d0ccSMatthew Wilcox 213*f8d5d0ccSMatthew Wilcox /** 214*f8d5d0ccSMatthew Wilcox * xa_init() - Initialise an empty XArray. 215*f8d5d0ccSMatthew Wilcox * @xa: XArray. 216*f8d5d0ccSMatthew Wilcox * 217*f8d5d0ccSMatthew Wilcox * An empty XArray is full of NULL entries. 218*f8d5d0ccSMatthew Wilcox * 219*f8d5d0ccSMatthew Wilcox * Context: Any context. 220*f8d5d0ccSMatthew Wilcox */ 221*f8d5d0ccSMatthew Wilcox static inline void xa_init(struct xarray *xa) 222*f8d5d0ccSMatthew Wilcox { 223*f8d5d0ccSMatthew Wilcox xa_init_flags(xa, 0); 224*f8d5d0ccSMatthew Wilcox } 225*f8d5d0ccSMatthew Wilcox 226f6bb2a2cSMatthew Wilcox #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) 227f6bb2a2cSMatthew Wilcox #define xa_lock(xa) spin_lock(&(xa)->xa_lock) 228f6bb2a2cSMatthew Wilcox #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) 229f6bb2a2cSMatthew Wilcox #define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock) 230f6bb2a2cSMatthew Wilcox #define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock) 231f6bb2a2cSMatthew Wilcox #define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock) 232f6bb2a2cSMatthew Wilcox #define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock) 233f6bb2a2cSMatthew Wilcox #define xa_lock_irqsave(xa, flags) \ 234f6bb2a2cSMatthew Wilcox spin_lock_irqsave(&(xa)->xa_lock, flags) 235f6bb2a2cSMatthew Wilcox #define xa_unlock_irqrestore(xa, flags) \ 236f6bb2a2cSMatthew Wilcox spin_unlock_irqrestore(&(xa)->xa_lock, flags) 237f6bb2a2cSMatthew Wilcox 23802c02bf1SMatthew Wilcox /* Everything below here is the Advanced API. Proceed with caution. */ 23902c02bf1SMatthew Wilcox 24002c02bf1SMatthew Wilcox /* 24102c02bf1SMatthew Wilcox * The xarray is constructed out of a set of 'chunks' of pointers. Choosing 24202c02bf1SMatthew Wilcox * the best chunk size requires some tradeoffs. A power of two recommends 24302c02bf1SMatthew Wilcox * itself so that we can walk the tree based purely on shifts and masks. 24402c02bf1SMatthew Wilcox * Generally, the larger the better; as the number of slots per level of the 24502c02bf1SMatthew Wilcox * tree increases, the less tall the tree needs to be. But that needs to be 24602c02bf1SMatthew Wilcox * balanced against the memory consumption of each node. On a 64-bit system, 24702c02bf1SMatthew Wilcox * xa_node is currently 576 bytes, and we get 7 of them per 4kB page. If we 24802c02bf1SMatthew Wilcox * doubled the number of slots per node, we'd get only 3 nodes per 4kB page. 24902c02bf1SMatthew Wilcox */ 25002c02bf1SMatthew Wilcox #ifndef XA_CHUNK_SHIFT 25102c02bf1SMatthew Wilcox #define XA_CHUNK_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) 25202c02bf1SMatthew Wilcox #endif 25302c02bf1SMatthew Wilcox #define XA_CHUNK_SIZE (1UL << XA_CHUNK_SHIFT) 25402c02bf1SMatthew Wilcox #define XA_CHUNK_MASK (XA_CHUNK_SIZE - 1) 25502c02bf1SMatthew Wilcox 25602c02bf1SMatthew Wilcox /* Private */ 25702c02bf1SMatthew Wilcox static inline bool xa_is_node(const void *entry) 25802c02bf1SMatthew Wilcox { 25902c02bf1SMatthew Wilcox return xa_is_internal(entry) && (unsigned long)entry > 4096; 26002c02bf1SMatthew Wilcox } 26102c02bf1SMatthew Wilcox 26202c02bf1SMatthew Wilcox /* Private */ 26302c02bf1SMatthew Wilcox static inline void *xa_mk_sibling(unsigned int offset) 26402c02bf1SMatthew Wilcox { 26502c02bf1SMatthew Wilcox return xa_mk_internal(offset); 26602c02bf1SMatthew Wilcox } 26702c02bf1SMatthew Wilcox 26802c02bf1SMatthew Wilcox /* Private */ 26902c02bf1SMatthew Wilcox static inline unsigned long xa_to_sibling(const void *entry) 27002c02bf1SMatthew Wilcox { 27102c02bf1SMatthew Wilcox return xa_to_internal(entry); 27202c02bf1SMatthew Wilcox } 27302c02bf1SMatthew Wilcox 27402c02bf1SMatthew Wilcox /** 27502c02bf1SMatthew Wilcox * xa_is_sibling() - Is the entry a sibling entry? 27602c02bf1SMatthew Wilcox * @entry: Entry retrieved from the XArray 27702c02bf1SMatthew Wilcox * 27802c02bf1SMatthew Wilcox * Return: %true if the entry is a sibling entry. 27902c02bf1SMatthew Wilcox */ 28002c02bf1SMatthew Wilcox static inline bool xa_is_sibling(const void *entry) 28102c02bf1SMatthew Wilcox { 28202c02bf1SMatthew Wilcox return IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) && 28302c02bf1SMatthew Wilcox (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1)); 28402c02bf1SMatthew Wilcox } 28502c02bf1SMatthew Wilcox 28602c02bf1SMatthew Wilcox #define XA_RETRY_ENTRY xa_mk_internal(256) 28702c02bf1SMatthew Wilcox 288f6bb2a2cSMatthew Wilcox #endif /* _LINUX_XARRAY_H */ 289