aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2009-03-24 05:43:30 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-24 08:09:00 -0400
commit093419971e03362a00f499960557c119982ea09f (patch)
treef355954c6282bc6ee3d67f7ae374408821a216ef /kernel
parente0dc81bec0927fa0c8aabc521793161909eef7a5 (diff)
blktrace: print human-readable act_mask
Impact: new feature, allow symbolic values in /debug/tracing/act_mask Print stringified act_mask instead of hex value: # cat act_mask read,write,barrier,sync,queue,requeue,issue,complete,fs,pc,ahead,meta, discard,drv_data # echo "meta,write" > act_mask # cat act_mask write,meta Also: - make act_mask accept "ahead", "meta", "discard" and "drv_data" - use strsep() instead of strchr() to parse user input - return -EINVAL if a token is not found in the mask map - fix a bug that 'value' is unsigned, so it can < 0 - propagate error value of blk_trace_mask2str() to userspace, but not always return -ENXIO. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Acked-by: Jens Axboe <jens.axboe@oracle.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <49C8AB42.1000802@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/blktrace.c103
1 files changed, 65 insertions, 38 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index f69f8bd8bef9..6fb274f5f34e 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -1316,53 +1316,77 @@ struct attribute_group blk_trace_attr_group = {
1316 .attrs = blk_trace_attrs, 1316 .attrs = blk_trace_attrs,
1317}; 1317};
1318 1318
1319static int blk_str2act_mask(const char *str) 1319static const struct {
1320 int mask;
1321 const char *str;
1322} mask_maps[] = {
1323 { BLK_TC_READ, "read" },
1324 { BLK_TC_WRITE, "write" },
1325 { BLK_TC_BARRIER, "barrier" },
1326 { BLK_TC_SYNC, "sync" },
1327 { BLK_TC_QUEUE, "queue" },
1328 { BLK_TC_REQUEUE, "requeue" },
1329 { BLK_TC_ISSUE, "issue" },
1330 { BLK_TC_COMPLETE, "complete" },
1331 { BLK_TC_FS, "fs" },
1332 { BLK_TC_PC, "pc" },
1333 { BLK_TC_AHEAD, "ahead" },
1334 { BLK_TC_META, "meta" },
1335 { BLK_TC_DISCARD, "discard" },
1336 { BLK_TC_DRV_DATA, "drv_data" },
1337};
1338
1339static int blk_trace_str2mask(const char *str)
1320{ 1340{
1341 int i;
1321 int mask = 0; 1342 int mask = 0;
1322 char *copy = kstrdup(str, GFP_KERNEL), *s; 1343 char *s, *token;
1323 1344
1324 if (copy == NULL) 1345 s = kstrdup(str, GFP_KERNEL);
1346 if (s == NULL)
1325 return -ENOMEM; 1347 return -ENOMEM;
1326 1348 s = strstrip(s);
1327 s = strstrip(copy);
1328 1349
1329 while (1) { 1350 while (1) {
1330 char *sep = strchr(s, ','); 1351 token = strsep(&s, ",");
1331 1352 if (token == NULL)
1332 if (sep != NULL)
1333 *sep = '\0';
1334
1335 if (strcasecmp(s, "barrier") == 0)
1336 mask |= BLK_TC_BARRIER;
1337 else if (strcasecmp(s, "complete") == 0)
1338 mask |= BLK_TC_COMPLETE;
1339 else if (strcasecmp(s, "fs") == 0)
1340 mask |= BLK_TC_FS;
1341 else if (strcasecmp(s, "issue") == 0)
1342 mask |= BLK_TC_ISSUE;
1343 else if (strcasecmp(s, "pc") == 0)
1344 mask |= BLK_TC_PC;
1345 else if (strcasecmp(s, "queue") == 0)
1346 mask |= BLK_TC_QUEUE;
1347 else if (strcasecmp(s, "read") == 0)
1348 mask |= BLK_TC_READ;
1349 else if (strcasecmp(s, "requeue") == 0)
1350 mask |= BLK_TC_REQUEUE;
1351 else if (strcasecmp(s, "sync") == 0)
1352 mask |= BLK_TC_SYNC;
1353 else if (strcasecmp(s, "write") == 0)
1354 mask |= BLK_TC_WRITE;
1355
1356 if (sep == NULL)
1357 break; 1353 break;
1358 1354
1359 s = sep + 1; 1355 if (*token == '\0')
1356 continue;
1357
1358 for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
1359 if (strcasecmp(token, mask_maps[i].str) == 0) {
1360 mask |= mask_maps[i].mask;
1361 break;
1362 }
1363 }
1364 if (i == ARRAY_SIZE(mask_maps)) {
1365 mask = -EINVAL;
1366 break;
1367 }
1360 } 1368 }
1361 kfree(copy); 1369 kfree(s);
1362 1370
1363 return mask; 1371 return mask;
1364} 1372}
1365 1373
1374static ssize_t blk_trace_mask2str(char *buf, int mask)
1375{
1376 int i;
1377 char *p = buf;
1378
1379 for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
1380 if (mask & mask_maps[i].mask) {
1381 p += sprintf(p, "%s%s",
1382 (p == buf) ? "" : ",", mask_maps[i].str);
1383 }
1384 }
1385 *p++ = '\n';
1386
1387 return p - buf;
1388}
1389
1366static struct request_queue *blk_trace_get_queue(struct block_device *bdev) 1390static struct request_queue *blk_trace_get_queue(struct block_device *bdev)
1367{ 1391{
1368 if (bdev->bd_disk == NULL) 1392 if (bdev->bd_disk == NULL)
@@ -1399,7 +1423,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
1399 if (q->blk_trace == NULL) 1423 if (q->blk_trace == NULL)
1400 ret = sprintf(buf, "disabled\n"); 1424 ret = sprintf(buf, "disabled\n");
1401 else if (attr == &dev_attr_act_mask) 1425 else if (attr == &dev_attr_act_mask)
1402 ret = sprintf(buf, "%#x\n", q->blk_trace->act_mask); 1426 ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
1403 else if (attr == &dev_attr_pid) 1427 else if (attr == &dev_attr_pid)
1404 ret = sprintf(buf, "%u\n", q->blk_trace->pid); 1428 ret = sprintf(buf, "%u\n", q->blk_trace->pid);
1405 else if (attr == &dev_attr_start_lba) 1429 else if (attr == &dev_attr_start_lba)
@@ -1424,7 +1448,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
1424 struct request_queue *q; 1448 struct request_queue *q;
1425 struct hd_struct *p; 1449 struct hd_struct *p;
1426 u64 value; 1450 u64 value;
1427 ssize_t ret = -ENXIO; 1451 ssize_t ret = -EINVAL;
1428 1452
1429 if (count == 0) 1453 if (count == 0)
1430 goto out; 1454 goto out;
@@ -1432,13 +1456,16 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
1432 if (attr == &dev_attr_act_mask) { 1456 if (attr == &dev_attr_act_mask) {
1433 if (sscanf(buf, "%llx", &value) != 1) { 1457 if (sscanf(buf, "%llx", &value) != 1) {
1434 /* Assume it is a list of trace category names */ 1458 /* Assume it is a list of trace category names */
1435 value = blk_str2act_mask(buf); 1459 ret = blk_trace_str2mask(buf);
1436 if (value < 0) 1460 if (ret < 0)
1437 goto out; 1461 goto out;
1462 value = ret;
1438 } 1463 }
1439 } else if (sscanf(buf, "%llu", &value) != 1) 1464 } else if (sscanf(buf, "%llu", &value) != 1)
1440 goto out; 1465 goto out;
1441 1466
1467 ret = -ENXIO;
1468
1442 lock_kernel(); 1469 lock_kernel();
1443 p = dev_to_part(dev); 1470 p = dev_to_part(dev);
1444 bdev = bdget(part_devt(p)); 1471 bdev = bdget(part_devt(p));