@@ -282,6 +282,7 @@ static struct rb_root sorted; /* place to store intermediate data */
282
282
static struct rb_root result ; /* place to store sorted data */
283
283
284
284
static LIST_HEAD (lock_keys );
285
+ static const char * output_fields ;
285
286
286
287
#define DEF_KEY_LOCK (name , header , fn_suffix , len ) \
287
288
{ #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
@@ -304,23 +305,65 @@ static int select_key(void)
304
305
for (i = 0 ; keys [i ].name ; i ++ ) {
305
306
if (!strcmp (keys [i ].name , sort_key )) {
306
307
compare = keys [i ].key ;
308
+
309
+ /* selected key should be in the output fields */
310
+ if (list_empty (& keys [i ].list ))
311
+ list_add_tail (& keys [i ].list , & lock_keys );
312
+
307
313
return 0 ;
308
314
}
309
315
}
310
316
311
317
pr_err ("Unknown compare key: %s\n" , sort_key );
312
-
313
318
return -1 ;
314
319
}
315
320
316
- static int setup_output_field ( void )
321
+ static int add_output_field ( struct list_head * head , char * name )
317
322
{
318
323
int i ;
319
324
325
+ for (i = 0 ; keys [i ].name ; i ++ ) {
326
+ if (strcmp (keys [i ].name , name ))
327
+ continue ;
328
+
329
+ /* prevent double link */
330
+ if (list_empty (& keys [i ].list ))
331
+ list_add_tail (& keys [i ].list , head );
332
+
333
+ return 0 ;
334
+ }
335
+
336
+ pr_err ("Unknown output field: %s\n" , name );
337
+ return -1 ;
338
+ }
339
+
340
+ static int setup_output_field (const char * str )
341
+ {
342
+ char * tok , * tmp , * orig ;
343
+ int i , ret = 0 ;
344
+
345
+ /* no output field given: use all of them */
346
+ if (str == NULL ) {
347
+ for (i = 0 ; keys [i ].name ; i ++ )
348
+ list_add_tail (& keys [i ].list , & lock_keys );
349
+ return 0 ;
350
+ }
351
+
320
352
for (i = 0 ; keys [i ].name ; i ++ )
321
- list_add_tail (& keys [i ].list , & lock_keys );
353
+ INIT_LIST_HEAD (& keys [i ].list );
322
354
323
- return 0 ;
355
+ orig = tmp = strdup (str );
356
+ if (orig == NULL )
357
+ return - ENOMEM ;
358
+
359
+ while ((tok = strsep (& tmp , "," )) != NULL ){
360
+ ret = add_output_field (& lock_keys , tok );
361
+ if (ret < 0 )
362
+ break ;
363
+ }
364
+ free (orig );
365
+
366
+ return ret ;
324
367
}
325
368
326
369
static void combine_lock_stats (struct lock_stat * st )
@@ -1002,7 +1045,7 @@ static int __cmd_report(bool display_info)
1002
1045
goto out_delete ;
1003
1046
}
1004
1047
1005
- if (setup_output_field ())
1048
+ if (setup_output_field (output_fields ))
1006
1049
goto out_delete ;
1007
1050
1008
1051
if (select_key ())
@@ -1090,6 +1133,8 @@ int cmd_lock(int argc, const char **argv)
1090
1133
const struct option report_options [] = {
1091
1134
OPT_STRING ('k' , "key" , & sort_key , "acquired" ,
1092
1135
"key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)" ),
1136
+ OPT_STRING ('F' , "field" , & output_fields , NULL ,
1137
+ "output fields (acquired / contended / avg_wait / wait_total / wait_max / wait_min)" ),
1093
1138
/* TODO: type */
1094
1139
OPT_BOOLEAN ('c' , "combine-locks" , & combine_locks ,
1095
1140
"combine locks in the same class" ),
0 commit comments