2018-04-11 02:36:52 +03:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
|
|
#ifndef _LINUX_XARRAY_H
|
|
|
|
#define _LINUX_XARRAY_H
|
|
|
|
/*
|
|
|
|
* eXtensible Arrays
|
|
|
|
* Copyright (c) 2017 Microsoft Corporation
|
2018-06-17 00:32:07 +03:00
|
|
|
* Author: Matthew Wilcox <willy@infradead.org>
|
2017-11-03 20:30:42 +03:00
|
|
|
*
|
|
|
|
* See Documentation/core-api/xarray.rst for how to use the XArray.
|
2018-04-11 02:36:52 +03:00
|
|
|
*/
|
|
|
|
|
2017-11-03 20:30:42 +03:00
|
|
|
#include <linux/bug.h>
|
2017-11-08 00:30:10 +03:00
|
|
|
#include <linux/compiler.h>
|
|
|
|
#include <linux/kconfig.h>
|
2018-04-11 02:36:52 +03:00
|
|
|
#include <linux/spinlock.h>
|
2017-11-03 20:30:42 +03:00
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The bottom two bits of the entry determine how the XArray interprets
|
|
|
|
* the contents:
|
|
|
|
*
|
|
|
|
* 00: Pointer entry
|
|
|
|
* 10: Internal entry
|
|
|
|
* x1: Value entry or tagged pointer
|
|
|
|
*
|
|
|
|
* Attempting to store internal entries in the XArray is a bug.
|
2017-11-04 06:09:45 +03:00
|
|
|
*
|
|
|
|
* Most internal entries are pointers to the next node in the tree.
|
|
|
|
* The following internal entries have a special meaning:
|
|
|
|
*
|
|
|
|
* 0-62: Sibling entries
|
|
|
|
* 256: Retry entry
|
2017-11-03 20:30:42 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define BITS_PER_XA_VALUE (BITS_PER_LONG - 1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_mk_value() - Create an XArray entry from an integer.
|
|
|
|
* @v: Value to store in XArray.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: An entry suitable for storing in the XArray.
|
|
|
|
*/
|
|
|
|
static inline void *xa_mk_value(unsigned long v)
|
|
|
|
{
|
|
|
|
WARN_ON((long)v < 0);
|
|
|
|
return (void *)((v << 1) | 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_to_value() - Get value stored in an XArray entry.
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: The value stored in the XArray entry.
|
|
|
|
*/
|
|
|
|
static inline unsigned long xa_to_value(const void *entry)
|
|
|
|
{
|
|
|
|
return (unsigned long)entry >> 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_is_value() - Determine if an entry is a value.
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: True if the entry is a value, false if it is a pointer.
|
|
|
|
*/
|
|
|
|
static inline bool xa_is_value(const void *entry)
|
|
|
|
{
|
|
|
|
return (unsigned long)entry & 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_tag_pointer() - Create an XArray entry for a tagged pointer.
|
|
|
|
* @p: Plain pointer.
|
|
|
|
* @tag: Tag value (0, 1 or 3).
|
|
|
|
*
|
|
|
|
* If the user of the XArray prefers, they can tag their pointers instead
|
|
|
|
* of storing value entries. Three tags are available (0, 1 and 3).
|
|
|
|
* These are distinct from the xa_mark_t as they are not replicated up
|
|
|
|
* through the array and cannot be searched for.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: An XArray entry.
|
|
|
|
*/
|
|
|
|
static inline void *xa_tag_pointer(void *p, unsigned long tag)
|
|
|
|
{
|
|
|
|
return (void *)((unsigned long)p | tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_untag_pointer() - Turn an XArray entry into a plain pointer.
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* If you have stored a tagged pointer in the XArray, call this function
|
|
|
|
* to get the untagged version of the pointer.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: A pointer.
|
|
|
|
*/
|
|
|
|
static inline void *xa_untag_pointer(void *entry)
|
|
|
|
{
|
|
|
|
return (void *)((unsigned long)entry & ~3UL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_pointer_tag() - Get the tag stored in an XArray entry.
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* If you have stored a tagged pointer in the XArray, call this function
|
|
|
|
* to get the tag of that pointer.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: A tag.
|
|
|
|
*/
|
|
|
|
static inline unsigned int xa_pointer_tag(void *entry)
|
|
|
|
{
|
|
|
|
return (unsigned long)entry & 3UL;
|
|
|
|
}
|
2018-04-11 02:36:52 +03:00
|
|
|
|
2017-11-04 06:09:45 +03:00
|
|
|
/*
|
|
|
|
* xa_mk_internal() - Create an internal entry.
|
|
|
|
* @v: Value to turn into an internal entry.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: An XArray internal entry corresponding to this value.
|
|
|
|
*/
|
|
|
|
static inline void *xa_mk_internal(unsigned long v)
|
|
|
|
{
|
|
|
|
return (void *)((v << 2) | 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* xa_to_internal() - Extract the value from an internal entry.
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: The value which was stored in the internal entry.
|
|
|
|
*/
|
|
|
|
static inline unsigned long xa_to_internal(const void *entry)
|
|
|
|
{
|
|
|
|
return (unsigned long)entry >> 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* xa_is_internal() - Is the entry an internal entry?
|
|
|
|
* @entry: XArray entry.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return: %true if the entry is an internal entry.
|
|
|
|
*/
|
|
|
|
static inline bool xa_is_internal(const void *entry)
|
|
|
|
{
|
|
|
|
return ((unsigned long)entry & 3) == 2;
|
|
|
|
}
|
|
|
|
|
2017-11-08 00:30:10 +03:00
|
|
|
/**
|
|
|
|
* struct xarray - The anchor of the XArray.
|
|
|
|
* @xa_lock: Lock that protects the contents of the XArray.
|
|
|
|
*
|
|
|
|
* To use the xarray, define it statically or embed it in your data structure.
|
|
|
|
* It is a very small data structure, so it does not usually make sense to
|
|
|
|
* allocate it separately and keep a pointer to it in your data structure.
|
|
|
|
*
|
|
|
|
* You may use the xa_lock to protect your own data structures as well.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* If all of the entries in the array are NULL, @xa_head is a NULL pointer.
|
|
|
|
* If the only non-NULL entry in the array is at index 0, @xa_head is that
|
|
|
|
* entry. If any other entry in the array is non-NULL, @xa_head points
|
|
|
|
* to an @xa_node.
|
|
|
|
*/
|
|
|
|
struct xarray {
|
|
|
|
spinlock_t xa_lock;
|
|
|
|
/* private: The rest of the data structure is not to be used directly. */
|
|
|
|
gfp_t xa_flags;
|
|
|
|
void __rcu * xa_head;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define XARRAY_INIT(name, flags) { \
|
|
|
|
.xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \
|
|
|
|
.xa_flags = flags, \
|
|
|
|
.xa_head = NULL, \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DEFINE_XARRAY_FLAGS() - Define an XArray with custom flags.
|
|
|
|
* @name: A string that names your XArray.
|
|
|
|
* @flags: XA_FLAG values.
|
|
|
|
*
|
|
|
|
* This is intended for file scope definitions of XArrays. It declares
|
|
|
|
* and initialises an empty XArray with the chosen name and flags. It is
|
|
|
|
* equivalent to calling xa_init_flags() on the array, but it does the
|
|
|
|
* initialisation at compiletime instead of runtime.
|
|
|
|
*/
|
|
|
|
#define DEFINE_XARRAY_FLAGS(name, flags) \
|
|
|
|
struct xarray name = XARRAY_INIT(name, flags)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DEFINE_XARRAY() - Define an XArray.
|
|
|
|
* @name: A string that names your XArray.
|
|
|
|
*
|
|
|
|
* This is intended for file scope definitions of XArrays. It declares
|
|
|
|
* and initialises an empty XArray with the chosen name. It is equivalent
|
|
|
|
* to calling xa_init() on the array, but it does the initialisation at
|
|
|
|
* compiletime instead of runtime.
|
|
|
|
*/
|
|
|
|
#define DEFINE_XARRAY(name) DEFINE_XARRAY_FLAGS(name, 0)
|
|
|
|
|
|
|
|
void xa_init_flags(struct xarray *, gfp_t flags);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_init() - Initialise an empty XArray.
|
|
|
|
* @xa: XArray.
|
|
|
|
*
|
|
|
|
* An empty XArray is full of NULL entries.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
*/
|
|
|
|
static inline void xa_init(struct xarray *xa)
|
|
|
|
{
|
|
|
|
xa_init_flags(xa, 0);
|
|
|
|
}
|
|
|
|
|
2018-04-11 02:36:52 +03:00
|
|
|
#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)
|
|
|
|
#define xa_lock(xa) spin_lock(&(xa)->xa_lock)
|
|
|
|
#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)
|
|
|
|
#define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock)
|
|
|
|
#define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock)
|
|
|
|
#define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock)
|
|
|
|
#define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock)
|
|
|
|
#define xa_lock_irqsave(xa, flags) \
|
|
|
|
spin_lock_irqsave(&(xa)->xa_lock, flags)
|
|
|
|
#define xa_unlock_irqrestore(xa, flags) \
|
|
|
|
spin_unlock_irqrestore(&(xa)->xa_lock, flags)
|
|
|
|
|
2017-11-04 06:09:45 +03:00
|
|
|
/* Everything below here is the Advanced API. Proceed with caution. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The xarray is constructed out of a set of 'chunks' of pointers. Choosing
|
|
|
|
* the best chunk size requires some tradeoffs. A power of two recommends
|
|
|
|
* itself so that we can walk the tree based purely on shifts and masks.
|
|
|
|
* Generally, the larger the better; as the number of slots per level of the
|
|
|
|
* tree increases, the less tall the tree needs to be. But that needs to be
|
|
|
|
* balanced against the memory consumption of each node. On a 64-bit system,
|
|
|
|
* xa_node is currently 576 bytes, and we get 7 of them per 4kB page. If we
|
|
|
|
* doubled the number of slots per node, we'd get only 3 nodes per 4kB page.
|
|
|
|
*/
|
|
|
|
#ifndef XA_CHUNK_SHIFT
|
|
|
|
#define XA_CHUNK_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)
|
|
|
|
#endif
|
|
|
|
#define XA_CHUNK_SIZE (1UL << XA_CHUNK_SHIFT)
|
|
|
|
#define XA_CHUNK_MASK (XA_CHUNK_SIZE - 1)
|
2017-11-09 17:23:56 +03:00
|
|
|
#define XA_MAX_MARKS 3
|
|
|
|
#define XA_MARK_LONGS DIV_ROUND_UP(XA_CHUNK_SIZE, BITS_PER_LONG)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @count is the count of every non-NULL element in the ->slots array
|
|
|
|
* whether that is a value entry, a retry entry, a user pointer,
|
|
|
|
* a sibling entry or a pointer to the next level of the tree.
|
|
|
|
* @nr_values is the count of every element in ->slots which is
|
|
|
|
* either a value entry or a sibling of a value entry.
|
|
|
|
*/
|
|
|
|
struct xa_node {
|
|
|
|
unsigned char shift; /* Bits remaining in each slot */
|
|
|
|
unsigned char offset; /* Slot offset in parent */
|
|
|
|
unsigned char count; /* Total entry count */
|
|
|
|
unsigned char nr_values; /* Value entry count */
|
|
|
|
struct xa_node __rcu *parent; /* NULL at top of tree */
|
|
|
|
struct xarray *array; /* The array we belong to */
|
|
|
|
union {
|
|
|
|
struct list_head private_list; /* For tree user */
|
|
|
|
struct rcu_head rcu_head; /* Used when freeing node */
|
|
|
|
};
|
|
|
|
void __rcu *slots[XA_CHUNK_SIZE];
|
|
|
|
union {
|
|
|
|
unsigned long tags[XA_MAX_MARKS][XA_MARK_LONGS];
|
|
|
|
unsigned long marks[XA_MAX_MARKS][XA_MARK_LONGS];
|
|
|
|
};
|
|
|
|
};
|
2017-11-04 06:09:45 +03:00
|
|
|
|
|
|
|
/* Private */
|
|
|
|
static inline bool xa_is_node(const void *entry)
|
|
|
|
{
|
|
|
|
return xa_is_internal(entry) && (unsigned long)entry > 4096;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Private */
|
|
|
|
static inline void *xa_mk_sibling(unsigned int offset)
|
|
|
|
{
|
|
|
|
return xa_mk_internal(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Private */
|
|
|
|
static inline unsigned long xa_to_sibling(const void *entry)
|
|
|
|
{
|
|
|
|
return xa_to_internal(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xa_is_sibling() - Is the entry a sibling entry?
|
|
|
|
* @entry: Entry retrieved from the XArray
|
|
|
|
*
|
|
|
|
* Return: %true if the entry is a sibling entry.
|
|
|
|
*/
|
|
|
|
static inline bool xa_is_sibling(const void *entry)
|
|
|
|
{
|
|
|
|
return IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) &&
|
|
|
|
(entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define XA_RETRY_ENTRY xa_mk_internal(256)
|
|
|
|
|
2018-04-11 02:36:52 +03:00
|
|
|
#endif /* _LINUX_XARRAY_H */
|