GFP_NOIO is often used for idr_alloc() inside preloaded section as the allocation mask doesn't really matter. If the idr tree needs to be expanded, idr_alloc() first tries to allocate using the specified allocation mask and if it fails falls back to the preloaded buffer. This order prevent non-preloading idr_alloc() users from taking advantage of preloading ones by using preload buffer without filling it shifting the burden of allocation to the preload users. Unfortunately, this allowed/expected-to-fail kmem_cache allocation ends up generating spurious slab lowmem warning before succeeding the request from the preload buffer. This patch makes idr_layer_alloc() add __GFP_NOWARN to the first kmem_cache attempt and try kmem_cache again w/o __GFP_NOWARN after allocation from preload_buffer fails so that lowmem warning is generated if not suppressed by the original @gfp_mask.
Unified · Split
| @@ -106,8 +106,14 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr) · 105 unmodified lines | ||
| 106 | 106 | if (layer_idr) |
| 107 | 107 | return get_from_free_list(layer_idr); |
| 108 | 108 | |
| 109 | − /* try to allocate directly from kmem_cache */ | |
| 110 | − new = kmem_cache_zalloc(idr_layer_cache, gfp_mask); | |
| 109 | + /* | |
| 110 | + * Try to allocate directly from kmem_cache. We want to try this | |
| 111 | + * before preload buffer; otherwise, non-preloading idr_alloc() | |
| 112 | + * users will end up taking advantage of preloading ones. As the | |
| 113 | + * following is allowed to fail for preloaded cases, suppress | |
| 114 | + * warning this time. | |
| 115 | + */ | |
| 116 | + new = kmem_cache_zalloc(idr_layer_cache, gfp_mask | __GFP_NOWARN); | |
| 111 | 117 | if (new) |
| 112 | 118 | return new; |
| 113 | 119 | |
| @@ -115,18 +121,24 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr) · 1 unmodified line | ||
| 115 | 121 | * Try to fetch one from the per-cpu preload buffer if in process |
| 116 | 122 | * context. See idr_preload() for details. |
| 117 | 123 | */ |
| 118 | − if (in_interrupt()) | |
| 119 | − return NULL; | |
| 120 | − | |
| 121 | − preempt_disable(); | |
| 122 | − new = __this_cpu_read(idr_preload_head); | |
| 123 | − if (new) { | |
| 124 | − __this_cpu_write(idr_preload_head, new->ary[0]); | |
| 125 | − __this_cpu_dec(idr_preload_cnt); | |
| 126 | − new->ary[0] = NULL; | |
| 124 | + if (!in_interrupt()) { | |
| 125 | + preempt_disable(); | |
| 126 | + new = __this_cpu_read(idr_preload_head); | |
| 127 | + if (new) { | |
| 128 | + __this_cpu_write(idr_preload_head, new->ary[0]); | |
| 129 | + __this_cpu_dec(idr_preload_cnt); | |
| 130 | + new->ary[0] = NULL; | |
| 131 | + } | |
| 132 | + preempt_enable(); | |
| 133 | + if (new) | |
| 134 | + return new; | |
| 127 | 135 | } |
| 128 | − preempt_enable(); | |
| 129 | − return new; | |
| 136 | + | |
| 137 | + /* | |
| 138 | + * Both failed. Try kmem_cache again w/o adding __GFP_NOWARN so | |
| 139 | + * that memory allocation failure warning is printed as intended. | |
| 140 | + */ | |
| 141 | + return kmem_cache_zalloc(idr_layer_cache, gfp_mask); | |
| 130 | 142 | } |
| 131 | 143 | |
| 132 | 144 | static void idr_layer_rcu_free(struct rcu_head *head) |