radix-tree: must check __radix_tree_preload() return value
__radix_tree_preload() only disables preemption if no error is returned. So we really need to make sure callers always check the return value. idr_preload() contract is to always disable preemption, so we need to add a missing preempt_disable() if an error happened. Similarly, ida_pre_get() only needs to call preempt_enable() in the case no error happened. Link: http://lkml.kernel.org/r/1504637190.15310.62.camel@edumazet-glaptop3.roam.corp.google.com Fixes:0a835c4f09
("Reimplement IDR and IDA using the radix tree") Fixes:7ad3d4d85c
("ida: Move ida_bitmap to a percpu variable") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Matthew Wilcox <mawilcox@microsoft.com> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: <stable@vger.kernel.org> [4.11+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
7c61bd6983
Коммит
bc9ae2247a
|
@ -463,7 +463,7 @@ radix_tree_node_free(struct radix_tree_node *node)
|
||||||
* To make use of this facility, the radix tree must be initialised without
|
* To make use of this facility, the radix tree must be initialised without
|
||||||
* __GFP_DIRECT_RECLAIM being passed to INIT_RADIX_TREE().
|
* __GFP_DIRECT_RECLAIM being passed to INIT_RADIX_TREE().
|
||||||
*/
|
*/
|
||||||
static int __radix_tree_preload(gfp_t gfp_mask, unsigned nr)
|
static __must_check int __radix_tree_preload(gfp_t gfp_mask, unsigned nr)
|
||||||
{
|
{
|
||||||
struct radix_tree_preload *rtp;
|
struct radix_tree_preload *rtp;
|
||||||
struct radix_tree_node *node;
|
struct radix_tree_node *node;
|
||||||
|
@ -2104,7 +2104,8 @@ EXPORT_SYMBOL(radix_tree_tagged);
|
||||||
*/
|
*/
|
||||||
void idr_preload(gfp_t gfp_mask)
|
void idr_preload(gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
__radix_tree_preload(gfp_mask, IDR_PRELOAD_SIZE);
|
if (__radix_tree_preload(gfp_mask, IDR_PRELOAD_SIZE))
|
||||||
|
preempt_disable();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(idr_preload);
|
EXPORT_SYMBOL(idr_preload);
|
||||||
|
|
||||||
|
@ -2118,12 +2119,12 @@ EXPORT_SYMBOL(idr_preload);
|
||||||
*/
|
*/
|
||||||
int ida_pre_get(struct ida *ida, gfp_t gfp)
|
int ida_pre_get(struct ida *ida, gfp_t gfp)
|
||||||
{
|
{
|
||||||
__radix_tree_preload(gfp, IDA_PRELOAD_SIZE);
|
|
||||||
/*
|
/*
|
||||||
* The IDA API has no preload_end() equivalent. Instead,
|
* The IDA API has no preload_end() equivalent. Instead,
|
||||||
* ida_get_new() can return -EAGAIN, prompting the caller
|
* ida_get_new() can return -EAGAIN, prompting the caller
|
||||||
* to return to the ida_pre_get() step.
|
* to return to the ida_pre_get() step.
|
||||||
*/
|
*/
|
||||||
|
if (!__radix_tree_preload(gfp, IDA_PRELOAD_SIZE))
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
if (!this_cpu_read(ida_bitmap)) {
|
if (!this_cpu_read(ida_bitmap)) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче