diff options
| author | Matthew Wilcox <mawilcox@microsoft.com> | 2016-12-17 08:18:17 -0500 |
|---|---|---|
| committer | Matthew Wilcox <mawilcox@microsoft.com> | 2017-02-13 21:44:02 -0500 |
| commit | d37cacc5adace7f3e0824e1f559192ad7299d029 (patch) | |
| tree | 9932ecc9ba3010ecc53bdbf5cd299eb0842106ec /tools/testing | |
| parent | 7ad3d4d85c7af9632055a6ac0aa15b6b6a321c6b (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/testing')
| -rw-r--r-- | tools/testing/radix-tree/idr-test.c | 93 |
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 | */ | ||
| 253 | void 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 | ||
| 337 | void 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 | |||
| 276 | void ida_checks(void) | 365 | void 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 | } |
