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> 13f8d5d0ccSMatthew Wilcox #include <linux/compiler.h> 14f8d5d0ccSMatthew 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 158f8d5d0ccSMatthew Wilcox /** 159f8d5d0ccSMatthew Wilcox * struct xarray - The anchor of the XArray. 160f8d5d0ccSMatthew Wilcox * @xa_lock: Lock that protects the contents of the XArray. 161f8d5d0ccSMatthew Wilcox * 162f8d5d0ccSMatthew Wilcox * To use the xarray, define it statically or embed it in your data structure. 163f8d5d0ccSMatthew Wilcox * It is a very small data structure, so it does not usually make sense to 164f8d5d0ccSMatthew Wilcox * allocate it separately and keep a pointer to it in your data structure. 165f8d5d0ccSMatthew Wilcox * 166f8d5d0ccSMatthew Wilcox * You may use the xa_lock to protect your own data structures as well. 167f8d5d0ccSMatthew Wilcox */ 168f8d5d0ccSMatthew Wilcox /* 169f8d5d0ccSMatthew Wilcox * If all of the entries in the array are NULL, @xa_head is a NULL pointer. 170f8d5d0ccSMatthew Wilcox * If the only non-NULL entry in the array is at index 0, @xa_head is that 171f8d5d0ccSMatthew Wilcox * entry. If any other entry in the array is non-NULL, @xa_head points 172f8d5d0ccSMatthew Wilcox * to an @xa_node. 173f8d5d0ccSMatthew Wilcox */ 174f8d5d0ccSMatthew Wilcox struct xarray { 175f8d5d0ccSMatthew Wilcox spinlock_t xa_lock; 176f8d5d0ccSMatthew Wilcox /* private: The rest of the data structure is not to be used directly. */ 177f8d5d0ccSMatthew Wilcox gfp_t xa_flags; 178f8d5d0ccSMatthew Wilcox void __rcu * xa_head; 179f8d5d0ccSMatthew Wilcox }; 180f8d5d0ccSMatthew Wilcox 181f8d5d0ccSMatthew Wilcox #define XARRAY_INIT(name, flags) { \ 182f8d5d0ccSMatthew Wilcox .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \ 183f8d5d0ccSMatthew Wilcox .xa_flags = flags, \ 184f8d5d0ccSMatthew Wilcox .xa_head = NULL, \ 185f8d5d0ccSMatthew Wilcox } 186f8d5d0ccSMatthew Wilcox 187f8d5d0ccSMatthew Wilcox /** 188f8d5d0ccSMatthew Wilcox * DEFINE_XARRAY_FLAGS() - Define an XArray with custom flags. 189f8d5d0ccSMatthew Wilcox * @name: A string that names your XArray. 190f8d5d0ccSMatthew Wilcox * @flags: XA_FLAG values. 191f8d5d0ccSMatthew Wilcox * 192f8d5d0ccSMatthew Wilcox * This is intended for file scope definitions of XArrays. It declares 193f8d5d0ccSMatthew Wilcox * and initialises an empty XArray with the chosen name and flags. It is 194f8d5d0ccSMatthew Wilcox * equivalent to calling xa_init_flags() on the array, but it does the 195f8d5d0ccSMatthew Wilcox * initialisation at compiletime instead of runtime. 196f8d5d0ccSMatthew Wilcox */ 197f8d5d0ccSMatthew Wilcox #define DEFINE_XARRAY_FLAGS(name, flags) \ 198f8d5d0ccSMatthew Wilcox struct xarray name = XARRAY_INIT(name, flags) 199f8d5d0ccSMatthew Wilcox 200f8d5d0ccSMatthew Wilcox /** 201f8d5d0ccSMatthew Wilcox * DEFINE_XARRAY() - Define an XArray. 202f8d5d0ccSMatthew Wilcox * @name: A string that names your XArray. 203f8d5d0ccSMatthew Wilcox * 204f8d5d0ccSMatthew Wilcox * This is intended for file scope definitions of XArrays. It declares 205f8d5d0ccSMatthew Wilcox * and initialises an empty XArray with the chosen name. It is equivalent 206f8d5d0ccSMatthew Wilcox * to calling xa_init() on the array, but it does the initialisation at 207f8d5d0ccSMatthew Wilcox * compiletime instead of runtime. 208f8d5d0ccSMatthew Wilcox */ 209f8d5d0ccSMatthew Wilcox #define DEFINE_XARRAY(name) DEFINE_XARRAY_FLAGS(name, 0) 210f8d5d0ccSMatthew Wilcox 211f8d5d0ccSMatthew Wilcox void xa_init_flags(struct xarray *, gfp_t flags); 212f8d5d0ccSMatthew Wilcox 213f8d5d0ccSMatthew Wilcox /** 214f8d5d0ccSMatthew Wilcox * xa_init() - Initialise an empty XArray. 215f8d5d0ccSMatthew Wilcox * @xa: XArray. 216f8d5d0ccSMatthew Wilcox * 217f8d5d0ccSMatthew Wilcox * An empty XArray is full of NULL entries. 218f8d5d0ccSMatthew Wilcox * 219f8d5d0ccSMatthew Wilcox * Context: Any context. 220f8d5d0ccSMatthew Wilcox */ 221f8d5d0ccSMatthew Wilcox static inline void xa_init(struct xarray *xa) 222f8d5d0ccSMatthew Wilcox { 223f8d5d0ccSMatthew Wilcox xa_init_flags(xa, 0); 224f8d5d0ccSMatthew Wilcox } 225f8d5d0ccSMatthew 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) 255*01959dfeSMatthew Wilcox #define XA_MAX_MARKS 3 256*01959dfeSMatthew Wilcox #define XA_MARK_LONGS DIV_ROUND_UP(XA_CHUNK_SIZE, BITS_PER_LONG) 257*01959dfeSMatthew Wilcox 258*01959dfeSMatthew Wilcox /* 259*01959dfeSMatthew Wilcox * @count is the count of every non-NULL element in the ->slots array 260*01959dfeSMatthew Wilcox * whether that is a value entry, a retry entry, a user pointer, 261*01959dfeSMatthew Wilcox * a sibling entry or a pointer to the next level of the tree. 262*01959dfeSMatthew Wilcox * @nr_values is the count of every element in ->slots which is 263*01959dfeSMatthew Wilcox * either a value entry or a sibling of a value entry. 264*01959dfeSMatthew Wilcox */ 265*01959dfeSMatthew Wilcox struct xa_node { 266*01959dfeSMatthew Wilcox unsigned char shift; /* Bits remaining in each slot */ 267*01959dfeSMatthew Wilcox unsigned char offset; /* Slot offset in parent */ 268*01959dfeSMatthew Wilcox unsigned char count; /* Total entry count */ 269*01959dfeSMatthew Wilcox unsigned char nr_values; /* Value entry count */ 270*01959dfeSMatthew Wilcox struct xa_node __rcu *parent; /* NULL at top of tree */ 271*01959dfeSMatthew Wilcox struct xarray *array; /* The array we belong to */ 272*01959dfeSMatthew Wilcox union { 273*01959dfeSMatthew Wilcox struct list_head private_list; /* For tree user */ 274*01959dfeSMatthew Wilcox struct rcu_head rcu_head; /* Used when freeing node */ 275*01959dfeSMatthew Wilcox }; 276*01959dfeSMatthew Wilcox void __rcu *slots[XA_CHUNK_SIZE]; 277*01959dfeSMatthew Wilcox union { 278*01959dfeSMatthew Wilcox unsigned long tags[XA_MAX_MARKS][XA_MARK_LONGS]; 279*01959dfeSMatthew Wilcox unsigned long marks[XA_MAX_MARKS][XA_MARK_LONGS]; 280*01959dfeSMatthew Wilcox }; 281*01959dfeSMatthew Wilcox }; 28202c02bf1SMatthew Wilcox 28302c02bf1SMatthew Wilcox /* Private */ 28402c02bf1SMatthew Wilcox static inline bool xa_is_node(const void *entry) 28502c02bf1SMatthew Wilcox { 28602c02bf1SMatthew Wilcox return xa_is_internal(entry) && (unsigned long)entry > 4096; 28702c02bf1SMatthew Wilcox } 28802c02bf1SMatthew Wilcox 28902c02bf1SMatthew Wilcox /* Private */ 29002c02bf1SMatthew Wilcox static inline void *xa_mk_sibling(unsigned int offset) 29102c02bf1SMatthew Wilcox { 29202c02bf1SMatthew Wilcox return xa_mk_internal(offset); 29302c02bf1SMatthew Wilcox } 29402c02bf1SMatthew Wilcox 29502c02bf1SMatthew Wilcox /* Private */ 29602c02bf1SMatthew Wilcox static inline unsigned long xa_to_sibling(const void *entry) 29702c02bf1SMatthew Wilcox { 29802c02bf1SMatthew Wilcox return xa_to_internal(entry); 29902c02bf1SMatthew Wilcox } 30002c02bf1SMatthew Wilcox 30102c02bf1SMatthew Wilcox /** 30202c02bf1SMatthew Wilcox * xa_is_sibling() - Is the entry a sibling entry? 30302c02bf1SMatthew Wilcox * @entry: Entry retrieved from the XArray 30402c02bf1SMatthew Wilcox * 30502c02bf1SMatthew Wilcox * Return: %true if the entry is a sibling entry. 30602c02bf1SMatthew Wilcox */ 30702c02bf1SMatthew Wilcox static inline bool xa_is_sibling(const void *entry) 30802c02bf1SMatthew Wilcox { 30902c02bf1SMatthew Wilcox return IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) && 31002c02bf1SMatthew Wilcox (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1)); 31102c02bf1SMatthew Wilcox } 31202c02bf1SMatthew Wilcox 31302c02bf1SMatthew Wilcox #define XA_RETRY_ENTRY xa_mk_internal(256) 31402c02bf1SMatthew Wilcox 315f6bb2a2cSMatthew Wilcox #endif /* _LINUX_XARRAY_H */ 316