2 * This file contains format parsing code for blkparse, allowing you to
3 * customize the individual action format and generel output format.
13 #define VALID_SPECS "BCDFGMPQRSTU"
15 #define HEADER "%D %2c %8s %5T.%9t %5p %2a %3d "
17 static char *override_format[256];
19 static inline int valid_spec(int spec)
21 return strchr(VALID_SPECS, spec) != NULL;
24 void set_all_format_specs(char *optarg)
28 for (p = VALID_SPECS; *p; p++)
29 if (override_format[(int)(*p)] == NULL)
30 override_format[(int)(*p)] = strdup(optarg);
33 int add_format_spec(char *optarg)
37 if (!valid_spec(spec)) {
38 fprintf(stderr,"Bad format specifier %c\n", spec);
41 if (optarg[1] != ',') {
42 fprintf(stderr,"Bad format specifier - need ',' %s\n", optarg);
46 if (*optarg == '\0') {
47 fprintf(stderr,"Bad format specifier - need fmt %s\n", optarg);
52 * Set both merges (front and back)
55 override_format['B'] = strdup(optarg);
56 override_format['M'] = strdup(optarg);
58 override_format[spec] = strdup(optarg);
63 static void print_field(char *act, struct per_cpu_info *pci,
64 struct blk_io_trace *t, unsigned long long elapsed,
65 int pdu_len, unsigned char *pdu_buf, char field,
66 int minus, int has_w, int width)
72 sprintf(format, "%%-%d", width);
74 sprintf(format, "%%%d", width);
76 sprintf(format, "%%");
80 fprintf(ofp, strcat(format, "s"), act);
83 fprintf(ofp, strcat(format, "d"), pci->cpu);
86 fprintf(ofp, strcat(format, "s"), t->comm);
91 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
92 int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER);
93 int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
103 fprintf(ofp, strcat(format, "s"), rwbs);
106 case 'D': /* format width ignored */
107 fprintf(ofp,"%3d,%-3d", MAJOR(t->device), MINOR(t->device));
110 fprintf(ofp, strcat(format, "d"), t->error);
113 fprintf(ofp, strcat(format, "d"), MAJOR(t->device));
116 fprintf(ofp, strcat(format, "d"), MINOR(t->device));
119 fprintf(ofp, strcat(format, "u"), t->bytes >> 9);
122 fprintf(ofp, strcat(format, "u"), t->pid);
124 case 'P': /* format width ignored */
125 if ((pdu_len > 0) && (pdu_buf != NULL)) {
127 unsigned char *p = pdu_buf;
128 for (i = 0; i < pdu_len; i++) {
132 fprintf(ofp, "%02x", *p++);
137 fprintf(ofp, strcat(format, "ld"), t->sequence);
140 fprintf(ofp, strcat(format, "lu"), t->sector);
143 sprintf(format, "%%0%dlu", has_w ? width : 9);
144 fprintf(ofp, format, NANO_SECONDS(t->time));
147 fprintf(ofp, strcat(format, "d"), SECONDS(t->time));
150 if (elapsed == -1ULL) {
151 fprintf(stderr, "Expecting elapsed value\n");
154 fprintf(ofp, strcat(format, "llu"), elapsed / 1000);
157 __u64 *depth = (__u64 *) ((char *) t + sizeof(*t));
158 fprintf(ofp, strcat(format, "u"),
159 (unsigned int) be64_to_cpu(*depth));
163 fprintf(ofp,strcat(format, "c"), field);
168 static char *parse_field(char *act, struct per_cpu_info *pci,
169 struct blk_io_trace *t, unsigned long long elapsed,
170 int pdu_len, unsigned char *pdu_buf,
176 char *p = master_format;
185 width = (width * 10) + (*p++ - '0');
186 } while ((*p) && (isdigit(*p)));
189 print_field(act, pci, t, elapsed, pdu_len, pdu_buf, *p++,
190 minus, has_w, width);
195 static char *fmt_select(int fmt_spec, struct blk_io_trace *t,
196 unsigned long long elapsed)
199 static char scratch_format[1024];
201 if (override_format[fmt_spec] != NULL)
202 return override_format[fmt_spec];
205 case 'C': /* Complete */
206 if (t->action & BLK_TC_ACT(BLK_TC_PC))
207 strcpy(scratch_format, HEADER "(%P) [%e]\n");
209 if (elapsed != -1ULL) {
210 strcpy(scratch_format,
211 HEADER "%S +%n (%8u) [%e]\n");
213 strcpy(scratch_format, HEADER "%S + %n [%e]\n");
215 fmt = scratch_format;
218 case 'D': /* Issue */
219 if (t->action & BLK_TC_ACT(BLK_TC_PC))
220 strcpy(scratch_format, HEADER "%n (%P) [%C]\n");
222 if (elapsed != -1ULL) {
223 strcpy(scratch_format,
224 HEADER "%S + %n (%8u) [%C]\n");
226 strcpy(scratch_format, HEADER "%S + %n [%C]\n");
228 fmt = scratch_format;
231 case 'I': /* Insert */
232 if (t->action & BLK_TC_ACT(BLK_TC_PC))
233 strcpy(scratch_format, HEADER "%n (%P) [%C]\n");
235 if (elapsed != -1ULL) {
236 strcpy(scratch_format,
237 HEADER "%S + %n (%8u) [%C]\n");
239 strcpy(scratch_format, HEADER "%S + %n [%C]\n");
241 fmt = scratch_format;
244 case 'Q': /* Queue */
245 case 'W': /* Bounce */
246 if (elapsed != -1ULL) {
247 strcpy(scratch_format, HEADER "%S + %n (%8u) [%C]\n");
249 strcpy(scratch_format, HEADER "%S + %n [%C]\n");
250 fmt = scratch_format;
253 case 'B': /* Back merge */
254 case 'F': /* Front merge */
255 case 'M': /* Front or back merge */
256 fmt = HEADER "%S + %n [%C]\n";
260 fmt = HEADER "[%C]\n";
263 case 'G': /* Get request */
264 case 'S': /* Sleep request */
265 fmt = HEADER "%S + %n [%C]\n";
268 case 'U': /* Unplug IO */
269 case 'T': /* Unplug timer */
270 fmt = HEADER "[%C] %U\n";
273 case 'X': /* Split */
274 strcpy(scratch_format, HEADER "%S / %U [%C]\n");
275 fmt = scratch_format;
279 fprintf(stderr,"FATAL: Invalid format spec %c\n", fmt_spec);
287 void process_fmt(char *act, struct per_cpu_info *pci, struct blk_io_trace *t,
288 unsigned long long elapsed, int pdu_len,
289 unsigned char *pdu_buf)
291 char *p = fmt_select(act[0], t, elapsed);
295 case '%': /* Field specifier */
298 fprintf(ofp, "%c", *p++);
300 fprintf(ofp, "%c", '%');
302 p = parse_field(act, pci, t, elapsed,
303 pdu_len, pdu_buf, p);
305 case '\\': { /* escape */
307 case 'b': fprintf(ofp, "\b"); break;
308 case 'n': fprintf(ofp, "\n"); break;
309 case 'r': fprintf(ofp, "\r"); break;
310 case 't': fprintf(ofp, "\t"); break;
313 "Invalid escape char in format %c\n",
322 fprintf(ofp, "%c", *p++);