--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef _LINUX_MAPLE_TREE_H
+#define _LINUX_MAPLE_TREE_H
+/*
+ * Maple Tree - An RCU-safe adaptive tree for storing ranges
+ * Copyright (c) 2018 Oracle
+ * Authors: Liam R. Howlett <Liam.Howlett@Oracle.com>
+ * Matthew Wilcox <willy@infradead.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/xarray.h>
+
+/*
+ * Allocated nodes are mutable until they have been inserted into the tree,
+ * at which time they cannot change their type until they have been removed
+ * from the tree and an RCU grace period has passed.
+ *
+ * Removed nodes have their ->parent set to point to themselves. RCU readers
+ * check ->parent before relying on the value that they loaded from the
+ * slots array. This lets us reuse the slots array for the RCU head.
+ *
+ * Nodes in the tree point to their parent unless bit 0 is set.
+ */
+#ifdef CONFIG_64BIT
+#define MAPLE_NODE_SLOTS 15 /* 128 bytes including ->parent */
+#define MAPLE_RANGE64_SLOTS 8 /* 128 bytes */
+#define MAPLE_RANGE32_SLOTS 10 /* 124 bytes */
+#define MAPLE_RANGE16_SLOTS 12 /* 126 bytes */
+#define MAPLE_SPARSE64_SLOTS 7 /* 120 bytes */
+#define MAPLE_SPARSE32_SLOTS 10 /* 128 bytes */
+#define MAPLE_SPARSE21_SLOTS 11 /* 128 bytes */
+#define MAPLE_SPARSE16_SLOTS 12 /* 128 bytes */
+#define MAPLE_SPARSE9_SLOTS 13 /* 127 bytes */
+#define MAPLE_SPARSE6_SLOTS 14 /* 128 bytes */
+#else
+/* Need to do corresponding calculations for 32-bit kernels */
+#endif
+
+/*
+ * We can be more cache-efficient if we interleave pivots and slots.
+ * Code will be more complex, though.
+ */
+struct maple_range_64 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_RANGE64_SLOTS];
+ u64 pivot[MAPLE_RANGE64_SLOTS - 1];
+};
+
+struct maple_range_32 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_RANGE32_SLOTS];
+ u32 pivot[MAPLE_RANGE32_SLOTS - 1];
+};
+
+struct maple_range_16 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_RANGE16_SLOTS];
+ u16 pivot[MAPLE_RANGE16_SLOTS - 1];
+};
+
+struct maple_sparse_64 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE64_SLOTS];
+ u64 pivot[MAPLE_SPARSE64_SLOTS];
+};
+
+struct maple_sparse_32 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE32_SLOTS];
+ u32 pivot[MAPLE_SPARSE32_SLOTS];
+};
+
+struct maple_sparse_21 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE21_SLOTS];
+ u64 pivot[(MAPLE_SPARSE21_SLOTS + 2) / 3];
+};
+
+struct maple_sparse_16 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE16_SLOTS];
+ u16 pivot[MAPLE_SPARSE16_SLOTS];
+};
+
+struct maple_sparse_9 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE9_SLOTS];
+ u64 pivot[(MAPLE_SPARSE9_SLOTS + 6) / 7];
+};
+
+struct maple_sparse_6 {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_SPARSE6_SLOTS];
+ u64 pivot; /* Use a bitmap for pivots */
+};
+
+struct maple_node {
+ union {
+ struct {
+ struct maple_node *parent;
+ void __rcu *slot[MAPLE_NODE_SLOTS];
+ };
+ struct maple_range_64 mr64;
+ struct maple_range_32 mr32;
+ struct maple_range_16 mr16;
+ struct maple_sparse_64 ms64;
+ struct maple_sparse_32 ms32;
+ struct maple_sparse_21 ms21;
+ struct maple_sparse_16 ms16;
+ struct maple_sparse_9 ms9;
+ struct maple_sparse_6 ms6;
+ };
+};
+
+struct maple_tree {
+ spinlock_t ma_lock;
+ unsigned int ma_flags;
+ void __rcu * ma_root;
+};
+
+#define MTREE_INIT(name, flags) { \
+ .ma_lock = __SPIN_LOCK_UNLOCKED(name.ma_lock), \
+ .ma_flags = flags, \
+ .ma_root = NULL, \
+}
+
+#define DEFINE_MTREE(name) \
+ struct maple_tree name = MTREE_INIT(name, 0)
+
+#define mtree_lock(mt) spin_lock(&mt->lock);
+#define mtree_unlock(mt) spin_unlock(&mt->lock);
+
+void mtree_init(struct maple_tree *);
+void *mtree_load(struct maple_tree *, unsigned long index);
+int mtree_insert(struct maple_tree *, unsigned long index, void *entry, gfp_t);
+int mtree_insert_range(struct maple_tree *, unsigned long first,
+ unsigned long last, void *entry, gfp_t);
+int mtree_erase(struct maple_tree *, unsigned long index);
+
+/**
+ * mtree_empty() - Determine if a tree has any present entries.
+ * @mt: Maple Tree.
+ *
+ * Context: Any context.
+ * Return: %true if the tree contains only NULL pointers.
+ */
+static inline bool mtree_empty(const struct maple_tree *mt)
+{
+ return mt->ma_root == NULL;
+}
+
+/* Advanced API */
+
+struct ma_state {
+ struct maple_tree *tree; /* The tree we're operating in */
+ unsigned long index; /* The index we're operating on */
+ unsigned long last; /* The last index we're operating on */
+ struct maple_node *node; /* The node containing this entry */
+ unsigned long min; /* The minimum index of this node */
+ unsigned long max; /* The maximum index of this node */
+ struct maple_node *alloc; /* Allocated nodes for this operation */
+};
+
+/*
+ * Special values for ma_state.node.
+ * MAS_START means we have not searched the tree.
+ * MAS_ROOT means we have searched the tree and the entry we found lives
+ * in the root of the tree (ie it has index 0, length 1 and is the only
+ * entry in the tree).
+ * MAS_NONE means we have searched the tree and there is no node in the
+ * tree for this entry. For example, we searched for index 1 in an empty
+ * tree. Or we have a tree which points to a full leaf node and we
+ * searched for an entry which is larger than can be contained in that
+ * leaf node.
+ * MA_ERROR represents an errno. After dropping the lock and attempting
+ * to resolve the error, the walk would have to be restarted from the
+ * top of the tree as the tree may have been modified.
+ */
+#define MAS_START ((struct maple_node *)1UL)
+#define MAS_ROOT ((struct maple_node *)5UL)
+#define MAS_NONE ((struct maple_node *)9UL)
+#define MA_ERROR(err) ((struct maple_node *)(((unsigned long)err << 2) | 2UL))
+
+#define MA_STATE(name, tree, first, last) \
+ struct ma_state name = { \
+ .tree = tree, \
+ .index = first, \
+ .last = last, \
+ .node = MAS_START, \
+ .min = 0, \
+ .max = ULONG_MAX, \
+ }
+
+void *mas_walk(struct ma_state *);
+void *mas_store(struct ma_state *, void *entry);
+void *mas_find(struct ma_state *, unsigned long max);
+
+bool mas_nomem(struct ma_state *, gfp_t);
+void mas_pause(struct ma_state *);
+#endif