aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMatthew Wilcox <mawilcox@microsoft.com>2016-12-17 08:18:17 -0500
committerMatthew Wilcox <mawilcox@microsoft.com>2017-02-13 21:44:02 -0500
commitd37cacc5adace7f3e0824e1f559192ad7299d029 (patch)
tree9932ecc9ba3010ecc53bdbf5cd299eb0842106ec /tools
parent7ad3d4d85c7af9632055a6ac0aa15b6b6a321c6b (diff)
ida: Use exceptional entries for small IDAs
We can use the root entry as a bitmap and save allocating a 128 byte bitmap for an IDA that contains only a few entries (30 on a 32-bit machine, 62 on a 64-bit machine). This costs about 300 bytes of kernel text on x86-64, so as long as 3 IDAs fall into this category, this is a net win for memory consumption. Thanks to Rasmus Villemoes for his work documenting the problem and collecting statistics on IDAs. Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/radix-tree/idr-test.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c
index 4dffad9284e0..59081122c63d 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -11,6 +11,7 @@
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details. 12 * more details.
13 */ 13 */
14#include <linux/bitmap.h>
14#include <linux/idr.h> 15#include <linux/idr.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
@@ -214,7 +215,7 @@ void ida_check_nomem(void)
214 DEFINE_IDA(ida); 215 DEFINE_IDA(ida);
215 int id, err; 216 int id, err;
216 217
217 err = ida_get_new(&ida, &id); 218 err = ida_get_new_above(&ida, 256, &id);
218 assert(err == -EAGAIN); 219 assert(err == -EAGAIN);
219 err = ida_get_new_above(&ida, 1UL << 30, &id); 220 err = ida_get_new_above(&ida, 1UL << 30, &id);
220 assert(err == -EAGAIN); 221 assert(err == -EAGAIN);
@@ -247,6 +248,66 @@ void ida_check_leaf(void)
247} 248}
248 249
249/* 250/*
251 * Check handling of conversions between exceptional entries and full bitmaps.
252 */
253void ida_check_conv(void)
254{
255 DEFINE_IDA(ida);
256 int id;
257 unsigned long i;
258
259 for (i = 0; i < IDA_BITMAP_BITS * 2; i += IDA_BITMAP_BITS) {
260 assert(ida_pre_get(&ida, GFP_KERNEL));
261 assert(!ida_get_new_above(&ida, i + 1, &id));
262 assert(id == i + 1);
263 assert(!ida_get_new_above(&ida, i + BITS_PER_LONG, &id));
264 assert(id == i + BITS_PER_LONG);
265 ida_remove(&ida, i + 1);
266 ida_remove(&ida, i + BITS_PER_LONG);
267 assert(ida_is_empty(&ida));
268 }
269
270 assert(ida_pre_get(&ida, GFP_KERNEL));
271
272 for (i = 0; i < IDA_BITMAP_BITS * 2; i++) {
273 assert(ida_pre_get(&ida, GFP_KERNEL));
274 assert(!ida_get_new(&ida, &id));
275 assert(id == i);
276 }
277
278 for (i = IDA_BITMAP_BITS * 2; i > 0; i--) {
279 ida_remove(&ida, i - 1);
280 }
281 assert(ida_is_empty(&ida));
282
283 for (i = 0; i < IDA_BITMAP_BITS + BITS_PER_LONG - 4; i++) {
284 assert(ida_pre_get(&ida, GFP_KERNEL));
285 assert(!ida_get_new(&ida, &id));
286 assert(id == i);
287 }
288
289 for (i = IDA_BITMAP_BITS + BITS_PER_LONG - 4; i > 0; i--) {
290 ida_remove(&ida, i - 1);
291 }
292 assert(ida_is_empty(&ida));
293
294 radix_tree_cpu_dead(1);
295 for (i = 0; i < 1000000; i++) {
296 int err = ida_get_new(&ida, &id);
297 if (err == -EAGAIN) {
298 assert((i % IDA_BITMAP_BITS) == (BITS_PER_LONG - 2));
299 assert(ida_pre_get(&ida, GFP_KERNEL));
300 err = ida_get_new(&ida, &id);
301 } else {
302 assert((i % IDA_BITMAP_BITS) != (BITS_PER_LONG - 2));
303 }
304 assert(!err);
305 assert(id == i);
306 }
307 ida_destroy(&ida);
308}
309
310/*
250 * Check allocations up to and slightly above the maximum allowed (2^31-1) ID. 311 * Check allocations up to and slightly above the maximum allowed (2^31-1) ID.
251 * Allocating up to 2^31-1 should succeed, and then allocating the next one 312 * Allocating up to 2^31-1 should succeed, and then allocating the next one
252 * should fail. 313 * should fail.
@@ -273,6 +334,34 @@ void ida_check_max(void)
273 } 334 }
274} 335}
275 336
337void ida_check_random(void)
338{
339 DEFINE_IDA(ida);
340 DECLARE_BITMAP(bitmap, 2048);
341 int id;
342 unsigned int i;
343 time_t s = time(NULL);
344
345 repeat:
346 memset(bitmap, 0, sizeof(bitmap));
347 for (i = 0; i < 100000; i++) {
348 int i = rand();
349 int bit = i & 2047;
350 if (test_bit(bit, bitmap)) {
351 __clear_bit(bit, bitmap);
352 ida_remove(&ida, bit);
353 } else {
354 __set_bit(bit, bitmap);
355 ida_pre_get(&ida, GFP_KERNEL);
356 assert(!ida_get_new_above(&ida, bit, &id));
357 assert(id == bit);
358 }
359 }
360 ida_destroy(&ida);
361 if (time(NULL) < s + 10)
362 goto repeat;
363}
364
276void ida_checks(void) 365void ida_checks(void)
277{ 366{
278 DEFINE_IDA(ida); 367 DEFINE_IDA(ida);
@@ -337,6 +426,8 @@ void ida_checks(void)
337 426
338 ida_check_leaf(); 427 ida_check_leaf();
339 ida_check_max(); 428 ida_check_max();
429 ida_check_conv();
430 ida_check_random();
340 431
341 radix_tree_cpu_dead(1); 432 radix_tree_cpu_dead(1);
342} 433}