Message ID | 20231009201639.920512-3-sidhartha.kumar@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | align maple tree write paths | expand |
Hi, 在 2023/10/10 04:16, Sidhartha Kumar 写道: > Preallocate maple nodes before call to mas_wr_store_entry(). If a new > node is not needed, go directly to mas_wr_store_entry(), otherwise > allocate the needed nodes and set the MA_STATE_PREALLOC flag. > > Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> > --- > lib/maple_tree.c | 22 +++++++++++++++++++--- > 1 file changed, 19 insertions(+), 3 deletions(-) > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > index e239197a57fc..25ae66e585f4 100644 > --- a/lib/maple_tree.c > +++ b/lib/maple_tree.c > @@ -5478,17 +5478,33 @@ int mas_prealloc_calc(struct ma_wr_state *wr_mas) > int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp) > { > MA_WR_STATE(wr_mas, mas, entry); > + int request; > > mas_wr_store_setup(&wr_mas); > - trace_ma_write(__func__, mas, 0, entry); > -retry: > + wr_mas.content = mas_start(mas); > + > + request = mas_prealloc_calc(&wr_mas); mas_wr_store_entry() does something similar to mas_prealloc_calc(). Now, making it do it twice would incur additional overhead. We encountered this issue while optimizing preallocation, but it hasn't been resolved yet. Previously, this problem only occurred when using mas_preallocate(). Now, this change would bring this impact to all write operations on maple tree. What do you think about it? Thanks, Peng > + if (!request) > + goto store_entry; > + > + mas_node_count_gfp(mas, request, gfp); > + if (unlikely(mas_is_err(mas))) { > + mas_set_alloc_req(mas, 0); > + mas_destroy(mas); > + mas_reset(mas); > + return xa_err(mas->node); > + } > + mas->mas_flags |= MA_STATE_PREALLOC; > + > +store_entry: > mas_wr_store_entry(&wr_mas); > if (unlikely(mas_nomem(mas, gfp))) > - goto retry; > + goto store_entry; > > if (unlikely(mas_is_err(mas))) > return xa_err(mas->node); > > + trace_ma_write(__func__, mas, 0, entry); > return 0; > } > EXPORT_SYMBOL_GPL(mas_store_gfp);
* Sidhartha Kumar <sidhartha.kumar@oracle.com> [231009 16:16]: > Preallocate maple nodes before call to mas_wr_store_entry(). If a new > node is not needed, go directly to mas_wr_store_entry(), otherwise > allocate the needed nodes and set the MA_STATE_PREALLOC flag. The way I'd like to see this working is to preallocate nodes prior to writing, but also to end in a state where we can call the store operation to continue the operation. Both of these parts need to be together in a patch set if they cannot be in the same patch. Thanks, Liam > > Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> > --- > lib/maple_tree.c | 22 +++++++++++++++++++--- > 1 file changed, 19 insertions(+), 3 deletions(-) > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > index e239197a57fc..25ae66e585f4 100644 > --- a/lib/maple_tree.c > +++ b/lib/maple_tree.c > @@ -5478,17 +5478,33 @@ int mas_prealloc_calc(struct ma_wr_state *wr_mas) > int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp) > { > MA_WR_STATE(wr_mas, mas, entry); > + int request; > > mas_wr_store_setup(&wr_mas); > - trace_ma_write(__func__, mas, 0, entry); > -retry: > + wr_mas.content = mas_start(mas); > + > + request = mas_prealloc_calc(&wr_mas); > + if (!request) > + goto store_entry; > + > + mas_node_count_gfp(mas, request, gfp); > + if (unlikely(mas_is_err(mas))) { > + mas_set_alloc_req(mas, 0); > + mas_destroy(mas); > + mas_reset(mas); > + return xa_err(mas->node); > + } > + mas->mas_flags |= MA_STATE_PREALLOC; > + > +store_entry: > mas_wr_store_entry(&wr_mas); > if (unlikely(mas_nomem(mas, gfp))) > - goto retry; > + goto store_entry; > > if (unlikely(mas_is_err(mas))) > return xa_err(mas->node); > > + trace_ma_write(__func__, mas, 0, entry); > return 0; > } > EXPORT_SYMBOL_GPL(mas_store_gfp); > -- > 2.41.0 >
On 10/9/23 8:03 PM, Peng Zhang wrote: > Hi, > > 在 2023/10/10 04:16, Sidhartha Kumar 写道: >> Preallocate maple nodes before call to mas_wr_store_entry(). If a new >> node is not needed, go directly to mas_wr_store_entry(), otherwise >> allocate the needed nodes and set the MA_STATE_PREALLOC flag. >> >> Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> >> --- >> lib/maple_tree.c | 22 +++++++++++++++++++--- >> 1 file changed, 19 insertions(+), 3 deletions(-) >> >> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >> index e239197a57fc..25ae66e585f4 100644 >> --- a/lib/maple_tree.c >> +++ b/lib/maple_tree.c >> @@ -5478,17 +5478,33 @@ int mas_prealloc_calc(struct ma_wr_state *wr_mas) >> int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp) >> { >> MA_WR_STATE(wr_mas, mas, entry); >> + int request; >> mas_wr_store_setup(&wr_mas); >> - trace_ma_write(__func__, mas, 0, entry); >> -retry: >> + wr_mas.content = mas_start(mas); >> + >> + request = mas_prealloc_calc(&wr_mas); > mas_wr_store_entry() does something similar to mas_prealloc_calc(). > Now, making it do it twice would incur additional overhead. > We encountered this issue while optimizing preallocation, but it > hasn't been resolved yet. Previously, this problem only occurred > when using mas_preallocate(). Now, this change would bring this > impact to all write operations on maple tree. What do you think > about it? > After talking to Liam, I will have to implement the store type enum feature on the Maple Tree Work list so that mas_prealloc_calc() can start a partial walk and write that information to the enum. mas_wr_store_entry() can then read that enum to continue the walk that was already started rather than having to redo the whole walk. This could also be used in mas_preallocate(). Do you have any suggestions for the implementation of this enum? Thanks, Sid > Thanks, > Peng >> + if (!request) >> + goto store_entry; >> + >> + mas_node_count_gfp(mas, request, gfp); >> + if (unlikely(mas_is_err(mas))) { >> + mas_set_alloc_req(mas, 0); >> + mas_destroy(mas); >> + mas_reset(mas); >> + return xa_err(mas->node); >> + } >> + mas->mas_flags |= MA_STATE_PREALLOC; >> + >> +store_entry: >> mas_wr_store_entry(&wr_mas); >> if (unlikely(mas_nomem(mas, gfp))) >> - goto retry; >> + goto store_entry; >> if (unlikely(mas_is_err(mas))) >> return xa_err(mas->node); >> + trace_ma_write(__func__, mas, 0, entry); >> return 0; >> } >> EXPORT_SYMBOL_GPL(mas_store_gfp); >
在 2023/10/11 08:17, Sidhartha Kumar 写道: > On 10/9/23 8:03 PM, Peng Zhang wrote: >> Hi, >> >> 在 2023/10/10 04:16, Sidhartha Kumar 写道: >>> Preallocate maple nodes before call to mas_wr_store_entry(). If a new >>> node is not needed, go directly to mas_wr_store_entry(), otherwise >>> allocate the needed nodes and set the MA_STATE_PREALLOC flag. >>> >>> Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> >>> --- >>> lib/maple_tree.c | 22 +++++++++++++++++++--- >>> 1 file changed, 19 insertions(+), 3 deletions(-) >>> >>> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >>> index e239197a57fc..25ae66e585f4 100644 >>> --- a/lib/maple_tree.c >>> +++ b/lib/maple_tree.c >>> @@ -5478,17 +5478,33 @@ int mas_prealloc_calc(struct ma_wr_state *wr_mas) >>> int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp) >>> { >>> MA_WR_STATE(wr_mas, mas, entry); >>> + int request; >>> mas_wr_store_setup(&wr_mas); >>> - trace_ma_write(__func__, mas, 0, entry); >>> -retry: >>> + wr_mas.content = mas_start(mas); >>> + >>> + request = mas_prealloc_calc(&wr_mas); >> mas_wr_store_entry() does something similar to mas_prealloc_calc(). >> Now, making it do it twice would incur additional overhead. >> We encountered this issue while optimizing preallocation, but it >> hasn't been resolved yet. Previously, this problem only occurred >> when using mas_preallocate(). Now, this change would bring this >> impact to all write operations on maple tree. What do you think >> about it? >> > > After talking to Liam, I will have to implement the store type enum feature on the Maple Tree Work list so that mas_prealloc_calc() can start a partial walk and write that information to the enum. mas_wr_store_entry() can then read that enum to continue the walk that was already started rather than having to redo the whole walk. This could also be used in mas_preallocate(). Do you have any suggestions for the implementation of this enum? There is another scenario where this enum can be useful, as seen in the implementation of mas_replace_entry() in [1]. It is a faster alternative to mas_store(), but it is not safe. If we can determine through the enum while writing the maple tree that a faster write operation can be performed, it would be beneficial. Some performance improvements can also be observed in [1]. [1] https://lore.kernel.org/lkml/49f0181a-55a4-41aa-8596-877560c8b802@bytedance.com/ > > Thanks, > Sid > >> Thanks, >> Peng >>> + if (!request) >>> + goto store_entry; >>> + >>> + mas_node_count_gfp(mas, request, gfp); >>> + if (unlikely(mas_is_err(mas))) { >>> + mas_set_alloc_req(mas, 0); >>> + mas_destroy(mas); >>> + mas_reset(mas); >>> + return xa_err(mas->node); >>> + } >>> + mas->mas_flags |= MA_STATE_PREALLOC; >>> + >>> +store_entry: >>> mas_wr_store_entry(&wr_mas); >>> if (unlikely(mas_nomem(mas, gfp))) >>> - goto retry; >>> + goto store_entry; >>> if (unlikely(mas_is_err(mas))) >>> return xa_err(mas->node); >>> + trace_ma_write(__func__, mas, 0, entry); >>> return 0; >>> } >>> EXPORT_SYMBOL_GPL(mas_store_gfp); >> > >
Hello, kernel test robot noticed "BUG:sleeping_function_called_from_invalid_context_at_include/linux/sched/mm.h" on: commit: 9116baa49536116f013d691d2178c520959f46c2 ("[PATCH 2/3] maple_tree: use preallocations in mas_store_gfp()") url: https://github.com/intel-lab-lkp/linux/commits/Sidhartha-Kumar/maple_tree-introduce-mas_prealloc_calc/20231010-041859 base: https://git.kernel.org/cgit/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/all/20231009201639.920512-3-sidhartha.kumar@oracle.com/ patch subject: [PATCH 2/3] maple_tree: use preallocations in mas_store_gfp() in testcase: boot compiler: gcc-11 test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G (please refer to attached dmesg/kmsg for entire log/backtrace) +------------------------------------------------------------------------------------+------------+------------+ | | 9cbebad6db | 9116baa495 | +------------------------------------------------------------------------------------+------------+------------+ | BUG:sleeping_function_called_from_invalid_context_at_include/linux/sched/mm.h | 0 | 7 | | WARNING:suspicious_RCU_usage | 0 | 7 | | include/linux/rcupdate.h:#Illegal_context_switch_in_RCU_read-side_critical_section | 0 | 7 | +------------------------------------------------------------------------------------+------------+------------+ If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <oliver.sang@intel.com> | Closes: https://lore.kernel.org/oe-lkp/202310251706.6e6f6c4a-oliver.sang@intel.com [ 12.322393][ T1] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:306 [ 12.324008][ T1] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper [ 12.325486][ T1] preempt_count: 1, expected: 0 [ 12.326345][ T1] 1 lock held by swapper/1: [ 12.327164][ T1] #0: c2b52570 (&mt->ma_lock){+.+.}-{2:2}, at: check_root_expand+0x46/0xac0 [ 12.328850][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G T 6.6.0-rc4-00400-g9116baa49536 #1 [ 12.329034][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 12.329034][ T1] Call Trace: [ 12.329034][ T1] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) [ 12.329034][ T1] dump_stack (lib/dump_stack.c:114) [ 12.329034][ T1] __might_resched (kernel/sched/core.c:10188) [ 12.329034][ T1] __might_sleep (kernel/sched/core.c:10117 (discriminator 17)) [ 12.329034][ T1] kmem_cache_alloc (include/linux/sched/mm.h:306 mm/slab.h:705 mm/slub.c:3460 mm/slub.c:3486 mm/slub.c:3493 mm/slub.c:3502) [ 12.329034][ T1] ? mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 12.329034][ T1] mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 12.329034][ T1] mas_node_count_gfp (lib/maple_tree.c:1347) [ 12.329034][ T1] mas_store_gfp (lib/maple_tree.c:256 lib/maple_tree.c:5491) [ 12.329034][ T1] ? check_empty_area_fill+0x3d0/0x3d0 [ 12.329034][ T1] check_root_expand+0x162/0xac0 [ 12.329034][ T1] maple_tree_seed (lib/test_maple_tree.c:3577) [ 12.329034][ T1] ? check_gap_combining+0xdf8/0xdf8 [ 12.329034][ T1] do_one_initcall (init/main.c:1232) [ 12.329034][ T1] do_initcalls (init/main.c:1293 init/main.c:1310) [ 12.329034][ T1] kernel_init_freeable (init/main.c:1551) [ 12.329034][ T1] ? rest_init (init/main.c:1429) [ 12.329034][ T1] kernel_init (init/main.c:1439) [ 12.329034][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 12.329034][ T1] ? rest_init (init/main.c:1429) [ 12.329034][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 12.329034][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:944) [ 12.353802][ T1] [ 12.354345][ T1] ============================= [ 12.355188][ T1] WARNING: suspicious RCU usage [ 12.356056][ T1] 6.6.0-rc4-00400-g9116baa49536 #1 Tainted: G W T [ 12.357413][ T1] ----------------------------- [ 12.358272][ T1] include/linux/rcupdate.h:375 Illegal context switch in RCU read-side critical section! [ 12.359905][ T1] [ 12.359905][ T1] other info that might help us debug this: [ 12.359905][ T1] [ 12.361711][ T1] [ 12.361711][ T1] rcu_scheduler_active = 2, debug_locks = 1 [ 12.363058][ T1] 2 locks held by swapper/1: [ 12.363877][ T1] #0: c2ad5938 (rcu_read_lock){....}-{1:2}, at: check_mas_store_gfp+0xa9/0x1b0 [ 12.365646][ T1] #1: c3965e84 (&mt->ma_lock){+.+.}-{2:2}, at: check_mas_store_gfp+0x104/0x1b0 [ 12.367338][ T1] [ 12.367338][ T1] stack backtrace: [ 12.368430][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G W T 6.6.0-rc4-00400-g9116baa49536 #1 [ 12.369129][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 12.369129][ T1] Call Trace: [ 12.369129][ T1] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) [ 12.369129][ T1] dump_stack (lib/dump_stack.c:114) [ 12.369129][ T1] lockdep_rcu_suspicious (kernel/locking/lockdep.c:6713) [ 12.369129][ T1] __might_resched (include/linux/rcupdate.h:375 kernel/sched/core.c:10149) [ 12.369129][ T1] __might_sleep (kernel/sched/core.c:10117 (discriminator 17)) [ 12.369129][ T1] kmem_cache_alloc (include/linux/sched/mm.h:306 mm/slab.h:705 mm/slub.c:3460 mm/slub.c:3486 mm/slub.c:3493 mm/slub.c:3502) [ 12.369129][ T1] ? mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 12.369129][ T1] mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 12.369129][ T1] mas_node_count_gfp (lib/maple_tree.c:1347) [ 12.369129][ T1] mas_store_gfp (lib/maple_tree.c:256 lib/maple_tree.c:5491) [ 12.369129][ T1] check_mas_store_gfp+0x14b/0x1b0 [ 12.369129][ T1] maple_tree_seed (lib/test_maple_tree.c:3646) [ 12.369129][ T1] ? check_gap_combining+0xdf8/0xdf8 [ 12.369129][ T1] do_one_initcall (init/main.c:1232) [ 12.369129][ T1] do_initcalls (init/main.c:1293 init/main.c:1310) [ 12.369129][ T1] kernel_init_freeable (init/main.c:1551) [ 12.369129][ T1] ? rest_init (init/main.c:1429) [ 12.369129][ T1] kernel_init (init/main.c:1439) [ 12.369129][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 12.369129][ T1] ? rest_init (init/main.c:1429) [ 12.369129][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 12.369129][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:944) [ 15.220029][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 16.033920][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 17.655206][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 19.245918][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 36.522020][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 37.994914][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 38.766533][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 41.775652][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 43.236341][ T35] torture_spin_lock_write_delay: delay = 24 jiffies. [ 44.106914][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 46.776934][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 47.165604][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 49.209209][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 50.316931][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 51.511048][ T34] torture_spin_lock_write_delay: delay = 25 jiffies. [ 54.564928][ T35] torture_spin_lock_write_delay: delay = 25 jiffies. [ 59.372367][ T1] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:306 [ 59.374045][ T1] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper [ 59.375483][ T1] preempt_count: 1, expected: 0 [ 59.376310][ T1] 1 lock held by swapper/1: [ 59.377090][ T1] #0: c2b52570 (&mt->ma_lock){+.+.}-{2:2}, at: check_empty_area_fill+0xe5/0x3d0 [ 59.378744][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G W T 6.6.0-rc4-00400-g9116baa49536 #1 [ 59.380409][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 59.381080][ T1] Call Trace: [ 59.381080][ T1] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) [ 59.381080][ T1] dump_stack (lib/dump_stack.c:114) [ 59.381080][ T1] __might_resched (kernel/sched/core.c:10188) [ 59.381080][ T1] __might_sleep (kernel/sched/core.c:10117 (discriminator 17)) [ 59.381080][ T1] kmem_cache_alloc (include/linux/sched/mm.h:306 mm/slab.h:705 mm/slub.c:3460 mm/slub.c:3486 mm/slub.c:3493 mm/slub.c:3502) [ 59.381080][ T1] ? mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 59.381080][ T1] mas_alloc_nodes (lib/maple_tree.c:160 lib/maple_tree.c:1265) [ 59.381080][ T1] mas_node_count_gfp (lib/maple_tree.c:1347) [ 59.381080][ T1] mas_store_gfp (lib/maple_tree.c:256 lib/maple_tree.c:5491) [ 59.381080][ T1] check_empty_area_fill+0xab/0x3d0 [ 59.381080][ T1] maple_tree_seed (lib/test_maple_tree.c:3837) [ 59.381080][ T1] ? check_gap_combining+0xdf8/0xdf8 [ 59.381080][ T1] do_one_initcall (init/main.c:1232) [ 59.381080][ T1] do_initcalls (init/main.c:1293 init/main.c:1310) [ 59.381080][ T1] kernel_init_freeable (init/main.c:1551) [ 59.381080][ T1] ? rest_init (init/main.c:1429) [ 59.381080][ T1] kernel_init (init/main.c:1439) [ 59.381080][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 59.381080][ T1] ? rest_init (init/main.c:1429) [ 59.381080][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 59.381080][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:944) [ 59.571154][ T1] maple_tree: 3807933 of 3807933 tests passed [ 59.572831][ T1] test_memcat_p: test passed [ 59.590510][ T1] test_meminit: all 11 tests in test_pages passed [ 59.621976][ T1] test_meminit: all 40 tests in test_kvmalloc passed [ 60.207905][ T1] test_meminit: all 70 tests in test_kmemcache passed [ 60.217750][ T1] test_meminit: all 10 tests in test_rcu_persistent passed [ 60.219088][ T1] test_meminit: all 131 tests passed! [ 60.220126][ T1] ref_tracker: reference already released. [ 60.220912][ T1] ref_tracker: allocated in: The kernel config and materials to reproduce are available at: https://download.01.org/0day-ci/archive/20231025/202310251706.6e6f6c4a-oliver.sang@intel.com
... Dropping direct Cc's in attempt to avoid even more noise. * kernel test robot <oliver.sang@intel.com> [231025 05:52]: > > > Hello, > > kernel test robot noticed "BUG:sleeping_function_called_from_invalid_context_at_include/linux/sched/mm.h" on: ... This patch set is being revised and discussed on how to make it a more complete solution. In the mean time, is there any way to stop the bot from emailing everyone and burning more power? Thank you, Liam
diff --git a/lib/maple_tree.c b/lib/maple_tree.c index e239197a57fc..25ae66e585f4 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -5478,17 +5478,33 @@ int mas_prealloc_calc(struct ma_wr_state *wr_mas) int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp) { MA_WR_STATE(wr_mas, mas, entry); + int request; mas_wr_store_setup(&wr_mas); - trace_ma_write(__func__, mas, 0, entry); -retry: + wr_mas.content = mas_start(mas); + + request = mas_prealloc_calc(&wr_mas); + if (!request) + goto store_entry; + + mas_node_count_gfp(mas, request, gfp); + if (unlikely(mas_is_err(mas))) { + mas_set_alloc_req(mas, 0); + mas_destroy(mas); + mas_reset(mas); + return xa_err(mas->node); + } + mas->mas_flags |= MA_STATE_PREALLOC; + +store_entry: mas_wr_store_entry(&wr_mas); if (unlikely(mas_nomem(mas, gfp))) - goto retry; + goto store_entry; if (unlikely(mas_is_err(mas))) return xa_err(mas->node); + trace_ma_write(__func__, mas, 0, entry); return 0; } EXPORT_SYMBOL_GPL(mas_store_gfp);
Preallocate maple nodes before call to mas_wr_store_entry(). If a new node is not needed, go directly to mas_wr_store_entry(), otherwise allocate the needed nodes and set the MA_STATE_PREALLOC flag. Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> --- lib/maple_tree.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)