@@ -499,7 +499,7 @@ static slab_flags_t slub_debug = DEBUG_DEFAULT_FLAGS;
499
499
static slab_flags_t slub_debug ;
500
500
#endif
501
501
502
- static char * slub_debug_slabs ;
502
+ static char * slub_debug_string ;
503
503
static int disable_higher_order_debug ;
504
504
505
505
/*
@@ -1262,68 +1262,132 @@ static noinline int free_debug_processing(
1262
1262
return ret ;
1263
1263
}
1264
1264
1265
- static int __init setup_slub_debug (char * str )
1265
+ /*
1266
+ * Parse a block of slub_debug options. Blocks are delimited by ';'
1267
+ *
1268
+ * @str: start of block
1269
+ * @flags: returns parsed flags, or DEBUG_DEFAULT_FLAGS if none specified
1270
+ * @slabs: return start of list of slabs, or NULL when there's no list
1271
+ * @init: assume this is initial parsing and not per-kmem-create parsing
1272
+ *
1273
+ * returns the start of next block if there's any, or NULL
1274
+ */
1275
+ static char *
1276
+ parse_slub_debug_flags (char * str , slab_flags_t * flags , char * * slabs , bool init )
1266
1277
{
1267
- slub_debug = DEBUG_DEFAULT_FLAGS ;
1268
- if (* str ++ != '=' || !* str )
1269
- /*
1270
- * No options specified. Switch on full debugging.
1271
- */
1272
- goto out ;
1278
+ bool higher_order_disable = false;
1273
1279
1274
- if (* str == ',' )
1280
+ /* Skip any completely empty blocks */
1281
+ while (* str && * str == ';' )
1282
+ str ++ ;
1283
+
1284
+ if (* str == ',' ) {
1275
1285
/*
1276
1286
* No options but restriction on slabs. This means full
1277
1287
* debugging for slabs matching a pattern.
1278
1288
*/
1289
+ * flags = DEBUG_DEFAULT_FLAGS ;
1279
1290
goto check_slabs ;
1291
+ }
1292
+ * flags = 0 ;
1280
1293
1281
- slub_debug = 0 ;
1282
- if (* str == '-' )
1283
- /*
1284
- * Switch off all debugging measures.
1285
- */
1286
- goto out ;
1287
-
1288
- /*
1289
- * Determine which debug features should be switched on
1290
- */
1291
- for (; * str && * str != ',' ; str ++ ) {
1294
+ /* Determine which debug features should be switched on */
1295
+ for (; * str && * str != ',' && * str != ';' ; str ++ ) {
1292
1296
switch (tolower (* str )) {
1297
+ case '-' :
1298
+ * flags = 0 ;
1299
+ break ;
1293
1300
case 'f' :
1294
- slub_debug |= SLAB_CONSISTENCY_CHECKS ;
1301
+ * flags |= SLAB_CONSISTENCY_CHECKS ;
1295
1302
break ;
1296
1303
case 'z' :
1297
- slub_debug |= SLAB_RED_ZONE ;
1304
+ * flags |= SLAB_RED_ZONE ;
1298
1305
break ;
1299
1306
case 'p' :
1300
- slub_debug |= SLAB_POISON ;
1307
+ * flags |= SLAB_POISON ;
1301
1308
break ;
1302
1309
case 'u' :
1303
- slub_debug |= SLAB_STORE_USER ;
1310
+ * flags |= SLAB_STORE_USER ;
1304
1311
break ;
1305
1312
case 't' :
1306
- slub_debug |= SLAB_TRACE ;
1313
+ * flags |= SLAB_TRACE ;
1307
1314
break ;
1308
1315
case 'a' :
1309
- slub_debug |= SLAB_FAILSLAB ;
1316
+ * flags |= SLAB_FAILSLAB ;
1310
1317
break ;
1311
1318
case 'o' :
1312
1319
/*
1313
1320
* Avoid enabling debugging on caches if its minimum
1314
1321
* order would increase as a result.
1315
1322
*/
1316
- disable_higher_order_debug = 1 ;
1323
+ higher_order_disable = true ;
1317
1324
break ;
1318
1325
default :
1319
- pr_err ( "slub_debug option '%c' unknown. skipped\n" ,
1320
- * str );
1326
+ if ( init )
1327
+ pr_err ( "slub_debug option '%c' unknown. skipped\n" , * str );
1321
1328
}
1322
1329
}
1323
-
1324
1330
check_slabs :
1325
1331
if (* str == ',' )
1326
- slub_debug_slabs = str + 1 ;
1332
+ * slabs = ++ str ;
1333
+ else
1334
+ * slabs = NULL ;
1335
+
1336
+ /* Skip over the slab list */
1337
+ while (* str && * str != ';' )
1338
+ str ++ ;
1339
+
1340
+ /* Skip any completely empty blocks */
1341
+ while (* str && * str == ';' )
1342
+ str ++ ;
1343
+
1344
+ if (init && higher_order_disable )
1345
+ disable_higher_order_debug = 1 ;
1346
+
1347
+ if (* str )
1348
+ return str ;
1349
+ else
1350
+ return NULL ;
1351
+ }
1352
+
1353
+ static int __init setup_slub_debug (char * str )
1354
+ {
1355
+ slab_flags_t flags ;
1356
+ char * saved_str ;
1357
+ char * slab_list ;
1358
+ bool global_slub_debug_changed = false;
1359
+ bool slab_list_specified = false;
1360
+
1361
+ slub_debug = DEBUG_DEFAULT_FLAGS ;
1362
+ if (* str ++ != '=' || !* str )
1363
+ /*
1364
+ * No options specified. Switch on full debugging.
1365
+ */
1366
+ goto out ;
1367
+
1368
+ saved_str = str ;
1369
+ while (str ) {
1370
+ str = parse_slub_debug_flags (str , & flags , & slab_list , true);
1371
+
1372
+ if (!slab_list ) {
1373
+ slub_debug = flags ;
1374
+ global_slub_debug_changed = true;
1375
+ } else {
1376
+ slab_list_specified = true;
1377
+ }
1378
+ }
1379
+
1380
+ /*
1381
+ * For backwards compatibility, a single list of flags with list of
1382
+ * slabs means debugging is only enabled for those slabs, so the global
1383
+ * slub_debug should be 0. We can extended that to multiple lists as
1384
+ * long as there is no option specifying flags without a slab list.
1385
+ */
1386
+ if (slab_list_specified ) {
1387
+ if (!global_slub_debug_changed )
1388
+ slub_debug = 0 ;
1389
+ slub_debug_string = saved_str ;
1390
+ }
1327
1391
out :
1328
1392
if ((static_branch_unlikely (& init_on_alloc ) ||
1329
1393
static_branch_unlikely (& init_on_free )) &&
@@ -1352,36 +1416,47 @@ slab_flags_t kmem_cache_flags(unsigned int object_size,
1352
1416
{
1353
1417
char * iter ;
1354
1418
size_t len ;
1419
+ char * next_block ;
1420
+ slab_flags_t block_flags ;
1355
1421
1356
1422
/* If slub_debug = 0, it folds into the if conditional. */
1357
- if (!slub_debug_slabs )
1423
+ if (!slub_debug_string )
1358
1424
return flags | slub_debug ;
1359
1425
1360
1426
len = strlen (name );
1361
- iter = slub_debug_slabs ;
1362
- while (* iter ) {
1363
- char * end , * glob ;
1364
- size_t cmplen ;
1365
-
1366
- end = strchrnul (iter , ',' );
1427
+ next_block = slub_debug_string ;
1428
+ /* Go through all blocks of debug options, see if any matches our slab's name */
1429
+ while (next_block ) {
1430
+ next_block = parse_slub_debug_flags (next_block , & block_flags , & iter , false);
1431
+ if (!iter )
1432
+ continue ;
1433
+ /* Found a block that has a slab list, search it */
1434
+ while (* iter ) {
1435
+ char * end , * glob ;
1436
+ size_t cmplen ;
1437
+
1438
+ end = strchrnul (iter , ',' );
1439
+ if (next_block && next_block < end )
1440
+ end = next_block - 1 ;
1441
+
1442
+ glob = strnchr (iter , end - iter , '*' );
1443
+ if (glob )
1444
+ cmplen = glob - iter ;
1445
+ else
1446
+ cmplen = max_t (size_t , len , (end - iter ));
1367
1447
1368
- glob = strnchr (iter , end - iter , '*' );
1369
- if (glob )
1370
- cmplen = glob - iter ;
1371
- else
1372
- cmplen = max_t (size_t , len , (end - iter ));
1448
+ if (!strncmp (name , iter , cmplen )) {
1449
+ flags |= block_flags ;
1450
+ return flags ;
1451
+ }
1373
1452
1374
- if (!strncmp ( name , iter , cmplen )) {
1375
- flags |= slub_debug ;
1376
- break ;
1453
+ if (!* end || * end == ';' )
1454
+ break ;
1455
+ iter = end + 1 ;
1377
1456
}
1378
-
1379
- if (!* end )
1380
- break ;
1381
- iter = end + 1 ;
1382
1457
}
1383
1458
1384
- return flags ;
1459
+ return slub_debug ;
1385
1460
}
1386
1461
#else /* !CONFIG_SLUB_DEBUG */
1387
1462
static inline void setup_object_debug (struct kmem_cache * s ,
0 commit comments