Re: [PATCH v16 1/5] lib/xbitmap: Introduce xbitmap
On 2017/09/30 13:05, Wei Wang wrote: > /** > + * xb_preload - preload for xb_set_bit() > + * @gfp_mask: allocation mask to use for preloading > + * > + * Preallocate memory to use for the next call to xb_set_bit(). This function > + * returns with preemption disabled. It will be enabled by xb_preload_end(). > + */ > +void xb_preload(gfp_t gfp) > +{ > + if (__radix_tree_preload(gfp, XB_PRELOAD_SIZE) < 0) > + preempt_disable(); > + > + if (!this_cpu_read(ida_bitmap)) { > + struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp); > + > + if (!bitmap) > + return; > + bitmap = this_cpu_cmpxchg(ida_bitmap, NULL, bitmap); > + kfree(bitmap); > + } > +} I'm not sure whether this function is safe. __radix_tree_preload() returns 0 with preemption disabled upon success. xb_preload() disables preemption if __radix_tree_preload() fails. Then, kmalloc() is called with preemption disabled, isn't it? But xb_set_page() calls xb_preload(GFP_KERNEL) which might sleep...
Re: [PATCH v16 1/5] lib/xbitmap: Introduce xbitmap
On 2017/09/30 13:05, Wei Wang wrote: > /** > + * xb_preload - preload for xb_set_bit() > + * @gfp_mask: allocation mask to use for preloading > + * > + * Preallocate memory to use for the next call to xb_set_bit(). This function > + * returns with preemption disabled. It will be enabled by xb_preload_end(). > + */ > +void xb_preload(gfp_t gfp) > +{ > + if (__radix_tree_preload(gfp, XB_PRELOAD_SIZE) < 0) > + preempt_disable(); > + > + if (!this_cpu_read(ida_bitmap)) { > + struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp); > + > + if (!bitmap) > + return; > + bitmap = this_cpu_cmpxchg(ida_bitmap, NULL, bitmap); > + kfree(bitmap); > + } > +} I'm not sure whether this function is safe. __radix_tree_preload() returns 0 with preemption disabled upon success. xb_preload() disables preemption if __radix_tree_preload() fails. Then, kmalloc() is called with preemption disabled, isn't it? But xb_set_page() calls xb_preload(GFP_KERNEL) which might sleep...
[PATCH v16 1/5] lib/xbitmap: Introduce xbitmap
From: Matthew WilcoxThe eXtensible Bitmap is a sparse bitmap representation which is efficient for set bits which tend to cluster. It supports up to 'unsigned long' worth of bits, and this commit adds the bare bones -- xb_set_bit(), xb_clear_bit() and xb_test_bit(). More possible optimizations to add in the future: 1) xb_set_bit_range: set a range of bits 2) when searching a bit, if the bit is not found in the slot, move on to the next slot directly. 3) add Tags to help searching Signed-off-by: Wei Wang Cc: Matthew Wilcox Cc: Andrew Morton Cc: Michal Hocko Cc: Michael S. Tsirkin v15->v16 ChangeLog: 1) coding style - separate small functions for bit set/clear/test; 2) Clear a range of bits in a more efficient way: A) clear a range of bits from the same ida bitmap directly rather than search the bitmap again for each bit; B) when the range of bits to clear covers the whole ida bitmap, directly free the bitmap - no need to zero the bitmap first. 3) more efficient bit searching, like 2.A. --- include/linux/radix-tree.h | 2 + include/linux/xbitmap.h| 66 lib/Makefile | 2 +- lib/radix-tree.c | 42 +++- lib/xbitmap.c | 264 + 5 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 include/linux/xbitmap.h create mode 100644 lib/xbitmap.c diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 3e57350..1cffeb3 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -309,6 +309,8 @@ void radix_tree_iter_replace(struct radix_tree_root *, const struct radix_tree_iter *, void __rcu **slot, void *entry); void radix_tree_replace_slot(struct radix_tree_root *, void __rcu **slot, void *entry); +bool __radix_tree_delete(struct radix_tree_root *root, +struct radix_tree_node *node, void __rcu **slot); void __radix_tree_delete_node(struct radix_tree_root *, struct radix_tree_node *, radix_tree_update_node_t update_node, diff --git a/include/linux/xbitmap.h b/include/linux/xbitmap.h new file mode 100644 index 000..f634bd9 --- /dev/null +++ b/include/linux/xbitmap.h @@ -0,0 +1,66 @@ +/* + * eXtensible Bitmaps + * Copyright (c) 2017 Microsoft Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * eXtensible Bitmaps provide an unlimited-size sparse bitmap facility. + * All bits are initially zero. + */ + +#ifndef __XBITMAP_H__ +#define __XBITMAP_H__ + +#include + +struct xb { + struct radix_tree_root xbrt; +}; + +#define XB_INIT { \ + .xbrt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT),\ +} +#define DEFINE_XB(name)struct xb name = XB_INIT + +static inline void xb_init(struct xb *xb) +{ + INIT_RADIX_TREE(>xbrt, IDR_RT_MARKER | GFP_NOWAIT); +} + +int xb_set_bit(struct xb *xb, unsigned long bit); +bool xb_test_bit(struct xb *xb, unsigned long bit); +void xb_clear_bit(struct xb *xb, unsigned long bit); +unsigned long xb_find_next_set_bit(struct xb *xb, unsigned long start, + unsigned long end); +unsigned long xb_find_next_zero_bit(struct xb *xb, unsigned long start, + unsigned long end); +void xb_clear_bit_range(struct xb *xb, unsigned long start, unsigned long end); + +/* Check if the xb tree is empty */ +static inline bool xb_is_empty(const struct xb *xb) +{ + return radix_tree_empty(>xbrt); +} + +void xb_preload(gfp_t gfp); + +/** + * xb_preload_end - end preload section started with xb_preload() + * + * Each xb_preload() should be matched with an invocation of this + * function. See xb_preload() for details. + */ +static inline void xb_preload_end(void) +{ + preempt_enable(); +} + +#endif diff --git a/lib/Makefile b/lib/Makefile index 40c1837..ea50496 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -18,7 +18,7 @@ KCOV_INSTRUMENT_dynamic_debug.o := n lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ -idr.o int_sqrt.o extable.o \ +idr.o xbitmap.o int_sqrt.o extable.o \ sha1.o chacha20.o irq_regs.o argv_split.o \
[PATCH v16 1/5] lib/xbitmap: Introduce xbitmap
From: Matthew Wilcox The eXtensible Bitmap is a sparse bitmap representation which is efficient for set bits which tend to cluster. It supports up to 'unsigned long' worth of bits, and this commit adds the bare bones -- xb_set_bit(), xb_clear_bit() and xb_test_bit(). More possible optimizations to add in the future: 1) xb_set_bit_range: set a range of bits 2) when searching a bit, if the bit is not found in the slot, move on to the next slot directly. 3) add Tags to help searching Signed-off-by: Wei Wang Cc: Matthew Wilcox Cc: Andrew Morton Cc: Michal Hocko Cc: Michael S. Tsirkin v15->v16 ChangeLog: 1) coding style - separate small functions for bit set/clear/test; 2) Clear a range of bits in a more efficient way: A) clear a range of bits from the same ida bitmap directly rather than search the bitmap again for each bit; B) when the range of bits to clear covers the whole ida bitmap, directly free the bitmap - no need to zero the bitmap first. 3) more efficient bit searching, like 2.A. --- include/linux/radix-tree.h | 2 + include/linux/xbitmap.h| 66 lib/Makefile | 2 +- lib/radix-tree.c | 42 +++- lib/xbitmap.c | 264 + 5 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 include/linux/xbitmap.h create mode 100644 lib/xbitmap.c diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 3e57350..1cffeb3 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -309,6 +309,8 @@ void radix_tree_iter_replace(struct radix_tree_root *, const struct radix_tree_iter *, void __rcu **slot, void *entry); void radix_tree_replace_slot(struct radix_tree_root *, void __rcu **slot, void *entry); +bool __radix_tree_delete(struct radix_tree_root *root, +struct radix_tree_node *node, void __rcu **slot); void __radix_tree_delete_node(struct radix_tree_root *, struct radix_tree_node *, radix_tree_update_node_t update_node, diff --git a/include/linux/xbitmap.h b/include/linux/xbitmap.h new file mode 100644 index 000..f634bd9 --- /dev/null +++ b/include/linux/xbitmap.h @@ -0,0 +1,66 @@ +/* + * eXtensible Bitmaps + * Copyright (c) 2017 Microsoft Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * eXtensible Bitmaps provide an unlimited-size sparse bitmap facility. + * All bits are initially zero. + */ + +#ifndef __XBITMAP_H__ +#define __XBITMAP_H__ + +#include + +struct xb { + struct radix_tree_root xbrt; +}; + +#define XB_INIT { \ + .xbrt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT),\ +} +#define DEFINE_XB(name)struct xb name = XB_INIT + +static inline void xb_init(struct xb *xb) +{ + INIT_RADIX_TREE(>xbrt, IDR_RT_MARKER | GFP_NOWAIT); +} + +int xb_set_bit(struct xb *xb, unsigned long bit); +bool xb_test_bit(struct xb *xb, unsigned long bit); +void xb_clear_bit(struct xb *xb, unsigned long bit); +unsigned long xb_find_next_set_bit(struct xb *xb, unsigned long start, + unsigned long end); +unsigned long xb_find_next_zero_bit(struct xb *xb, unsigned long start, + unsigned long end); +void xb_clear_bit_range(struct xb *xb, unsigned long start, unsigned long end); + +/* Check if the xb tree is empty */ +static inline bool xb_is_empty(const struct xb *xb) +{ + return radix_tree_empty(>xbrt); +} + +void xb_preload(gfp_t gfp); + +/** + * xb_preload_end - end preload section started with xb_preload() + * + * Each xb_preload() should be matched with an invocation of this + * function. See xb_preload() for details. + */ +static inline void xb_preload_end(void) +{ + preempt_enable(); +} + +#endif diff --git a/lib/Makefile b/lib/Makefile index 40c1837..ea50496 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -18,7 +18,7 @@ KCOV_INSTRUMENT_dynamic_debug.o := n lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ -idr.o int_sqrt.o extable.o \ +idr.o xbitmap.o int_sqrt.o extable.o \ sha1.o chacha20.o irq_regs.o argv_split.o \ flex_proportions.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ diff --git a/lib/radix-tree.c