diff options
| author | Matthew Wilcox <willy@infradead.org> | 2017-11-07 16:30:10 -0500 |
|---|---|---|
| committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:45:53 -0400 |
| commit | f8d5d0cc145cc21bfc56ef807dc28102aebbf228 (patch) | |
| tree | 0fcba575e83fb02fd2cb49df1ce1cc55bcd927d3 /lib | |
| parent | 02c02bf12c5d838603eed44195d3e91f094e2ab2 (diff) | |
xarray: Add definition of struct xarray
This is a direct replacement for struct radix_tree_root. Some of the
struct members have changed name; convert those, and use a #define so
that radix_tree users continue to work without change.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Reviewed-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/idr.c | 4 | ||||
| -rw-r--r-- | lib/radix-tree.c | 75 | ||||
| -rw-r--r-- | lib/xarray.c | 44 |
4 files changed, 84 insertions, 41 deletions
diff --git a/lib/Makefile b/lib/Makefile index ca3f7ebb900d..057385f1f145 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -18,7 +18,7 @@ KCOV_INSTRUMENT_debugobjects.o := n | |||
| 18 | KCOV_INSTRUMENT_dynamic_debug.o := n | 18 | KCOV_INSTRUMENT_dynamic_debug.o := n |
| 19 | 19 | ||
| 20 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ | 20 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ |
| 21 | rbtree.o radix-tree.o timerqueue.o\ | 21 | rbtree.o radix-tree.o timerqueue.o xarray.o \ |
| 22 | idr.o int_sqrt.o extable.o \ | 22 | idr.o int_sqrt.o extable.o \ |
| 23 | sha1.o chacha20.o irq_regs.o argv_split.o \ | 23 | sha1.o chacha20.o irq_regs.o argv_split.o \ |
| 24 | flex_proportions.o ratelimit.o show_mem.o \ | 24 | flex_proportions.o ratelimit.o show_mem.o \ |
| @@ -39,8 +39,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, | |||
| 39 | unsigned int base = idr->idr_base; | 39 | unsigned int base = idr->idr_base; |
| 40 | unsigned int id = *nextid; | 40 | unsigned int id = *nextid; |
| 41 | 41 | ||
| 42 | if (WARN_ON_ONCE(!(idr->idr_rt.gfp_mask & ROOT_IS_IDR))) | 42 | if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR))) |
| 43 | idr->idr_rt.gfp_mask |= IDR_RT_MARKER; | 43 | idr->idr_rt.xa_flags |= IDR_RT_MARKER; |
| 44 | 44 | ||
| 45 | id = (id < base) ? 0 : id - base; | 45 | id = (id < base) ? 0 : id - base; |
| 46 | radix_tree_iter_init(&iter, id); | 46 | radix_tree_iter_init(&iter, id); |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 59b28111eabc..299d4bdba109 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
| @@ -124,7 +124,7 @@ static unsigned int radix_tree_descend(const struct radix_tree_node *parent, | |||
| 124 | 124 | ||
| 125 | static inline gfp_t root_gfp_mask(const struct radix_tree_root *root) | 125 | static inline gfp_t root_gfp_mask(const struct radix_tree_root *root) |
| 126 | { | 126 | { |
| 127 | return root->gfp_mask & (__GFP_BITS_MASK & ~GFP_ZONEMASK); | 127 | return root->xa_flags & (__GFP_BITS_MASK & ~GFP_ZONEMASK); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static inline void tag_set(struct radix_tree_node *node, unsigned int tag, | 130 | static inline void tag_set(struct radix_tree_node *node, unsigned int tag, |
| @@ -147,32 +147,32 @@ static inline int tag_get(const struct radix_tree_node *node, unsigned int tag, | |||
| 147 | 147 | ||
| 148 | static inline void root_tag_set(struct radix_tree_root *root, unsigned tag) | 148 | static inline void root_tag_set(struct radix_tree_root *root, unsigned tag) |
| 149 | { | 149 | { |
| 150 | root->gfp_mask |= (__force gfp_t)(1 << (tag + ROOT_TAG_SHIFT)); | 150 | root->xa_flags |= (__force gfp_t)(1 << (tag + ROOT_TAG_SHIFT)); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | static inline void root_tag_clear(struct radix_tree_root *root, unsigned tag) | 153 | static inline void root_tag_clear(struct radix_tree_root *root, unsigned tag) |
| 154 | { | 154 | { |
| 155 | root->gfp_mask &= (__force gfp_t)~(1 << (tag + ROOT_TAG_SHIFT)); | 155 | root->xa_flags &= (__force gfp_t)~(1 << (tag + ROOT_TAG_SHIFT)); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static inline void root_tag_clear_all(struct radix_tree_root *root) | 158 | static inline void root_tag_clear_all(struct radix_tree_root *root) |
| 159 | { | 159 | { |
| 160 | root->gfp_mask &= (1 << ROOT_TAG_SHIFT) - 1; | 160 | root->xa_flags &= (__force gfp_t)((1 << ROOT_TAG_SHIFT) - 1); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag) | 163 | static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag) |
| 164 | { | 164 | { |
| 165 | return (__force int)root->gfp_mask & (1 << (tag + ROOT_TAG_SHIFT)); | 165 | return (__force int)root->xa_flags & (1 << (tag + ROOT_TAG_SHIFT)); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | static inline unsigned root_tags_get(const struct radix_tree_root *root) | 168 | static inline unsigned root_tags_get(const struct radix_tree_root *root) |
| 169 | { | 169 | { |
| 170 | return (__force unsigned)root->gfp_mask >> ROOT_TAG_SHIFT; | 170 | return (__force unsigned)root->xa_flags >> ROOT_TAG_SHIFT; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | static inline bool is_idr(const struct radix_tree_root *root) | 173 | static inline bool is_idr(const struct radix_tree_root *root) |
| 174 | { | 174 | { |
| 175 | return !!(root->gfp_mask & ROOT_IS_IDR); | 175 | return !!(root->xa_flags & ROOT_IS_IDR); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | /* | 178 | /* |
| @@ -291,12 +291,12 @@ static void dump_node(struct radix_tree_node *node, unsigned long index) | |||
| 291 | /* For debug */ | 291 | /* For debug */ |
| 292 | static void radix_tree_dump(struct radix_tree_root *root) | 292 | static void radix_tree_dump(struct radix_tree_root *root) |
| 293 | { | 293 | { |
| 294 | pr_debug("radix root: %p rnode %p tags %x\n", | 294 | pr_debug("radix root: %p xa_head %p tags %x\n", |
| 295 | root, root->rnode, | 295 | root, root->xa_head, |
| 296 | root->gfp_mask >> ROOT_TAG_SHIFT); | 296 | root->xa_flags >> ROOT_TAG_SHIFT); |
| 297 | if (!radix_tree_is_internal_node(root->rnode)) | 297 | if (!radix_tree_is_internal_node(root->xa_head)) |
| 298 | return; | 298 | return; |
| 299 | dump_node(entry_to_node(root->rnode), 0); | 299 | dump_node(entry_to_node(root->xa_head), 0); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static void dump_ida_node(void *entry, unsigned long index) | 302 | static void dump_ida_node(void *entry, unsigned long index) |
| @@ -340,9 +340,9 @@ static void dump_ida_node(void *entry, unsigned long index) | |||
| 340 | static void ida_dump(struct ida *ida) | 340 | static void ida_dump(struct ida *ida) |
| 341 | { | 341 | { |
| 342 | struct radix_tree_root *root = &ida->ida_rt; | 342 | struct radix_tree_root *root = &ida->ida_rt; |
| 343 | pr_debug("ida: %p node %p free %d\n", ida, root->rnode, | 343 | pr_debug("ida: %p node %p free %d\n", ida, root->xa_head, |
| 344 | root->gfp_mask >> ROOT_TAG_SHIFT); | 344 | root->xa_flags >> ROOT_TAG_SHIFT); |
| 345 | dump_ida_node(root->rnode, 0); | 345 | dump_ida_node(root->xa_head, 0); |
| 346 | } | 346 | } |
| 347 | #endif | 347 | #endif |
| 348 | 348 | ||
| @@ -576,7 +576,7 @@ int radix_tree_maybe_preload_order(gfp_t gfp_mask, int order) | |||
| 576 | static unsigned radix_tree_load_root(const struct radix_tree_root *root, | 576 | static unsigned radix_tree_load_root(const struct radix_tree_root *root, |
| 577 | struct radix_tree_node **nodep, unsigned long *maxindex) | 577 | struct radix_tree_node **nodep, unsigned long *maxindex) |
| 578 | { | 578 | { |
| 579 | struct radix_tree_node *node = rcu_dereference_raw(root->rnode); | 579 | struct radix_tree_node *node = rcu_dereference_raw(root->xa_head); |
| 580 | 580 | ||
| 581 | *nodep = node; | 581 | *nodep = node; |
| 582 | 582 | ||
| @@ -605,7 +605,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, | |||
| 605 | while (index > shift_maxindex(maxshift)) | 605 | while (index > shift_maxindex(maxshift)) |
| 606 | maxshift += RADIX_TREE_MAP_SHIFT; | 606 | maxshift += RADIX_TREE_MAP_SHIFT; |
| 607 | 607 | ||
| 608 | entry = rcu_dereference_raw(root->rnode); | 608 | entry = rcu_dereference_raw(root->xa_head); |
| 609 | if (!entry && (!is_idr(root) || root_tag_get(root, IDR_FREE))) | 609 | if (!entry && (!is_idr(root) || root_tag_get(root, IDR_FREE))) |
| 610 | goto out; | 610 | goto out; |
| 611 | 611 | ||
| @@ -633,7 +633,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, | |||
| 633 | if (radix_tree_is_internal_node(entry)) { | 633 | if (radix_tree_is_internal_node(entry)) { |
| 634 | entry_to_node(entry)->parent = node; | 634 | entry_to_node(entry)->parent = node; |
| 635 | } else if (xa_is_value(entry)) { | 635 | } else if (xa_is_value(entry)) { |
| 636 | /* Moving an exceptional root->rnode to a node */ | 636 | /* Moving an exceptional root->xa_head to a node */ |
| 637 | node->exceptional = 1; | 637 | node->exceptional = 1; |
| 638 | } | 638 | } |
| 639 | /* | 639 | /* |
| @@ -642,7 +642,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, | |||
| 642 | */ | 642 | */ |
| 643 | node->slots[0] = (void __rcu *)entry; | 643 | node->slots[0] = (void __rcu *)entry; |
| 644 | entry = node_to_entry(node); | 644 | entry = node_to_entry(node); |
| 645 | rcu_assign_pointer(root->rnode, entry); | 645 | rcu_assign_pointer(root->xa_head, entry); |
| 646 | shift += RADIX_TREE_MAP_SHIFT; | 646 | shift += RADIX_TREE_MAP_SHIFT; |
| 647 | } while (shift <= maxshift); | 647 | } while (shift <= maxshift); |
| 648 | out: | 648 | out: |
| @@ -659,7 +659,7 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root, | |||
| 659 | bool shrunk = false; | 659 | bool shrunk = false; |
| 660 | 660 | ||
| 661 | for (;;) { | 661 | for (;;) { |
| 662 | struct radix_tree_node *node = rcu_dereference_raw(root->rnode); | 662 | struct radix_tree_node *node = rcu_dereference_raw(root->xa_head); |
| 663 | struct radix_tree_node *child; | 663 | struct radix_tree_node *child; |
| 664 | 664 | ||
| 665 | if (!radix_tree_is_internal_node(node)) | 665 | if (!radix_tree_is_internal_node(node)) |
| @@ -695,9 +695,9 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root, | |||
| 695 | * moving the node from one part of the tree to another: if it | 695 | * moving the node from one part of the tree to another: if it |
| 696 | * was safe to dereference the old pointer to it | 696 | * was safe to dereference the old pointer to it |
| 697 | * (node->slots[0]), it will be safe to dereference the new | 697 | * (node->slots[0]), it will be safe to dereference the new |
| 698 | * one (root->rnode) as far as dependent read barriers go. | 698 | * one (root->xa_head) as far as dependent read barriers go. |
| 699 | */ | 699 | */ |
| 700 | root->rnode = (void __rcu *)child; | 700 | root->xa_head = (void __rcu *)child; |
| 701 | if (is_idr(root) && !tag_get(node, IDR_FREE, 0)) | 701 | if (is_idr(root) && !tag_get(node, IDR_FREE, 0)) |
| 702 | root_tag_clear(root, IDR_FREE); | 702 | root_tag_clear(root, IDR_FREE); |
| 703 | 703 | ||
| @@ -745,9 +745,8 @@ static bool delete_node(struct radix_tree_root *root, | |||
| 745 | 745 | ||
| 746 | if (node->count) { | 746 | if (node->count) { |
| 747 | if (node_to_entry(node) == | 747 | if (node_to_entry(node) == |
| 748 | rcu_dereference_raw(root->rnode)) | 748 | rcu_dereference_raw(root->xa_head)) |
| 749 | deleted |= radix_tree_shrink(root, | 749 | deleted |= radix_tree_shrink(root, update_node); |
| 750 | update_node); | ||
| 751 | return deleted; | 750 | return deleted; |
| 752 | } | 751 | } |
| 753 | 752 | ||
| @@ -762,7 +761,7 @@ static bool delete_node(struct radix_tree_root *root, | |||
| 762 | */ | 761 | */ |
| 763 | if (!is_idr(root)) | 762 | if (!is_idr(root)) |
| 764 | root_tag_clear_all(root); | 763 | root_tag_clear_all(root); |
| 765 | root->rnode = NULL; | 764 | root->xa_head = NULL; |
| 766 | } | 765 | } |
| 767 | 766 | ||
| 768 | WARN_ON_ONCE(!list_empty(&node->private_list)); | 767 | WARN_ON_ONCE(!list_empty(&node->private_list)); |
| @@ -787,7 +786,7 @@ static bool delete_node(struct radix_tree_root *root, | |||
| 787 | * at position @index in the radix tree @root. | 786 | * at position @index in the radix tree @root. |
| 788 | * | 787 | * |
| 789 | * Until there is more than one item in the tree, no nodes are | 788 | * Until there is more than one item in the tree, no nodes are |
| 790 | * allocated and @root->rnode is used as a direct slot instead of | 789 | * allocated and @root->xa_head is used as a direct slot instead of |
| 791 | * pointing to a node, in which case *@nodep will be NULL. | 790 | * pointing to a node, in which case *@nodep will be NULL. |
| 792 | * | 791 | * |
| 793 | * Returns -ENOMEM, or 0 for success. | 792 | * Returns -ENOMEM, or 0 for success. |
| @@ -797,7 +796,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, | |||
| 797 | void __rcu ***slotp) | 796 | void __rcu ***slotp) |
| 798 | { | 797 | { |
| 799 | struct radix_tree_node *node = NULL, *child; | 798 | struct radix_tree_node *node = NULL, *child; |
| 800 | void __rcu **slot = (void __rcu **)&root->rnode; | 799 | void __rcu **slot = (void __rcu **)&root->xa_head; |
| 801 | unsigned long maxindex; | 800 | unsigned long maxindex; |
| 802 | unsigned int shift, offset = 0; | 801 | unsigned int shift, offset = 0; |
| 803 | unsigned long max = index | ((1UL << order) - 1); | 802 | unsigned long max = index | ((1UL << order) - 1); |
| @@ -813,7 +812,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, | |||
| 813 | if (error < 0) | 812 | if (error < 0) |
| 814 | return error; | 813 | return error; |
| 815 | shift = error; | 814 | shift = error; |
| 816 | child = rcu_dereference_raw(root->rnode); | 815 | child = rcu_dereference_raw(root->xa_head); |
| 817 | } | 816 | } |
| 818 | 817 | ||
| 819 | while (shift > order) { | 818 | while (shift > order) { |
| @@ -1004,7 +1003,7 @@ EXPORT_SYMBOL(__radix_tree_insert); | |||
| 1004 | * tree @root. | 1003 | * tree @root. |
| 1005 | * | 1004 | * |
| 1006 | * Until there is more than one item in the tree, no nodes are | 1005 | * Until there is more than one item in the tree, no nodes are |
| 1007 | * allocated and @root->rnode is used as a direct slot instead of | 1006 | * allocated and @root->xa_head is used as a direct slot instead of |
| 1008 | * pointing to a node, in which case *@nodep will be NULL. | 1007 | * pointing to a node, in which case *@nodep will be NULL. |
| 1009 | */ | 1008 | */ |
| 1010 | void *__radix_tree_lookup(const struct radix_tree_root *root, | 1009 | void *__radix_tree_lookup(const struct radix_tree_root *root, |
| @@ -1017,7 +1016,7 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, | |||
| 1017 | 1016 | ||
| 1018 | restart: | 1017 | restart: |
| 1019 | parent = NULL; | 1018 | parent = NULL; |
| 1020 | slot = (void __rcu **)&root->rnode; | 1019 | slot = (void __rcu **)&root->xa_head; |
| 1021 | radix_tree_load_root(root, &node, &maxindex); | 1020 | radix_tree_load_root(root, &node, &maxindex); |
| 1022 | if (index > maxindex) | 1021 | if (index > maxindex) |
| 1023 | return NULL; | 1022 | return NULL; |
| @@ -1168,9 +1167,9 @@ void __radix_tree_replace(struct radix_tree_root *root, | |||
| 1168 | /* | 1167 | /* |
| 1169 | * This function supports replacing exceptional entries and | 1168 | * This function supports replacing exceptional entries and |
| 1170 | * deleting entries, but that needs accounting against the | 1169 | * deleting entries, but that needs accounting against the |
| 1171 | * node unless the slot is root->rnode. | 1170 | * node unless the slot is root->xa_head. |
| 1172 | */ | 1171 | */ |
| 1173 | WARN_ON_ONCE(!node && (slot != (void __rcu **)&root->rnode) && | 1172 | WARN_ON_ONCE(!node && (slot != (void __rcu **)&root->xa_head) && |
| 1174 | (count || exceptional)); | 1173 | (count || exceptional)); |
| 1175 | replace_slot(slot, item, node, count, exceptional); | 1174 | replace_slot(slot, item, node, count, exceptional); |
| 1176 | 1175 | ||
| @@ -1722,7 +1721,7 @@ void __rcu **radix_tree_next_chunk(const struct radix_tree_root *root, | |||
| 1722 | iter->tags = 1; | 1721 | iter->tags = 1; |
| 1723 | iter->node = NULL; | 1722 | iter->node = NULL; |
| 1724 | __set_iter_shift(iter, 0); | 1723 | __set_iter_shift(iter, 0); |
| 1725 | return (void __rcu **)&root->rnode; | 1724 | return (void __rcu **)&root->xa_head; |
| 1726 | } | 1725 | } |
| 1727 | 1726 | ||
| 1728 | do { | 1727 | do { |
| @@ -2109,7 +2108,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root, | |||
| 2109 | unsigned long max) | 2108 | unsigned long max) |
| 2110 | { | 2109 | { |
| 2111 | struct radix_tree_node *node = NULL, *child; | 2110 | struct radix_tree_node *node = NULL, *child; |
| 2112 | void __rcu **slot = (void __rcu **)&root->rnode; | 2111 | void __rcu **slot = (void __rcu **)&root->xa_head; |
| 2113 | unsigned long maxindex, start = iter->next_index; | 2112 | unsigned long maxindex, start = iter->next_index; |
| 2114 | unsigned int shift, offset = 0; | 2113 | unsigned int shift, offset = 0; |
| 2115 | 2114 | ||
| @@ -2125,7 +2124,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root, | |||
| 2125 | if (error < 0) | 2124 | if (error < 0) |
| 2126 | return ERR_PTR(error); | 2125 | return ERR_PTR(error); |
| 2127 | shift = error; | 2126 | shift = error; |
| 2128 | child = rcu_dereference_raw(root->rnode); | 2127 | child = rcu_dereference_raw(root->xa_head); |
| 2129 | } | 2128 | } |
| 2130 | if (start == 0 && shift == 0) | 2129 | if (start == 0 && shift == 0) |
| 2131 | shift = RADIX_TREE_MAP_SHIFT; | 2130 | shift = RADIX_TREE_MAP_SHIFT; |
| @@ -2190,10 +2189,10 @@ void __rcu **idr_get_free(struct radix_tree_root *root, | |||
| 2190 | */ | 2189 | */ |
| 2191 | void idr_destroy(struct idr *idr) | 2190 | void idr_destroy(struct idr *idr) |
| 2192 | { | 2191 | { |
| 2193 | struct radix_tree_node *node = rcu_dereference_raw(idr->idr_rt.rnode); | 2192 | struct radix_tree_node *node = rcu_dereference_raw(idr->idr_rt.xa_head); |
| 2194 | if (radix_tree_is_internal_node(node)) | 2193 | if (radix_tree_is_internal_node(node)) |
| 2195 | radix_tree_free_nodes(node); | 2194 | radix_tree_free_nodes(node); |
| 2196 | idr->idr_rt.rnode = NULL; | 2195 | idr->idr_rt.xa_head = NULL; |
| 2197 | root_tag_set(&idr->idr_rt, IDR_FREE); | 2196 | root_tag_set(&idr->idr_rt, IDR_FREE); |
| 2198 | } | 2197 | } |
| 2199 | EXPORT_SYMBOL(idr_destroy); | 2198 | EXPORT_SYMBOL(idr_destroy); |
diff --git a/lib/xarray.c b/lib/xarray.c new file mode 100644 index 000000000000..862f4c64c754 --- /dev/null +++ b/lib/xarray.c | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * XArray implementation | ||
| 4 | * Copyright (c) 2017 Microsoft Corporation | ||
| 5 | * Author: Matthew Wilcox <willy@infradead.org> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/export.h> | ||
| 9 | #include <linux/xarray.h> | ||
| 10 | |||
| 11 | /* | ||
| 12 | * Coding conventions in this file: | ||
| 13 | * | ||
| 14 | * @xa is used to refer to the entire xarray. | ||
| 15 | * @xas is the 'xarray operation state'. It may be either a pointer to | ||
| 16 | * an xa_state, or an xa_state stored on the stack. This is an unfortunate | ||
| 17 | * ambiguity. | ||
| 18 | * @index is the index of the entry being operated on | ||
| 19 | * @mark is an xa_mark_t; a small number indicating one of the mark bits. | ||
| 20 | * @node refers to an xa_node; usually the primary one being operated on by | ||
| 21 | * this function. | ||
| 22 | * @offset is the index into the slots array inside an xa_node. | ||
| 23 | * @parent refers to the @xa_node closer to the head than @node. | ||
| 24 | * @entry refers to something stored in a slot in the xarray | ||
| 25 | */ | ||
| 26 | |||
| 27 | /** | ||
| 28 | * xa_init_flags() - Initialise an empty XArray with flags. | ||
| 29 | * @xa: XArray. | ||
| 30 | * @flags: XA_FLAG values. | ||
| 31 | * | ||
| 32 | * If you need to initialise an XArray with special flags (eg you need | ||
| 33 | * to take the lock from interrupt context), use this function instead | ||
| 34 | * of xa_init(). | ||
| 35 | * | ||
| 36 | * Context: Any context. | ||
| 37 | */ | ||
| 38 | void xa_init_flags(struct xarray *xa, gfp_t flags) | ||
| 39 | { | ||
| 40 | spin_lock_init(&xa->xa_lock); | ||
| 41 | xa->xa_flags = flags; | ||
| 42 | xa->xa_head = NULL; | ||
| 43 | } | ||
| 44 | EXPORT_SYMBOL(xa_init_flags); | ||
