@@ -1867,6 +1867,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
static BLK_TRACE_DEVICE_ATTR(enable);
static BLK_TRACE_DEVICE_ATTR(act_mask);
+static BLK_TRACE_DEVICE_ATTR(prio_mask);
static BLK_TRACE_DEVICE_ATTR(pid);
static BLK_TRACE_DEVICE_ATTR(start_lba);
static BLK_TRACE_DEVICE_ATTR(end_lba);
@@ -1874,6 +1875,7 @@ static BLK_TRACE_DEVICE_ATTR(end_lba);
static struct attribute *blk_trace_attrs[] = {
&dev_attr_enable.attr,
&dev_attr_act_mask.attr,
+ &dev_attr_prio_mask.attr,
&dev_attr_pid.attr,
&dev_attr_start_lba.attr,
&dev_attr_end_lba.attr,
@@ -1911,6 +1913,16 @@ static const struct {
#endif /* CONFIG_BLKTRACE_EXT */
};
+static const struct {
+ int prio_mask;
+ const char *str;
+} prio_mask_maps[] = {
+ { IOPRIO_CLASS_NONE, "none" },
+ { IOPRIO_CLASS_RT, "read" },
+ { IOPRIO_CLASS_BE, "best" },
+ { IOPRIO_CLASS_IDLE, "idle" },
+};
+
static int blk_trace_str2mask(const char *str)
{
int i;
@@ -1962,6 +1974,62 @@ static ssize_t blk_trace_mask2str(char *buf, int mask)
return p - buf;
}
+#ifdef CONFIG_BLKTRACE_EXT
+static int blk_trace_str2priomask(const char *str)
+{
+ int i;
+ int mask = 0;
+ char *buf, *s, *token;
+
+ /* XXX: revisit this placeholder for now */
+ buf = kstrdup(str, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ s = strstrip(buf);
+
+ while (1) {
+ token = strsep(&s, ",");
+ if (token == NULL)
+ break;
+
+ if (*token == '\0')
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(prio_mask_maps); i++) {
+ if (strcasecmp(token, prio_mask_maps[i].str) == 0) {
+ mask |= (1 << prio_mask_maps[i].prio_mask);
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(prio_mask_maps)) {
+ mask = -EINVAL;
+ break;
+ }
+ }
+ kfree(buf);
+
+ return mask;
+}
+
+static ssize_t blk_trace_prio_mask2str(char *buf, int mask)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < ARRAY_SIZE(prio_mask_maps); i++) {
+ /* XXX: revisit this placeholder for now */
+ if (mask & (0xF & (1 << prio_mask_maps[i].prio_mask))) {
+ p += sprintf(p, "%s%s",
+ (p == buf) ? "" : ",",
+ prio_mask_maps[i].str);
+ }
+ }
+ *p++ = '\n';
+
+ return p - buf;
+}
+#endif /* CONFIG_BLKTRACE_EXT */
+
static struct request_queue *blk_trace_get_queue(struct block_device *bdev)
{
if (bdev->bd_disk == NULL)
@@ -1998,6 +2066,10 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
ret = sprintf(buf, "disabled\n");
else if (attr == &dev_attr_act_mask)
ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
+#ifdef CONFIG_BLKTRACE_EXT
+ else if (attr == &dev_attr_prio_mask)
+ ret = blk_trace_prio_mask2str(buf, q->blk_trace->prio_mask);
+#endif /* CONFIG_BLKTRACE_EXT */
else if (attr == &dev_attr_pid)
ret = sprintf(buf, "%u\n", q->blk_trace->pid);
else if (attr == &dev_attr_start_lba)
@@ -2034,7 +2106,19 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
goto out;
value = ret;
}
- } else if (kstrtoull(buf, 0, &value))
+ }
+#ifdef CONFIG_BLKTRACE_EXT
+ else if (attr == &dev_attr_prio_mask) {
+ if (kstrtoull(buf, 0, &value)) {
+ /* Assume it is a list of trace category names */
+ ret = blk_trace_str2priomask(buf);
+ if (ret < 0)
+ goto out;
+ value = ret;
+ }
+ }
+#endif /* CONFIG_BLKTRACE_EXT */
+ else if (kstrtoull(buf, 0, &value))
goto out;
ret = -ENXIO;
@@ -2069,6 +2153,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
if (ret == 0) {
if (attr == &dev_attr_act_mask)
q->blk_trace->act_mask = value;
+#ifdef CONFIG_BLKTRACE_EXT
+ else if (attr == &dev_attr_prio_mask)
+ q->blk_trace->prio_mask = value;
+#endif /* CONFIG_BLKTRACE_EXT */
else if (attr == &dev_attr_pid)
q->blk_trace->pid = value;
else if (attr == &dev_attr_start_lba)
With the priority mask and tracking support added, here we add priority mask in the sysfs. These are just place holders for now but they are required for complete the RFC. Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> --- kernel/trace/blktrace.c | 90 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-)