Blame view

kernel/trace/blktrace.c 42.1 KB
2056a782f   Jens Axboe   [PATCH] Block que...
1
  /*
0fe234795   Jens Axboe   [PATCH] Update ax...
2
   * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
2056a782f   Jens Axboe   [PATCH] Block que...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   */
2056a782f   Jens Axboe   [PATCH] Block que...
18
19
20
21
22
23
  #include <linux/kernel.h>
  #include <linux/blkdev.h>
  #include <linux/blktrace_api.h>
  #include <linux/percpu.h>
  #include <linux/init.h>
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
2056a782f   Jens Axboe   [PATCH] Block que...
25
  #include <linux/debugfs.h>
6e5fdeedc   Paul Gortmaker   kernel: Fix files...
26
  #include <linux/export.h>
be1c63411   Olaf Kirch   [PATCH] blktrace:...
27
  #include <linux/time.h>
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
28
  #include <linux/uaccess.h>
55782138e   Li Zefan   tracing/events: c...
29
30
  
  #include <trace/events/block.h>
2db270a80   Frederic Weisbecker   tracing/blktrace:...
31
  #include "trace_output.h"
2056a782f   Jens Axboe   [PATCH] Block que...
32

55782138e   Li Zefan   tracing/events: c...
33
  #ifdef CONFIG_BLK_DEV_IO_TRACE
2056a782f   Jens Axboe   [PATCH] Block que...
34
  static unsigned int blktrace_seq __read_mostly = 1;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
35
  static struct trace_array *blk_tr;
5006ea73f   Li Zefan   blktrace: make bl...
36
  static bool blk_tracer_enabled __read_mostly;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
37
38
  
  /* Select an alternative, minimalistic output than the original one */
ef18012b2   Steven Rostedt   tracing: remove f...
39
  #define TRACE_BLK_OPT_CLASSIC	0x1
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
40
41
42
  
  static struct tracer_opt blk_tracer_opts[] = {
  	/* Default disable the minimalistic output */
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
43
  	{ TRACER_OPT(blk_classic, TRACE_BLK_OPT_CLASSIC) },
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
44
45
46
47
48
49
50
  	{ }
  };
  
  static struct tracer_flags blk_tracer_flags = {
  	.val  = 0,
  	.opts = blk_tracer_opts,
  };
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
51
  /* Global reference count of probes */
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
52
  static atomic_t blk_probes_ref = ATOMIC_INIT(0);
3c289ba7c   Li Zefan   blktrace: remove ...
53
  static void blk_register_tracepoints(void);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
54
  static void blk_unregister_tracepoints(void);
2056a782f   Jens Axboe   [PATCH] Block que...
55
  /*
be1c63411   Olaf Kirch   [PATCH] blktrace:...
56
57
   * Send out a notify message.
   */
a863055b1   Jens Axboe   [PATCH] blktrace:...
58
59
  static void trace_note(struct blk_trace *bt, pid_t pid, int action,
  		       const void *data, size_t len)
be1c63411   Olaf Kirch   [PATCH] blktrace:...
60
61
  {
  	struct blk_io_trace *t;
18cea4591   Li Zefan   blktrace: print o...
62
  	struct ring_buffer_event *event = NULL;
e77405ad8   Steven Rostedt   tracing: pass aro...
63
  	struct ring_buffer *buffer = NULL;
18cea4591   Li Zefan   blktrace: print o...
64
65
66
67
68
  	int pc = 0;
  	int cpu = smp_processor_id();
  	bool blk_tracer = blk_tracer_enabled;
  
  	if (blk_tracer) {
e77405ad8   Steven Rostedt   tracing: pass aro...
69
  		buffer = blk_tr->buffer;
18cea4591   Li Zefan   blktrace: print o...
70
  		pc = preempt_count();
e77405ad8   Steven Rostedt   tracing: pass aro...
71
  		event = trace_buffer_lock_reserve(buffer, TRACE_BLK,
18cea4591   Li Zefan   blktrace: print o...
72
73
74
75
76
77
78
  						  sizeof(*t) + len,
  						  0, pc);
  		if (!event)
  			return;
  		t = ring_buffer_event_data(event);
  		goto record_it;
  	}
be1c63411   Olaf Kirch   [PATCH] blktrace:...
79

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
80
81
  	if (!bt->rchan)
  		return;
be1c63411   Olaf Kirch   [PATCH] blktrace:...
82
  	t = relay_reserve(bt->rchan, sizeof(*t) + len);
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
83
  	if (t) {
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
84
  		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
2997c8c4a   Ingo Molnar   block: fix blktra...
85
  		t->time = ktime_to_ns(ktime_get());
18cea4591   Li Zefan   blktrace: print o...
86
  record_it:
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
87
88
89
90
91
92
  		t->device = bt->dev;
  		t->action = action;
  		t->pid = pid;
  		t->cpu = cpu;
  		t->pdu_len = len;
  		memcpy((void *) t + sizeof(*t), data, len);
18cea4591   Li Zefan   blktrace: print o...
93
94
  
  		if (blk_tracer)
e77405ad8   Steven Rostedt   tracing: pass aro...
95
  			trace_buffer_unlock_commit(buffer, event, 0, pc);
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
96
  	}
be1c63411   Olaf Kirch   [PATCH] blktrace:...
97
98
99
  }
  
  /*
2056a782f   Jens Axboe   [PATCH] Block que...
100
101
102
103
104
   * Send out a notify for this process, if we haven't done so since a trace
   * started
   */
  static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk)
  {
a863055b1   Jens Axboe   [PATCH] blktrace:...
105
106
  	tsk->btrace_seq = blktrace_seq;
  	trace_note(bt, tsk->pid, BLK_TN_PROCESS, tsk->comm, sizeof(tsk->comm));
be1c63411   Olaf Kirch   [PATCH] blktrace:...
107
  }
2056a782f   Jens Axboe   [PATCH] Block que...
108

be1c63411   Olaf Kirch   [PATCH] blktrace:...
109
110
111
112
113
114
115
116
117
118
119
120
121
  static void trace_note_time(struct blk_trace *bt)
  {
  	struct timespec now;
  	unsigned long flags;
  	u32 words[2];
  
  	getnstimeofday(&now);
  	words[0] = now.tv_sec;
  	words[1] = now.tv_nsec;
  
  	local_irq_save(flags);
  	trace_note(bt, 0, BLK_TN_TIMESTAMP, words, sizeof(words));
  	local_irq_restore(flags);
2056a782f   Jens Axboe   [PATCH] Block que...
122
  }
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
123
124
125
126
  void __trace_note_message(struct blk_trace *bt, const char *fmt, ...)
  {
  	int n;
  	va_list args;
14a73f547   Carl Henrik Lunde   block: disable IR...
127
  	unsigned long flags;
64565911c   Jens Axboe   block: make blktr...
128
  	char *buf;
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
129

18cea4591   Li Zefan   blktrace: print o...
130
131
  	if (unlikely(bt->trace_state != Blktrace_running &&
  		     !blk_tracer_enabled))
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
132
  		return;
490da40d8   Tao Ma   blktrace: Don't o...
133
134
135
136
137
138
  	/*
  	 * If the BLK_TC_NOTIFY action mask isn't set, don't send any note
  	 * message to the trace.
  	 */
  	if (!(bt->act_mask & BLK_TC_NOTIFY))
  		return;
14a73f547   Carl Henrik Lunde   block: disable IR...
139
  	local_irq_save(flags);
64565911c   Jens Axboe   block: make blktr...
140
  	buf = per_cpu_ptr(bt->msg_data, smp_processor_id());
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
141
  	va_start(args, fmt);
64565911c   Jens Axboe   block: make blktr...
142
  	n = vscnprintf(buf, BLK_TN_MAX_MSG, fmt, args);
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
143
  	va_end(args);
64565911c   Jens Axboe   block: make blktr...
144
  	trace_note(bt, 0, BLK_TN_MESSAGE, buf, n);
14a73f547   Carl Henrik Lunde   block: disable IR...
145
  	local_irq_restore(flags);
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
146
147
  }
  EXPORT_SYMBOL_GPL(__trace_note_message);
2056a782f   Jens Axboe   [PATCH] Block que...
148
149
150
151
152
  static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector,
  			 pid_t pid)
  {
  	if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0)
  		return 1;
d0deef5b1   Shawn Du   blktrace: support...
153
  	if (sector && (sector < bt->start_lba || sector > bt->end_lba))
2056a782f   Jens Axboe   [PATCH] Block que...
154
155
156
157
158
159
160
161
162
163
  		return 1;
  	if (bt->pid && pid != bt->pid)
  		return 1;
  
  	return 0;
  }
  
  /*
   * Data direction bit lookup
   */
e4955c998   Li Zefan   blktrace: mark dd...
164
165
  static const u32 ddir_act[2] = { BLK_TC_ACT(BLK_TC_READ),
  				 BLK_TC_ACT(BLK_TC_WRITE) };
2056a782f   Jens Axboe   [PATCH] Block que...
166

7b6d91dae   Christoph Hellwig   block: unify flag...
167
  #define BLK_TC_RAHEAD		BLK_TC_AHEAD
35ba8f708   David Woodhouse   blktrace: simplif...
168
  /* The ilog2() calls fall out because they're constant */
7b6d91dae   Christoph Hellwig   block: unify flag...
169
170
  #define MASK_TC_BIT(rw, __name) ((rw & REQ_ ## __name) << \
  	  (ilog2(BLK_TC_ ## __name) + BLK_TC_SHIFT - __REQ_ ## __name))
2056a782f   Jens Axboe   [PATCH] Block que...
171
172
173
174
175
  
  /*
   * The worker for the various blk_add_trace*() types. Fills out a
   * blk_io_trace structure and places it in a per-cpu subbuffer.
   */
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
176
  static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
2056a782f   Jens Axboe   [PATCH] Block que...
177
178
179
  		     int rw, u32 what, int error, int pdu_len, void *pdu_data)
  {
  	struct task_struct *tsk = current;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
180
  	struct ring_buffer_event *event = NULL;
e77405ad8   Steven Rostedt   tracing: pass aro...
181
  	struct ring_buffer *buffer = NULL;
2056a782f   Jens Axboe   [PATCH] Block que...
182
  	struct blk_io_trace *t;
0a9877514   Arnaldo Carvalho de Melo   ring_buffer: remo...
183
  	unsigned long flags = 0;
2056a782f   Jens Axboe   [PATCH] Block que...
184
185
  	unsigned long *sequence;
  	pid_t pid;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
186
  	int cpu, pc = 0;
18cea4591   Li Zefan   blktrace: print o...
187
  	bool blk_tracer = blk_tracer_enabled;
2056a782f   Jens Axboe   [PATCH] Block que...
188

18cea4591   Li Zefan   blktrace: print o...
189
  	if (unlikely(bt->trace_state != Blktrace_running && !blk_tracer))
2056a782f   Jens Axboe   [PATCH] Block que...
190
191
192
  		return;
  
  	what |= ddir_act[rw & WRITE];
7b6d91dae   Christoph Hellwig   block: unify flag...
193
194
  	what |= MASK_TC_BIT(rw, SYNC);
  	what |= MASK_TC_BIT(rw, RAHEAD);
35ba8f708   David Woodhouse   blktrace: simplif...
195
196
  	what |= MASK_TC_BIT(rw, META);
  	what |= MASK_TC_BIT(rw, DISCARD);
c09c47cae   Namhyung Kim   blktrace: add FLU...
197
198
  	what |= MASK_TC_BIT(rw, FLUSH);
  	what |= MASK_TC_BIT(rw, FUA);
2056a782f   Jens Axboe   [PATCH] Block que...
199
200
  
  	pid = tsk->pid;
d0deef5b1   Shawn Du   blktrace: support...
201
  	if (act_log_check(bt, what, sector, pid))
2056a782f   Jens Axboe   [PATCH] Block que...
202
  		return;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
203
  	cpu = raw_smp_processor_id();
18cea4591   Li Zefan   blktrace: print o...
204
  	if (blk_tracer) {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
205
  		tracing_record_cmdline(current);
e77405ad8   Steven Rostedt   tracing: pass aro...
206
  		buffer = blk_tr->buffer;
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
207
  		pc = preempt_count();
e77405ad8   Steven Rostedt   tracing: pass aro...
208
  		event = trace_buffer_lock_reserve(buffer, TRACE_BLK,
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
209
210
  						  sizeof(*t) + pdu_len,
  						  0, pc);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
211
212
  		if (!event)
  			return;
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
213
  		t = ring_buffer_event_data(event);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
214
215
  		goto record_it;
  	}
2056a782f   Jens Axboe   [PATCH] Block que...
216
217
218
219
  
  	/*
  	 * A word about the locking here - we disable interrupts to reserve
  	 * some space in the relay per-cpu buffer, to prevent an irq
14a73f547   Carl Henrik Lunde   block: disable IR...
220
  	 * from coming in and stepping on our toes.
2056a782f   Jens Axboe   [PATCH] Block que...
221
222
223
224
225
226
227
228
  	 */
  	local_irq_save(flags);
  
  	if (unlikely(tsk->btrace_seq != blktrace_seq))
  		trace_note_tsk(bt, tsk);
  
  	t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len);
  	if (t) {
2056a782f   Jens Axboe   [PATCH] Block que...
229
230
231
232
  		sequence = per_cpu_ptr(bt->sequence, cpu);
  
  		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
  		t->sequence = ++(*sequence);
2997c8c4a   Ingo Molnar   block: fix blktra...
233
  		t->time = ktime_to_ns(ktime_get());
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
234
  record_it:
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
235
  		/*
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
236
237
238
239
240
241
242
  		 * These two are not needed in ftrace as they are in the
  		 * generic trace_entry, filled by tracing_generic_entry_update,
  		 * but for the trace_event->bin() synthesizer benefit we do it
  		 * here too.
  		 */
  		t->cpu = cpu;
  		t->pid = pid;
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
243

2056a782f   Jens Axboe   [PATCH] Block que...
244
245
246
  		t->sector = sector;
  		t->bytes = bytes;
  		t->action = what;
2056a782f   Jens Axboe   [PATCH] Block que...
247
  		t->device = bt->dev;
2056a782f   Jens Axboe   [PATCH] Block que...
248
249
250
251
252
  		t->error = error;
  		t->pdu_len = pdu_len;
  
  		if (pdu_len)
  			memcpy((void *) t + sizeof(*t), pdu_data, pdu_len);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
253

18cea4591   Li Zefan   blktrace: print o...
254
  		if (blk_tracer) {
e77405ad8   Steven Rostedt   tracing: pass aro...
255
  			trace_buffer_unlock_commit(buffer, event, 0, pc);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
256
257
  			return;
  		}
2056a782f   Jens Axboe   [PATCH] Block que...
258
259
260
261
  	}
  
  	local_irq_restore(flags);
  }
2056a782f   Jens Axboe   [PATCH] Block que...
262
  static struct dentry *blk_tree_root;
11a57153e   Jens Axboe   blktrace: kill th...
263
  static DEFINE_MUTEX(blk_tree_mutex);
2056a782f   Jens Axboe   [PATCH] Block que...
264

ad5dd5493   Li Zefan   blktrace: fix mem...
265
  static void blk_trace_free(struct blk_trace *bt)
2056a782f   Jens Axboe   [PATCH] Block que...
266
  {
02c62304e   Alan D. Brunelle   Added in user-inj...
267
  	debugfs_remove(bt->msg_file);
2056a782f   Jens Axboe   [PATCH] Block que...
268
  	debugfs_remove(bt->dropped_file);
f48fc4d32   Jens Axboe   block: get rid of...
269
  	relay_close(bt->rchan);
39cbb602b   Alan D. Brunelle   Remove double rem...
270
  	debugfs_remove(bt->dir);
2056a782f   Jens Axboe   [PATCH] Block que...
271
  	free_percpu(bt->sequence);
64565911c   Jens Axboe   block: make blktr...
272
  	free_percpu(bt->msg_data);
2056a782f   Jens Axboe   [PATCH] Block que...
273
  	kfree(bt);
ad5dd5493   Li Zefan   blktrace: fix mem...
274
275
276
277
278
  }
  
  static void blk_trace_cleanup(struct blk_trace *bt)
  {
  	blk_trace_free(bt);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
279
280
  	if (atomic_dec_and_test(&blk_probes_ref))
  		blk_unregister_tracepoints();
2056a782f   Jens Axboe   [PATCH] Block que...
281
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
282
  int blk_trace_remove(struct request_queue *q)
2056a782f   Jens Axboe   [PATCH] Block que...
283
284
285
286
287
288
  {
  	struct blk_trace *bt;
  
  	bt = xchg(&q->blk_trace, NULL);
  	if (!bt)
  		return -EINVAL;
555472048   Li Zefan   blktrace: fix the...
289
  	if (bt->trace_state != Blktrace_running)
2056a782f   Jens Axboe   [PATCH] Block que...
290
291
292
293
  		blk_trace_cleanup(bt);
  
  	return 0;
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
294
  EXPORT_SYMBOL_GPL(blk_trace_remove);
2056a782f   Jens Axboe   [PATCH] Block que...
295
296
297
  
  static int blk_dropped_open(struct inode *inode, struct file *filp)
  {
8e18e2941   Theodore Ts'o   [PATCH] inode_die...
298
  	filp->private_data = inode->i_private;
2056a782f   Jens Axboe   [PATCH] Block que...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  
  	return 0;
  }
  
  static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
  				size_t count, loff_t *ppos)
  {
  	struct blk_trace *bt = filp->private_data;
  	char buf[16];
  
  	snprintf(buf, sizeof(buf), "%u
  ", atomic_read(&bt->dropped));
  
  	return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
  }
2b8693c06   Arjan van de Ven   [PATCH] mark stru...
314
  static const struct file_operations blk_dropped_fops = {
2056a782f   Jens Axboe   [PATCH] Block que...
315
316
317
  	.owner =	THIS_MODULE,
  	.open =		blk_dropped_open,
  	.read =		blk_dropped_read,
6038f373a   Arnd Bergmann   llseek: automatic...
318
  	.llseek =	default_llseek,
2056a782f   Jens Axboe   [PATCH] Block que...
319
  };
02c62304e   Alan D. Brunelle   Added in user-inj...
320
321
322
323
324
325
326
327
328
329
330
331
  static int blk_msg_open(struct inode *inode, struct file *filp)
  {
  	filp->private_data = inode->i_private;
  
  	return 0;
  }
  
  static ssize_t blk_msg_write(struct file *filp, const char __user *buffer,
  				size_t count, loff_t *ppos)
  {
  	char *msg;
  	struct blk_trace *bt;
7635b03ad   Li Zefan   blktrace: small c...
332
  	if (count >= BLK_TN_MAX_MSG)
02c62304e   Alan D. Brunelle   Added in user-inj...
333
  		return -EINVAL;
a4b3ada83   Carl Henrik Lunde   blktrace: NUL-ter...
334
  	msg = kmalloc(count + 1, GFP_KERNEL);
02c62304e   Alan D. Brunelle   Added in user-inj...
335
336
337
338
339
340
341
  	if (msg == NULL)
  		return -ENOMEM;
  
  	if (copy_from_user(msg, buffer, count)) {
  		kfree(msg);
  		return -EFAULT;
  	}
a4b3ada83   Carl Henrik Lunde   blktrace: NUL-ter...
342
  	msg[count] = '\0';
02c62304e   Alan D. Brunelle   Added in user-inj...
343
344
345
346
347
348
349
350
351
352
353
  	bt = filp->private_data;
  	__trace_note_message(bt, "%s", msg);
  	kfree(msg);
  
  	return count;
  }
  
  static const struct file_operations blk_msg_fops = {
  	.owner =	THIS_MODULE,
  	.open =		blk_msg_open,
  	.write =	blk_msg_write,
6038f373a   Arnd Bergmann   llseek: automatic...
354
  	.llseek =	noop_llseek,
02c62304e   Alan D. Brunelle   Added in user-inj...
355
  };
2056a782f   Jens Axboe   [PATCH] Block que...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  /*
   * Keep track of how many times we encountered a full subbuffer, to aid
   * the user space app in telling how many lost events there were.
   */
  static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
  				     void *prev_subbuf, size_t prev_padding)
  {
  	struct blk_trace *bt;
  
  	if (!relay_buf_full(buf))
  		return 1;
  
  	bt = buf->chan->private_data;
  	atomic_inc(&bt->dropped);
  	return 0;
  }
  
  static int blk_remove_buf_file_callback(struct dentry *dentry)
  {
  	debugfs_remove(dentry);
f48fc4d32   Jens Axboe   block: get rid of...
376

2056a782f   Jens Axboe   [PATCH] Block que...
377
378
379
380
381
  	return 0;
  }
  
  static struct dentry *blk_create_buf_file_callback(const char *filename,
  						   struct dentry *parent,
f4ae40a6a   Al Viro   switch debugfs to...
382
  						   umode_t mode,
2056a782f   Jens Axboe   [PATCH] Block que...
383
384
385
386
387
388
389
390
391
392
393
394
  						   struct rchan_buf *buf,
  						   int *is_global)
  {
  	return debugfs_create_file(filename, mode, parent, buf,
  					&relay_file_operations);
  }
  
  static struct rchan_callbacks blk_relay_callbacks = {
  	.subbuf_start		= blk_subbuf_start_callback,
  	.create_buf_file	= blk_create_buf_file_callback,
  	.remove_buf_file	= blk_remove_buf_file_callback,
  };
9908c3099   Li Zefan   blktrace: support...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  static void blk_trace_setup_lba(struct blk_trace *bt,
  				struct block_device *bdev)
  {
  	struct hd_struct *part = NULL;
  
  	if (bdev)
  		part = bdev->bd_part;
  
  	if (part) {
  		bt->start_lba = part->start_sect;
  		bt->end_lba = part->start_sect + part->nr_sects;
  	} else {
  		bt->start_lba = 0;
  		bt->end_lba = -1ULL;
  	}
  }
2056a782f   Jens Axboe   [PATCH] Block que...
411
412
413
  /*
   * Setup everything required to start tracing
   */
6da127ad0   Christof Schmitt   blktrace: Add blk...
414
  int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
d0deef5b1   Shawn Du   blktrace: support...
415
416
  		       struct block_device *bdev,
  		       struct blk_user_trace_setup *buts)
2056a782f   Jens Axboe   [PATCH] Block que...
417
  {
2056a782f   Jens Axboe   [PATCH] Block que...
418
419
  	struct blk_trace *old_bt, *bt = NULL;
  	struct dentry *dir = NULL;
2056a782f   Jens Axboe   [PATCH] Block que...
420
  	int ret, i;
171044d44   Arnd Bergmann   compat_ioctl: han...
421
  	if (!buts->buf_size || !buts->buf_nr)
2056a782f   Jens Axboe   [PATCH] Block que...
422
  		return -EINVAL;
0497b345e   Jens Axboe   blktrace: use BLK...
423
424
  	strncpy(buts->name, name, BLKTRACE_BDEV_SIZE);
  	buts->name[BLKTRACE_BDEV_SIZE - 1] = '\0';
2056a782f   Jens Axboe   [PATCH] Block que...
425
426
427
428
429
  
  	/*
  	 * some device names have larger paths - convert the slashes
  	 * to underscores for this to work as expected
  	 */
171044d44   Arnd Bergmann   compat_ioctl: han...
430
431
432
  	for (i = 0; i < strlen(buts->name); i++)
  		if (buts->name[i] == '/')
  			buts->name[i] = '_';
2056a782f   Jens Axboe   [PATCH] Block que...
433

2056a782f   Jens Axboe   [PATCH] Block que...
434
435
  	bt = kzalloc(sizeof(*bt), GFP_KERNEL);
  	if (!bt)
ad5dd5493   Li Zefan   blktrace: fix mem...
436
  		return -ENOMEM;
2056a782f   Jens Axboe   [PATCH] Block que...
437

ad5dd5493   Li Zefan   blktrace: fix mem...
438
  	ret = -ENOMEM;
2056a782f   Jens Axboe   [PATCH] Block que...
439
440
441
  	bt->sequence = alloc_percpu(unsigned long);
  	if (!bt->sequence)
  		goto err;
313e458f8   Rusty Russell   alloc_percpu: add...
442
  	bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char));
64565911c   Jens Axboe   block: make blktr...
443
444
  	if (!bt->msg_data)
  		goto err;
2056a782f   Jens Axboe   [PATCH] Block que...
445
  	ret = -ENOENT;
f48fc4d32   Jens Axboe   block: get rid of...
446

b5230b56e   Li Zefan   blktrace: fix a r...
447
  	mutex_lock(&blk_tree_mutex);
f48fc4d32   Jens Axboe   block: get rid of...
448
449
  	if (!blk_tree_root) {
  		blk_tree_root = debugfs_create_dir("block", NULL);
b5230b56e   Li Zefan   blktrace: fix a r...
450
451
  		if (!blk_tree_root) {
  			mutex_unlock(&blk_tree_mutex);
1a17662ea   Li Zefan   blktrace: fix pos...
452
  			goto err;
b5230b56e   Li Zefan   blktrace: fix a r...
453
  		}
f48fc4d32   Jens Axboe   block: get rid of...
454
  	}
b5230b56e   Li Zefan   blktrace: fix a r...
455
  	mutex_unlock(&blk_tree_mutex);
f48fc4d32   Jens Axboe   block: get rid of...
456
457
  
  	dir = debugfs_create_dir(buts->name, blk_tree_root);
2056a782f   Jens Axboe   [PATCH] Block que...
458
459
460
461
  	if (!dir)
  		goto err;
  
  	bt->dir = dir;
6da127ad0   Christof Schmitt   blktrace: Add blk...
462
  	bt->dev = dev;
2056a782f   Jens Axboe   [PATCH] Block que...
463
464
465
  	atomic_set(&bt->dropped, 0);
  
  	ret = -EIO;
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
466
467
  	bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt,
  					       &blk_dropped_fops);
2056a782f   Jens Axboe   [PATCH] Block que...
468
469
  	if (!bt->dropped_file)
  		goto err;
02c62304e   Alan D. Brunelle   Added in user-inj...
470
471
472
  	bt->msg_file = debugfs_create_file("msg", 0222, dir, bt, &blk_msg_fops);
  	if (!bt->msg_file)
  		goto err;
171044d44   Arnd Bergmann   compat_ioctl: han...
473
474
  	bt->rchan = relay_open("trace", dir, buts->buf_size,
  				buts->buf_nr, &blk_relay_callbacks, bt);
2056a782f   Jens Axboe   [PATCH] Block que...
475
476
  	if (!bt->rchan)
  		goto err;
2056a782f   Jens Axboe   [PATCH] Block que...
477

171044d44   Arnd Bergmann   compat_ioctl: han...
478
  	bt->act_mask = buts->act_mask;
2056a782f   Jens Axboe   [PATCH] Block que...
479
480
  	if (!bt->act_mask)
  		bt->act_mask = (u16) -1;
9908c3099   Li Zefan   blktrace: support...
481
  	blk_trace_setup_lba(bt, bdev);
2056a782f   Jens Axboe   [PATCH] Block que...
482

d0deef5b1   Shawn Du   blktrace: support...
483
484
485
486
487
  	/* overwrite with user settings */
  	if (buts->start_lba)
  		bt->start_lba = buts->start_lba;
  	if (buts->end_lba)
  		bt->end_lba = buts->end_lba;
171044d44   Arnd Bergmann   compat_ioctl: han...
488
  	bt->pid = buts->pid;
2056a782f   Jens Axboe   [PATCH] Block que...
489
490
491
492
493
494
495
496
  	bt->trace_state = Blktrace_setup;
  
  	ret = -EBUSY;
  	old_bt = xchg(&q->blk_trace, bt);
  	if (old_bt) {
  		(void) xchg(&q->blk_trace, old_bt);
  		goto err;
  	}
17ba97e34   Li Zefan   blktrace: fix blk...
497
  	if (atomic_inc_return(&blk_probes_ref) == 1)
cbe28296e   Li Zefan   blktrace: don't i...
498
  		blk_register_tracepoints();
2056a782f   Jens Axboe   [PATCH] Block que...
499
500
  	return 0;
  err:
ad5dd5493   Li Zefan   blktrace: fix mem...
501
  	blk_trace_free(bt);
2056a782f   Jens Axboe   [PATCH] Block que...
502
503
  	return ret;
  }
171044d44   Arnd Bergmann   compat_ioctl: han...
504

6da127ad0   Christof Schmitt   blktrace: Add blk...
505
  int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
d0deef5b1   Shawn Du   blktrace: support...
506
  		    struct block_device *bdev,
6da127ad0   Christof Schmitt   blktrace: Add blk...
507
  		    char __user *arg)
171044d44   Arnd Bergmann   compat_ioctl: han...
508
509
510
511
512
513
514
  {
  	struct blk_user_trace_setup buts;
  	int ret;
  
  	ret = copy_from_user(&buts, arg, sizeof(buts));
  	if (ret)
  		return -EFAULT;
d0deef5b1   Shawn Du   blktrace: support...
515
  	ret = do_blk_trace_setup(q, name, dev, bdev, &buts);
171044d44   Arnd Bergmann   compat_ioctl: han...
516
517
  	if (ret)
  		return ret;
9a8c28c83   Dmitry Monakhov   blktrace: perform...
518
519
  	if (copy_to_user(arg, &buts, sizeof(buts))) {
  		blk_trace_remove(q);
171044d44   Arnd Bergmann   compat_ioctl: han...
520
  		return -EFAULT;
9a8c28c83   Dmitry Monakhov   blktrace: perform...
521
  	}
171044d44   Arnd Bergmann   compat_ioctl: han...
522
523
  	return 0;
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
524
  EXPORT_SYMBOL_GPL(blk_trace_setup);
2056a782f   Jens Axboe   [PATCH] Block que...
525

62c2a7d96   Arnd Bergmann   block: push BKL i...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
  static int compat_blk_trace_setup(struct request_queue *q, char *name,
  				  dev_t dev, struct block_device *bdev,
  				  char __user *arg)
  {
  	struct blk_user_trace_setup buts;
  	struct compat_blk_user_trace_setup cbuts;
  	int ret;
  
  	if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
  		return -EFAULT;
  
  	buts = (struct blk_user_trace_setup) {
  		.act_mask = cbuts.act_mask,
  		.buf_size = cbuts.buf_size,
  		.buf_nr = cbuts.buf_nr,
  		.start_lba = cbuts.start_lba,
  		.end_lba = cbuts.end_lba,
  		.pid = cbuts.pid,
  	};
  	memcpy(&buts.name, &cbuts.name, 32);
  
  	ret = do_blk_trace_setup(q, name, dev, bdev, &buts);
  	if (ret)
  		return ret;
  
  	if (copy_to_user(arg, &buts.name, 32)) {
  		blk_trace_remove(q);
  		return -EFAULT;
  	}
  
  	return 0;
  }
  #endif
6da127ad0   Christof Schmitt   blktrace: Add blk...
560
  int blk_trace_startstop(struct request_queue *q, int start)
2056a782f   Jens Axboe   [PATCH] Block que...
561
  {
2056a782f   Jens Axboe   [PATCH] Block que...
562
  	int ret;
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
563
  	struct blk_trace *bt = q->blk_trace;
2056a782f   Jens Axboe   [PATCH] Block que...
564

939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
565
  	if (bt == NULL)
2056a782f   Jens Axboe   [PATCH] Block que...
566
567
568
569
570
571
572
573
574
575
576
577
578
  		return -EINVAL;
  
  	/*
  	 * For starting a trace, we can transition from a setup or stopped
  	 * trace. For stopping a trace, the state must be running
  	 */
  	ret = -EINVAL;
  	if (start) {
  		if (bt->trace_state == Blktrace_setup ||
  		    bt->trace_state == Blktrace_stopped) {
  			blktrace_seq++;
  			smp_mb();
  			bt->trace_state = Blktrace_running;
be1c63411   Olaf Kirch   [PATCH] blktrace:...
579
580
  
  			trace_note_time(bt);
2056a782f   Jens Axboe   [PATCH] Block que...
581
582
583
584
585
586
587
588
589
590
591
592
  			ret = 0;
  		}
  	} else {
  		if (bt->trace_state == Blktrace_running) {
  			bt->trace_state = Blktrace_stopped;
  			relay_flush(bt->rchan);
  			ret = 0;
  		}
  	}
  
  	return ret;
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
593
  EXPORT_SYMBOL_GPL(blk_trace_startstop);
2056a782f   Jens Axboe   [PATCH] Block que...
594
595
596
597
  
  /**
   * blk_trace_ioctl: - handle the ioctls associated with tracing
   * @bdev:	the block device
ef18012b2   Steven Rostedt   tracing: remove f...
598
   * @cmd:	the ioctl cmd
2056a782f   Jens Axboe   [PATCH] Block que...
599
600
601
602
603
   * @arg:	the argument data, if any
   *
   **/
  int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
  {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
604
  	struct request_queue *q;
2056a782f   Jens Axboe   [PATCH] Block que...
605
  	int ret, start = 0;
6da127ad0   Christof Schmitt   blktrace: Add blk...
606
  	char b[BDEVNAME_SIZE];
2056a782f   Jens Axboe   [PATCH] Block que...
607
608
609
610
611
612
613
614
615
  
  	q = bdev_get_queue(bdev);
  	if (!q)
  		return -ENXIO;
  
  	mutex_lock(&bdev->bd_mutex);
  
  	switch (cmd) {
  	case BLKTRACESETUP:
f36f21ecc   Jean Delvare   Fix misuses of bd...
616
  		bdevname(bdev, b);
d0deef5b1   Shawn Du   blktrace: support...
617
  		ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
2056a782f   Jens Axboe   [PATCH] Block que...
618
  		break;
62c2a7d96   Arnd Bergmann   block: push BKL i...
619
620
621
622
623
624
  #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
  	case BLKTRACESETUP32:
  		bdevname(bdev, b);
  		ret = compat_blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
  		break;
  #endif
2056a782f   Jens Axboe   [PATCH] Block que...
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  	case BLKTRACESTART:
  		start = 1;
  	case BLKTRACESTOP:
  		ret = blk_trace_startstop(q, start);
  		break;
  	case BLKTRACETEARDOWN:
  		ret = blk_trace_remove(q);
  		break;
  	default:
  		ret = -ENOTTY;
  		break;
  	}
  
  	mutex_unlock(&bdev->bd_mutex);
  	return ret;
  }
  
  /**
   * blk_trace_shutdown: - stop and cleanup trace structures
   * @q:    the request queue associated with the device
   *
   **/
165125e1e   Jens Axboe   [BLOCK] Get rid o...
647
  void blk_trace_shutdown(struct request_queue *q)
2056a782f   Jens Axboe   [PATCH] Block que...
648
  {
6c5c93415   Alexey Dobriyan   [PATCH] ifdef blk...
649
650
651
652
  	if (q->blk_trace) {
  		blk_trace_startstop(q, 0);
  		blk_trace_remove(q);
  	}
2056a782f   Jens Axboe   [PATCH] Block que...
653
  }
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
  
  /*
   * blktrace probes
   */
  
  /**
   * blk_add_trace_rq - Add a trace for a request oriented action
   * @q:		queue the io is for
   * @rq:		the source request
   * @what:	the action
   *
   * Description:
   *     Records an action against a request. Will log the bio offset + size.
   *
   **/
  static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
805f6b5e1   Tao Ma   blktrace: Use rq-...
670
  			     u32 what)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
671
672
  {
  	struct blk_trace *bt = q->blk_trace;
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
673
674
675
  
  	if (likely(!bt))
  		return;
33659ebba   Christoph Hellwig   block: remove wra...
676
  	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
677
  		what |= BLK_TC_ACT(BLK_TC_PC);
805f6b5e1   Tao Ma   blktrace: Use rq-...
678
  		__blk_add_trace(bt, 0, blk_rq_bytes(rq), rq->cmd_flags,
2e46e8b27   Tejun Heo   block: drop reque...
679
  				what, rq->errors, rq->cmd_len, rq->cmd);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
680
681
  	} else  {
  		what |= BLK_TC_ACT(BLK_TC_FS);
805f6b5e1   Tao Ma   blktrace: Use rq-...
682
683
  		__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
  				rq->cmd_flags, what, rq->errors, 0, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
684
685
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
686
687
  static void blk_add_trace_rq_abort(void *ignore,
  				   struct request_queue *q, struct request *rq)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
688
689
690
  {
  	blk_add_trace_rq(q, rq, BLK_TA_ABORT);
  }
38516ab59   Steven Rostedt   tracing: Let trac...
691
692
  static void blk_add_trace_rq_insert(void *ignore,
  				    struct request_queue *q, struct request *rq)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
693
694
695
  {
  	blk_add_trace_rq(q, rq, BLK_TA_INSERT);
  }
38516ab59   Steven Rostedt   tracing: Let trac...
696
697
  static void blk_add_trace_rq_issue(void *ignore,
  				   struct request_queue *q, struct request *rq)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
698
699
700
  {
  	blk_add_trace_rq(q, rq, BLK_TA_ISSUE);
  }
38516ab59   Steven Rostedt   tracing: Let trac...
701
702
  static void blk_add_trace_rq_requeue(void *ignore,
  				     struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
703
  				     struct request *rq)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
704
705
706
  {
  	blk_add_trace_rq(q, rq, BLK_TA_REQUEUE);
  }
38516ab59   Steven Rostedt   tracing: Let trac...
707
708
  static void blk_add_trace_rq_complete(void *ignore,
  				      struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
709
  				      struct request *rq)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
710
711
712
713
714
715
716
717
718
  {
  	blk_add_trace_rq(q, rq, BLK_TA_COMPLETE);
  }
  
  /**
   * blk_add_trace_bio - Add a trace for a bio oriented action
   * @q:		queue the io is for
   * @bio:	the source bio
   * @what:	the action
797a455d2   Jens Axboe   block: ensure tha...
719
   * @error:	error, if any
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
720
721
722
723
724
725
   *
   * Description:
   *     Records an action against a bio. Will log the bio offset + size.
   *
   **/
  static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
797a455d2   Jens Axboe   block: ensure tha...
726
  			      u32 what, int error)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
727
728
729
730
731
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (likely(!bt))
  		return;
797a455d2   Jens Axboe   block: ensure tha...
732
733
  	if (!error && !bio_flagged(bio, BIO_UPTODATE))
  		error = EIO;
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
734
  	__blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what,
797a455d2   Jens Axboe   block: ensure tha...
735
  			error, 0, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
736
  }
38516ab59   Steven Rostedt   tracing: Let trac...
737
738
  static void blk_add_trace_bio_bounce(void *ignore,
  				     struct request_queue *q, struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
739
  {
797a455d2   Jens Axboe   block: ensure tha...
740
  	blk_add_trace_bio(q, bio, BLK_TA_BOUNCE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
741
  }
38516ab59   Steven Rostedt   tracing: Let trac...
742
  static void blk_add_trace_bio_complete(void *ignore,
23036f1a3   Mathieu Desnoyers   blktrace: add mis...
743
744
  				       struct request_queue *q, struct bio *bio,
  				       int error)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
745
  {
797a455d2   Jens Axboe   block: ensure tha...
746
  	blk_add_trace_bio(q, bio, BLK_TA_COMPLETE, error);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
747
  }
38516ab59   Steven Rostedt   tracing: Let trac...
748
749
  static void blk_add_trace_bio_backmerge(void *ignore,
  					struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
750
  					struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
751
  {
797a455d2   Jens Axboe   block: ensure tha...
752
  	blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
753
  }
38516ab59   Steven Rostedt   tracing: Let trac...
754
755
  static void blk_add_trace_bio_frontmerge(void *ignore,
  					 struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
756
  					 struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
757
  {
797a455d2   Jens Axboe   block: ensure tha...
758
  	blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
759
  }
38516ab59   Steven Rostedt   tracing: Let trac...
760
761
  static void blk_add_trace_bio_queue(void *ignore,
  				    struct request_queue *q, struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
762
  {
797a455d2   Jens Axboe   block: ensure tha...
763
  	blk_add_trace_bio(q, bio, BLK_TA_QUEUE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
764
  }
38516ab59   Steven Rostedt   tracing: Let trac...
765
766
  static void blk_add_trace_getrq(void *ignore,
  				struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
767
  				struct bio *bio, int rw)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
768
769
  {
  	if (bio)
797a455d2   Jens Axboe   block: ensure tha...
770
  		blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
771
772
773
774
775
776
777
  	else {
  		struct blk_trace *bt = q->blk_trace;
  
  		if (bt)
  			__blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL);
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
778
779
  static void blk_add_trace_sleeprq(void *ignore,
  				  struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
780
  				  struct bio *bio, int rw)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
781
782
  {
  	if (bio)
797a455d2   Jens Axboe   block: ensure tha...
783
  		blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
784
785
786
787
  	else {
  		struct blk_trace *bt = q->blk_trace;
  
  		if (bt)
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
788
789
  			__blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
  					0, 0, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
790
791
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
792
  static void blk_add_trace_plug(void *ignore, struct request_queue *q)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
793
794
795
796
797
798
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (bt)
  		__blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
  }
49cac01e1   Jens Axboe   block: make unplu...
799
800
  static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
  				    unsigned int depth, bool explicit)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
801
802
803
804
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (bt) {
94b5eb28b   Jens Axboe   block: fixup bloc...
805
  		__be64 rpdu = cpu_to_be64(depth);
49cac01e1   Jens Axboe   block: make unplu...
806
  		u32 what;
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
807

49cac01e1   Jens Axboe   block: make unplu...
808
809
810
811
812
813
  		if (explicit)
  			what = BLK_TA_UNPLUG_IO;
  		else
  			what = BLK_TA_UNPLUG_TIMER;
  
  		__blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
814
815
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
816
817
  static void blk_add_trace_split(void *ignore,
  				struct request_queue *q, struct bio *bio,
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
  				unsigned int pdu)
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (bt) {
  		__be64 rpdu = cpu_to_be64(pdu);
  
  		__blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw,
  				BLK_TA_SPLIT, !bio_flagged(bio, BIO_UPTODATE),
  				sizeof(rpdu), &rpdu);
  	}
  }
  
  /**
d07335e51   Mike Snitzer   block: Rename "bl...
832
   * blk_add_trace_bio_remap - Add a trace for a bio-remap operation
546cf44a1   Randy Dunlap   blktrace: Fix new...
833
   * @ignore:	trace callback data parameter (not used)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
834
835
836
   * @q:		queue the io is for
   * @bio:	the source bio
   * @dev:	target device
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
837
   * @from:	source sector
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
838
839
840
841
842
843
   *
   * Description:
   *     Device mapper or raid target sometimes need to split a bio because
   *     it spans a stripe (or similar). Add a trace for that action.
   *
   **/
d07335e51   Mike Snitzer   block: Rename "bl...
844
845
846
  static void blk_add_trace_bio_remap(void *ignore,
  				    struct request_queue *q, struct bio *bio,
  				    dev_t dev, sector_t from)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
847
848
849
850
851
852
  {
  	struct blk_trace *bt = q->blk_trace;
  	struct blk_io_trace_remap r;
  
  	if (likely(!bt))
  		return;
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
853
854
855
  	r.device_from = cpu_to_be32(dev);
  	r.device_to   = cpu_to_be32(bio->bi_bdev->bd_dev);
  	r.sector_from = cpu_to_be64(from);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
856

22a7c31a9   Alan D. Brunelle   blktrace: from-se...
857
858
859
  	__blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw,
  			BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE),
  			sizeof(r), &r);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
860
861
862
  }
  
  /**
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
863
   * blk_add_trace_rq_remap - Add a trace for a request-remap operation
546cf44a1   Randy Dunlap   blktrace: Fix new...
864
   * @ignore:	trace callback data parameter (not used)
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
865
866
867
868
869
870
871
872
873
874
   * @q:		queue the io is for
   * @rq:		the source request
   * @dev:	target device
   * @from:	source sector
   *
   * Description:
   *     Device mapper remaps request to other devices.
   *     Add a trace for that action.
   *
   **/
38516ab59   Steven Rostedt   tracing: Let trac...
875
876
  static void blk_add_trace_rq_remap(void *ignore,
  				   struct request_queue *q,
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
  				   struct request *rq, dev_t dev,
  				   sector_t from)
  {
  	struct blk_trace *bt = q->blk_trace;
  	struct blk_io_trace_remap r;
  
  	if (likely(!bt))
  		return;
  
  	r.device_from = cpu_to_be32(dev);
  	r.device_to   = cpu_to_be32(disk_devt(rq->rq_disk));
  	r.sector_from = cpu_to_be64(from);
  
  	__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
  			rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors,
  			sizeof(r), &r);
  }
  
  /**
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
   * blk_add_driver_data - Add binary message with driver-specific data
   * @q:		queue the io is for
   * @rq:		io request
   * @data:	driver-specific data
   * @len:	length of driver-specific data
   *
   * Description:
   *     Some drivers might want to write driver-specific data per request.
   *
   **/
  void blk_add_driver_data(struct request_queue *q,
  			 struct request *rq,
  			 void *data, size_t len)
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (likely(!bt))
  		return;
33659ebba   Christoph Hellwig   block: remove wra...
914
  	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
2e46e8b27   Tejun Heo   block: drop reque...
915
916
  		__blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
  				BLK_TA_DRV_DATA, rq->errors, len, data);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
917
  	else
2e46e8b27   Tejun Heo   block: drop reque...
918
919
  		__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
  				BLK_TA_DRV_DATA, rq->errors, len, data);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
920
921
  }
  EXPORT_SYMBOL_GPL(blk_add_driver_data);
3c289ba7c   Li Zefan   blktrace: remove ...
922
  static void blk_register_tracepoints(void)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
923
924
  {
  	int ret;
38516ab59   Steven Rostedt   tracing: Let trac...
925
  	ret = register_trace_block_rq_abort(blk_add_trace_rq_abort, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
926
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
927
  	ret = register_trace_block_rq_insert(blk_add_trace_rq_insert, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
928
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
929
  	ret = register_trace_block_rq_issue(blk_add_trace_rq_issue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
930
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
931
  	ret = register_trace_block_rq_requeue(blk_add_trace_rq_requeue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
932
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
933
  	ret = register_trace_block_rq_complete(blk_add_trace_rq_complete, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
934
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
935
  	ret = register_trace_block_bio_bounce(blk_add_trace_bio_bounce, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
936
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
937
  	ret = register_trace_block_bio_complete(blk_add_trace_bio_complete, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
938
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
939
  	ret = register_trace_block_bio_backmerge(blk_add_trace_bio_backmerge, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
940
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
941
  	ret = register_trace_block_bio_frontmerge(blk_add_trace_bio_frontmerge, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
942
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
943
  	ret = register_trace_block_bio_queue(blk_add_trace_bio_queue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
944
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
945
  	ret = register_trace_block_getrq(blk_add_trace_getrq, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
946
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
947
  	ret = register_trace_block_sleeprq(blk_add_trace_sleeprq, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
948
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
949
  	ret = register_trace_block_plug(blk_add_trace_plug, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
950
  	WARN_ON(ret);
49cac01e1   Jens Axboe   block: make unplu...
951
  	ret = register_trace_block_unplug(blk_add_trace_unplug, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
952
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
953
  	ret = register_trace_block_split(blk_add_trace_split, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
954
  	WARN_ON(ret);
d07335e51   Mike Snitzer   block: Rename "bl...
955
  	ret = register_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
956
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
957
  	ret = register_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
958
  	WARN_ON(ret);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
959
960
961
962
  }
  
  static void blk_unregister_tracepoints(void)
  {
38516ab59   Steven Rostedt   tracing: Let trac...
963
  	unregister_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
d07335e51   Mike Snitzer   block: Rename "bl...
964
  	unregister_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
38516ab59   Steven Rostedt   tracing: Let trac...
965
  	unregister_trace_block_split(blk_add_trace_split, NULL);
49cac01e1   Jens Axboe   block: make unplu...
966
  	unregister_trace_block_unplug(blk_add_trace_unplug, NULL);
38516ab59   Steven Rostedt   tracing: Let trac...
967
968
969
970
971
972
973
974
975
976
977
978
979
  	unregister_trace_block_plug(blk_add_trace_plug, NULL);
  	unregister_trace_block_sleeprq(blk_add_trace_sleeprq, NULL);
  	unregister_trace_block_getrq(blk_add_trace_getrq, NULL);
  	unregister_trace_block_bio_queue(blk_add_trace_bio_queue, NULL);
  	unregister_trace_block_bio_frontmerge(blk_add_trace_bio_frontmerge, NULL);
  	unregister_trace_block_bio_backmerge(blk_add_trace_bio_backmerge, NULL);
  	unregister_trace_block_bio_complete(blk_add_trace_bio_complete, NULL);
  	unregister_trace_block_bio_bounce(blk_add_trace_bio_bounce, NULL);
  	unregister_trace_block_rq_complete(blk_add_trace_rq_complete, NULL);
  	unregister_trace_block_rq_requeue(blk_add_trace_rq_requeue, NULL);
  	unregister_trace_block_rq_issue(blk_add_trace_rq_issue, NULL);
  	unregister_trace_block_rq_insert(blk_add_trace_rq_insert, NULL);
  	unregister_trace_block_rq_abort(blk_add_trace_rq_abort, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
980
981
982
  
  	tracepoint_synchronize_unregister();
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
983
984
985
986
987
988
989
  
  /*
   * struct blk_io_tracer formatting routines
   */
  
  static void fill_rwbs(char *rwbs, const struct blk_io_trace *t)
  {
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
990
  	int i = 0;
65796348e   Li Zefan   blktrace: fix wro...
991
  	int tc = t->action >> BLK_TC_SHIFT;
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
992

18cea4591   Li Zefan   blktrace: print o...
993
994
995
996
  	if (t->action == BLK_TN_MESSAGE) {
  		rwbs[i++] = 'N';
  		goto out;
  	}
c09c47cae   Namhyung Kim   blktrace: add FLU...
997
998
  	if (tc & BLK_TC_FLUSH)
  		rwbs[i++] = 'F';
65796348e   Li Zefan   blktrace: fix wro...
999
  	if (tc & BLK_TC_DISCARD)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1000
  		rwbs[i++] = 'D';
65796348e   Li Zefan   blktrace: fix wro...
1001
  	else if (tc & BLK_TC_WRITE)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1002
1003
1004
1005
1006
  		rwbs[i++] = 'W';
  	else if (t->bytes)
  		rwbs[i++] = 'R';
  	else
  		rwbs[i++] = 'N';
c09c47cae   Namhyung Kim   blktrace: add FLU...
1007
1008
  	if (tc & BLK_TC_FUA)
  		rwbs[i++] = 'F';
65796348e   Li Zefan   blktrace: fix wro...
1009
  	if (tc & BLK_TC_AHEAD)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1010
  		rwbs[i++] = 'A';
65796348e   Li Zefan   blktrace: fix wro...
1011
  	if (tc & BLK_TC_SYNC)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1012
  		rwbs[i++] = 'S';
65796348e   Li Zefan   blktrace: fix wro...
1013
  	if (tc & BLK_TC_META)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1014
  		rwbs[i++] = 'M';
18cea4591   Li Zefan   blktrace: print o...
1015
  out:
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1016
  	rwbs[i] = '\0';
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  }
  
  static inline
  const struct blk_io_trace *te_blk_io_trace(const struct trace_entry *ent)
  {
  	return (const struct blk_io_trace *)ent;
  }
  
  static inline const void *pdu_start(const struct trace_entry *ent)
  {
  	return te_blk_io_trace(ent) + 1;
  }
66de7792c   Li Zefan   blktrace: fix out...
1029
1030
1031
1032
1033
1034
1035
1036
1037
  static inline u32 t_action(const struct trace_entry *ent)
  {
  	return te_blk_io_trace(ent)->action;
  }
  
  static inline u32 t_bytes(const struct trace_entry *ent)
  {
  	return te_blk_io_trace(ent)->bytes;
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  static inline u32 t_sec(const struct trace_entry *ent)
  {
  	return te_blk_io_trace(ent)->bytes >> 9;
  }
  
  static inline unsigned long long t_sector(const struct trace_entry *ent)
  {
  	return te_blk_io_trace(ent)->sector;
  }
  
  static inline __u16 t_error(const struct trace_entry *ent)
  {
e0dc81bec   Li Zefan   blktrace: fix t_e...
1050
  	return te_blk_io_trace(ent)->error;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
  }
  
  static __u64 get_pdu_int(const struct trace_entry *ent)
  {
  	const __u64 *val = pdu_start(ent);
  	return be64_to_cpu(*val);
  }
  
  static void get_pdu_remap(const struct trace_entry *ent,
  			  struct blk_io_trace_remap *r)
  {
  	const struct blk_io_trace_remap *__r = pdu_start(ent);
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1063
  	__u64 sector_from = __r->sector_from;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1064

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1065
  	r->device_from = be32_to_cpu(__r->device_from);
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1066
1067
  	r->device_to   = be32_to_cpu(__r->device_to);
  	r->sector_from = be64_to_cpu(sector_from);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1068
  }
b6a4b0c3a   Li Zefan   blktrace: extract...
1069
1070
1071
  typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act);
  
  static int blk_log_action_classic(struct trace_iterator *iter, const char *act)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1072
  {
c09c47cae   Namhyung Kim   blktrace: add FLU...
1073
  	char rwbs[RWBS_LEN];
35ac51bfe   Li Zefan   blktrace: make cl...
1074
1075
  	unsigned long long ts  = iter->ts;
  	unsigned long nsec_rem = do_div(ts, NSEC_PER_SEC);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1076
  	unsigned secs	       = (unsigned long)ts;
b6a4b0c3a   Li Zefan   blktrace: extract...
1077
  	const struct blk_io_trace *t = te_blk_io_trace(iter->ent);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1078
1079
1080
1081
  
  	fill_rwbs(rwbs, t);
  
  	return trace_seq_printf(&iter->seq,
35ac51bfe   Li Zefan   blktrace: make cl...
1082
  				"%3d,%-3d %2d %5d.%09lu %5u %2s %3s ",
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1083
  				MAJOR(t->device), MINOR(t->device), iter->cpu,
b6a4b0c3a   Li Zefan   blktrace: extract...
1084
  				secs, nsec_rem, iter->ent->pid, act, rwbs);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1085
  }
b6a4b0c3a   Li Zefan   blktrace: extract...
1086
  static int blk_log_action(struct trace_iterator *iter, const char *act)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1087
  {
c09c47cae   Namhyung Kim   blktrace: add FLU...
1088
  	char rwbs[RWBS_LEN];
b6a4b0c3a   Li Zefan   blktrace: extract...
1089
  	const struct blk_io_trace *t = te_blk_io_trace(iter->ent);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1090
  	fill_rwbs(rwbs, t);
b6a4b0c3a   Li Zefan   blktrace: extract...
1091
  	return trace_seq_printf(&iter->seq, "%3d,%-3d %2s %3s ",
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1092
1093
  				MAJOR(t->device), MINOR(t->device), act, rwbs);
  }
66de7792c   Li Zefan   blktrace: fix out...
1094
1095
  static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent)
  {
049862579   Li Zefan   blktrace: pdu_buf...
1096
  	const unsigned char *pdu_buf;
66de7792c   Li Zefan   blktrace: fix out...
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  	int pdu_len;
  	int i, end, ret;
  
  	pdu_buf = pdu_start(ent);
  	pdu_len = te_blk_io_trace(ent)->pdu_len;
  
  	if (!pdu_len)
  		return 1;
  
  	/* find the last zero that needs to be printed */
  	for (end = pdu_len - 1; end >= 0; end--)
  		if (pdu_buf[end])
  			break;
  	end++;
  
  	if (!trace_seq_putc(s, '('))
  		return 0;
  
  	for (i = 0; i < pdu_len; i++) {
  
  		ret = trace_seq_printf(s, "%s%02x",
  				       i == 0 ? "" : " ", pdu_buf[i]);
  		if (!ret)
  			return ret;
  
  		/*
  		 * stop when the rest is just zeroes and indicate so
  		 * with a ".." appended
  		 */
  		if (i == end && end != pdu_len - 1)
  			return trace_seq_puts(s, " ..) ");
  	}
  
  	return trace_seq_puts(s, ") ");
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1132
1133
  static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent)
  {
4ca530852   Steven Rostedt   tracing: protect ...
1134
1135
1136
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1137

66de7792c   Li Zefan   blktrace: fix out...
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  	if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
  		int ret;
  
  		ret = trace_seq_printf(s, "%u ", t_bytes(ent));
  		if (!ret)
  			return 0;
  		ret = blk_log_dump_pdu(s, ent);
  		if (!ret)
  			return 0;
  		return trace_seq_printf(s, "[%s]
  ", cmd);
  	} else {
  		if (t_sec(ent))
  			return trace_seq_printf(s, "%llu + %u [%s]
  ",
  						t_sector(ent), t_sec(ent), cmd);
  		return trace_seq_printf(s, "[%s]
  ", cmd);
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1157
  }
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1158
1159
  static int blk_log_with_error(struct trace_seq *s,
  			      const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1160
  {
66de7792c   Li Zefan   blktrace: fix out...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  	if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
  		int ret;
  
  		ret = blk_log_dump_pdu(s, ent);
  		if (ret)
  			return trace_seq_printf(s, "[%d]
  ", t_error(ent));
  		return 0;
  	} else {
  		if (t_sec(ent))
  			return trace_seq_printf(s, "%llu + %u [%d]
  ",
  						t_sector(ent),
  						t_sec(ent), t_error(ent));
  		return trace_seq_printf(s, "%llu [%d]
  ",
  					t_sector(ent), t_error(ent));
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1179
1180
1181
1182
  }
  
  static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
  {
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1183
  	struct blk_io_trace_remap r = { .device_from = 0, };
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1184
1185
1186
1187
  
  	get_pdu_remap(ent, &r);
  	return trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu
  ",
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1188
1189
1190
  				t_sector(ent), t_sec(ent),
  				MAJOR(r.device_from), MINOR(r.device_from),
  				(unsigned long long)r.sector_from);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1191
1192
1193
1194
  }
  
  static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
  {
4ca530852   Steven Rostedt   tracing: protect ...
1195
1196
1197
1198
1199
1200
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
  
  	return trace_seq_printf(s, "[%s]
  ", cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1201
1202
1203
1204
  }
  
  static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent)
  {
4ca530852   Steven Rostedt   tracing: protect ...
1205
1206
1207
1208
1209
1210
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
  
  	return trace_seq_printf(s, "[%s] %llu
  ", cmd, get_pdu_int(ent));
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1211
1212
1213
1214
  }
  
  static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent)
  {
4ca530852   Steven Rostedt   tracing: protect ...
1215
1216
1217
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1218
1219
  	return trace_seq_printf(s, "%llu / %llu [%s]
  ", t_sector(ent),
4ca530852   Steven Rostedt   tracing: protect ...
1220
  				get_pdu_int(ent), cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1221
  }
18cea4591   Li Zefan   blktrace: print o...
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  static int blk_log_msg(struct trace_seq *s, const struct trace_entry *ent)
  {
  	int ret;
  	const struct blk_io_trace *t = te_blk_io_trace(ent);
  
  	ret = trace_seq_putmem(s, t + 1, t->pdu_len);
  	if (ret)
  		return trace_seq_putc(s, '
  ');
  	return ret;
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
  /*
   * struct tracer operations
   */
  
  static void blk_tracer_print_header(struct seq_file *m)
  {
  	if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC))
  		return;
  	seq_puts(m, "# DEV   CPU TIMESTAMP     PID ACT FLG
  "
  		    "#  |     |     |           |   |   |
  ");
  }
  
  static void blk_tracer_start(struct trace_array *tr)
  {
ad5dd5493   Li Zefan   blktrace: fix mem...
1249
  	blk_tracer_enabled = true;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1250
1251
1252
1253
1254
1255
  }
  
  static int blk_tracer_init(struct trace_array *tr)
  {
  	blk_tr = tr;
  	blk_tracer_start(tr);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1256
1257
1258
1259
1260
  	return 0;
  }
  
  static void blk_tracer_stop(struct trace_array *tr)
  {
ad5dd5493   Li Zefan   blktrace: fix mem...
1261
  	blk_tracer_enabled = false;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1262
1263
1264
1265
  }
  
  static void blk_tracer_reset(struct trace_array *tr)
  {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1266
1267
  	blk_tracer_stop(tr);
  }
e4955c998   Li Zefan   blktrace: mark dd...
1268
  static const struct {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1269
  	const char *act[2];
ef18012b2   Steven Rostedt   tracing: remove f...
1270
  	int	   (*print)(struct trace_seq *s, const struct trace_entry *ent);
e4955c998   Li Zefan   blktrace: mark dd...
1271
  } what2act[] = {
ef18012b2   Steven Rostedt   tracing: remove f...
1272
  	[__BLK_TA_QUEUE]	= {{  "Q", "queue" },	   blk_log_generic },
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1273
1274
1275
1276
1277
1278
1279
1280
1281
  	[__BLK_TA_BACKMERGE]	= {{  "M", "backmerge" },  blk_log_generic },
  	[__BLK_TA_FRONTMERGE]	= {{  "F", "frontmerge" }, blk_log_generic },
  	[__BLK_TA_GETRQ]	= {{  "G", "getrq" },	   blk_log_generic },
  	[__BLK_TA_SLEEPRQ]	= {{  "S", "sleeprq" },	   blk_log_generic },
  	[__BLK_TA_REQUEUE]	= {{  "R", "requeue" },	   blk_log_with_error },
  	[__BLK_TA_ISSUE]	= {{  "D", "issue" },	   blk_log_generic },
  	[__BLK_TA_COMPLETE]	= {{  "C", "complete" },   blk_log_with_error },
  	[__BLK_TA_PLUG]		= {{  "P", "plug" },	   blk_log_plug },
  	[__BLK_TA_UNPLUG_IO]	= {{  "U", "unplug_io" },  blk_log_unplug },
49cac01e1   Jens Axboe   block: make unplu...
1282
  	[__BLK_TA_UNPLUG_TIMER]	= {{ "UT", "unplug_timer" }, blk_log_unplug },
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1283
1284
1285
1286
1287
  	[__BLK_TA_INSERT]	= {{  "I", "insert" },	   blk_log_generic },
  	[__BLK_TA_SPLIT]	= {{  "X", "split" },	   blk_log_split },
  	[__BLK_TA_BOUNCE]	= {{  "B", "bounce" },	   blk_log_generic },
  	[__BLK_TA_REMAP]	= {{  "A", "remap" },	   blk_log_remap },
  };
b6a4b0c3a   Li Zefan   blktrace: extract...
1288
1289
  static enum print_line_t print_one_line(struct trace_iterator *iter,
  					bool classic)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1290
  {
2c9b238eb   Arnaldo Carvalho de Melo   trace: Change str...
1291
  	struct trace_seq *s = &iter->seq;
b6a4b0c3a   Li Zefan   blktrace: extract...
1292
1293
  	const struct blk_io_trace *t;
  	u16 what;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1294
  	int ret;
b6a4b0c3a   Li Zefan   blktrace: extract...
1295
1296
  	bool long_act;
  	blk_log_action_t *log_action;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1297

b6a4b0c3a   Li Zefan   blktrace: extract...
1298
1299
1300
1301
  	t	   = te_blk_io_trace(iter->ent);
  	what	   = t->action & ((1 << BLK_TC_SHIFT) - 1);
  	long_act   = !!(trace_flags & TRACE_ITER_VERBOSE);
  	log_action = classic ? &blk_log_action_classic : &blk_log_action;
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1302

18cea4591   Li Zefan   blktrace: print o...
1303
1304
1305
1306
1307
1308
  	if (t->action == BLK_TN_MESSAGE) {
  		ret = log_action(iter, long_act ? "message" : "m");
  		if (ret)
  			ret = blk_log_msg(s, iter->ent);
  		goto out;
  	}
eb08f8eb0   Li Zefan   blktrace: fix off...
1309
  	if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act)))
b78825d60   Li Zefan   blktrace: fix out...
1310
1311
  		ret = trace_seq_printf(s, "Unknown action %x
  ", what);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1312
  	else {
b6a4b0c3a   Li Zefan   blktrace: extract...
1313
  		ret = log_action(iter, what2act[what].act[long_act]);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1314
  		if (ret)
2c9b238eb   Arnaldo Carvalho de Melo   trace: Change str...
1315
  			ret = what2act[what].print(s, iter->ent);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1316
  	}
18cea4591   Li Zefan   blktrace: print o...
1317
  out:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1318
1319
  	return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
  }
b6a4b0c3a   Li Zefan   blktrace: extract...
1320
  static enum print_line_t blk_trace_event_print(struct trace_iterator *iter,
a9a577638   Steven Rostedt   tracing: Allow ev...
1321
  					       int flags, struct trace_event *event)
b6a4b0c3a   Li Zefan   blktrace: extract...
1322
  {
b6a4b0c3a   Li Zefan   blktrace: extract...
1323
1324
  	return print_one_line(iter, false);
  }
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1325
1326
1327
1328
1329
1330
1331
  static int blk_trace_synthesize_old_trace(struct trace_iterator *iter)
  {
  	struct trace_seq *s = &iter->seq;
  	struct blk_io_trace *t = (struct blk_io_trace *)iter->ent;
  	const int offset = offsetof(struct blk_io_trace, sector);
  	struct blk_io_trace old = {
  		.magic	  = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION,
6c051ce03   Li Zefan   blktrace: fix tim...
1332
  		.time     = iter->ts,
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1333
1334
1335
1336
1337
1338
1339
  	};
  
  	if (!trace_seq_putmem(s, &old, offset))
  		return 0;
  	return trace_seq_putmem(s, &t->sector,
  				sizeof(old) - offset + t->pdu_len);
  }
ae7462b4f   Arnaldo Carvalho de Melo   trace: make the t...
1340
  static enum print_line_t
a9a577638   Steven Rostedt   tracing: Allow ev...
1341
1342
  blk_trace_event_print_binary(struct trace_iterator *iter, int flags,
  			     struct trace_event *event)
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1343
1344
1345
1346
  {
  	return blk_trace_synthesize_old_trace(iter) ?
  			TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1347
1348
  static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter)
  {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1349
1350
  	if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC))
  		return TRACE_TYPE_UNHANDLED;
b6a4b0c3a   Li Zefan   blktrace: extract...
1351
  	return print_one_line(iter, true);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1352
  }
f3948f885   Li Zefan   blktrace: fix con...
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
  static int blk_tracer_set_flag(u32 old_flags, u32 bit, int set)
  {
  	/* don't output context-info for blk_classic output */
  	if (bit == TRACE_BLK_OPT_CLASSIC) {
  		if (set)
  			trace_flags &= ~TRACE_ITER_CONTEXT_INFO;
  		else
  			trace_flags |= TRACE_ITER_CONTEXT_INFO;
  	}
  	return 0;
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1364
1365
1366
1367
1368
1369
1370
1371
1372
  static struct tracer blk_tracer __read_mostly = {
  	.name		= "blk",
  	.init		= blk_tracer_init,
  	.reset		= blk_tracer_reset,
  	.start		= blk_tracer_start,
  	.stop		= blk_tracer_stop,
  	.print_header	= blk_tracer_print_header,
  	.print_line	= blk_tracer_print_line,
  	.flags		= &blk_tracer_flags,
f3948f885   Li Zefan   blktrace: fix con...
1373
  	.set_flag	= blk_tracer_set_flag,
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1374
  };
a9a577638   Steven Rostedt   tracing: Allow ev...
1375
  static struct trace_event_functions trace_blk_event_funcs = {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1376
  	.trace		= blk_trace_event_print,
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1377
  	.binary		= blk_trace_event_print_binary,
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1378
  };
a9a577638   Steven Rostedt   tracing: Allow ev...
1379
1380
1381
1382
  static struct trace_event trace_blk_event = {
  	.type		= TRACE_BLK,
  	.funcs		= &trace_blk_event_funcs,
  };
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  static int __init init_blk_tracer(void)
  {
  	if (!register_ftrace_event(&trace_blk_event)) {
  		pr_warning("Warning: could not register block events
  ");
  		return 1;
  	}
  
  	if (register_tracer(&blk_tracer) != 0) {
  		pr_warning("Warning: could not register the block tracer
  ");
  		unregister_ftrace_event(&trace_blk_event);
  		return 1;
  	}
  
  	return 0;
  }
  
  device_initcall(init_blk_tracer);
  
  static int blk_trace_remove_queue(struct request_queue *q)
  {
  	struct blk_trace *bt;
  
  	bt = xchg(&q->blk_trace, NULL);
  	if (bt == NULL)
  		return -EINVAL;
17ba97e34   Li Zefan   blktrace: fix blk...
1410
1411
  	if (atomic_dec_and_test(&blk_probes_ref))
  		blk_unregister_tracepoints();
ad5dd5493   Li Zefan   blktrace: fix mem...
1412
  	blk_trace_free(bt);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1413
1414
1415
1416
1417
1418
  	return 0;
  }
  
  /*
   * Setup everything required to start tracing
   */
9908c3099   Li Zefan   blktrace: support...
1419
1420
  static int blk_trace_setup_queue(struct request_queue *q,
  				 struct block_device *bdev)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1421
1422
  {
  	struct blk_trace *old_bt, *bt = NULL;
18cea4591   Li Zefan   blktrace: print o...
1423
  	int ret = -ENOMEM;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1424

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1425
1426
  	bt = kzalloc(sizeof(*bt), GFP_KERNEL);
  	if (!bt)
15152e448   Li Zefan   blktrace: report ...
1427
  		return -ENOMEM;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1428

18cea4591   Li Zefan   blktrace: print o...
1429
1430
1431
  	bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char));
  	if (!bt->msg_data)
  		goto free_bt;
9908c3099   Li Zefan   blktrace: support...
1432
  	bt->dev = bdev->bd_dev;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1433
  	bt->act_mask = (u16)-1;
9908c3099   Li Zefan   blktrace: support...
1434
1435
  
  	blk_trace_setup_lba(bt, bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1436
1437
1438
1439
  
  	old_bt = xchg(&q->blk_trace, bt);
  	if (old_bt != NULL) {
  		(void)xchg(&q->blk_trace, old_bt);
18cea4591   Li Zefan   blktrace: print o...
1440
1441
  		ret = -EBUSY;
  		goto free_bt;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1442
  	}
15152e448   Li Zefan   blktrace: report ...
1443

17ba97e34   Li Zefan   blktrace: fix blk...
1444
1445
  	if (atomic_inc_return(&blk_probes_ref) == 1)
  		blk_register_tracepoints();
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1446
  	return 0;
18cea4591   Li Zefan   blktrace: print o...
1447
1448
1449
1450
  
  free_bt:
  	blk_trace_free(bt);
  	return ret;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1451
1452
1453
1454
1455
  }
  
  /*
   * sysfs interface to enable and configure tracing
   */
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
  static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
  					 struct device_attribute *attr,
  					 char *buf);
  static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
  					  struct device_attribute *attr,
  					  const char *buf, size_t count);
  #define BLK_TRACE_DEVICE_ATTR(_name) \
  	DEVICE_ATTR(_name, S_IRUGO | S_IWUSR, \
  		    sysfs_blk_trace_attr_show, \
  		    sysfs_blk_trace_attr_store)
cd649b8bb   Li Zefan   blktrace: remove ...
1466
  static BLK_TRACE_DEVICE_ATTR(enable);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
  static BLK_TRACE_DEVICE_ATTR(act_mask);
  static BLK_TRACE_DEVICE_ATTR(pid);
  static BLK_TRACE_DEVICE_ATTR(start_lba);
  static BLK_TRACE_DEVICE_ATTR(end_lba);
  
  static struct attribute *blk_trace_attrs[] = {
  	&dev_attr_enable.attr,
  	&dev_attr_act_mask.attr,
  	&dev_attr_pid.attr,
  	&dev_attr_start_lba.attr,
  	&dev_attr_end_lba.attr,
  	NULL
  };
  
  struct attribute_group blk_trace_attr_group = {
  	.name  = "trace",
  	.attrs = blk_trace_attrs,
  };
093419971   Li Zefan   blktrace: print h...
1485
1486
1487
1488
1489
1490
  static const struct {
  	int mask;
  	const char *str;
  } mask_maps[] = {
  	{ BLK_TC_READ,		"read"		},
  	{ BLK_TC_WRITE,		"write"		},
c09c47cae   Namhyung Kim   blktrace: add FLU...
1491
  	{ BLK_TC_FLUSH,		"flush"		},
093419971   Li Zefan   blktrace: print h...
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  	{ BLK_TC_SYNC,		"sync"		},
  	{ BLK_TC_QUEUE,		"queue"		},
  	{ BLK_TC_REQUEUE,	"requeue"	},
  	{ BLK_TC_ISSUE,		"issue"		},
  	{ BLK_TC_COMPLETE,	"complete"	},
  	{ BLK_TC_FS,		"fs"		},
  	{ BLK_TC_PC,		"pc"		},
  	{ BLK_TC_AHEAD,		"ahead"		},
  	{ BLK_TC_META,		"meta"		},
  	{ BLK_TC_DISCARD,	"discard"	},
  	{ BLK_TC_DRV_DATA,	"drv_data"	},
c09c47cae   Namhyung Kim   blktrace: add FLU...
1503
  	{ BLK_TC_FUA,		"fua"		},
093419971   Li Zefan   blktrace: print h...
1504
1505
1506
  };
  
  static int blk_trace_str2mask(const char *str)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1507
  {
093419971   Li Zefan   blktrace: print h...
1508
  	int i;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1509
  	int mask = 0;
9eb85125c   Li Zefan   blktrace: pass th...
1510
  	char *buf, *s, *token;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1511

9eb85125c   Li Zefan   blktrace: pass th...
1512
1513
  	buf = kstrdup(str, GFP_KERNEL);
  	if (buf == NULL)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1514
  		return -ENOMEM;
9eb85125c   Li Zefan   blktrace: pass th...
1515
  	s = strstrip(buf);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1516
1517
  
  	while (1) {
093419971   Li Zefan   blktrace: print h...
1518
1519
  		token = strsep(&s, ",");
  		if (token == NULL)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1520
  			break;
093419971   Li Zefan   blktrace: print h...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
  		if (*token == '\0')
  			continue;
  
  		for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
  			if (strcasecmp(token, mask_maps[i].str) == 0) {
  				mask |= mask_maps[i].mask;
  				break;
  			}
  		}
  		if (i == ARRAY_SIZE(mask_maps)) {
  			mask = -EINVAL;
  			break;
  		}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1534
  	}
9eb85125c   Li Zefan   blktrace: pass th...
1535
  	kfree(buf);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1536
1537
1538
  
  	return mask;
  }
093419971   Li Zefan   blktrace: print h...
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
  static ssize_t blk_trace_mask2str(char *buf, int mask)
  {
  	int i;
  	char *p = buf;
  
  	for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
  		if (mask & mask_maps[i].mask) {
  			p += sprintf(p, "%s%s",
  				    (p == buf) ? "" : ",", mask_maps[i].str);
  		}
  	}
  	*p++ = '
  ';
  
  	return p - buf;
  }
b125130b2   Li Zefan   blktrace: avoid a...
1555
1556
1557
1558
1559
1560
1561
  static struct request_queue *blk_trace_get_queue(struct block_device *bdev)
  {
  	if (bdev->bd_disk == NULL)
  		return NULL;
  
  	return bdev_get_queue(bdev);
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1562
1563
1564
1565
1566
1567
1568
1569
  static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
  					 struct device_attribute *attr,
  					 char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  	struct request_queue *q;
  	struct block_device *bdev;
  	ssize_t ret = -ENXIO;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1570
1571
  	bdev = bdget(part_devt(p));
  	if (bdev == NULL)
01b284f9b   Arnd Bergmann   blktrace: remove ...
1572
  		goto out;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1573

b125130b2   Li Zefan   blktrace: avoid a...
1574
  	q = blk_trace_get_queue(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1575
1576
  	if (q == NULL)
  		goto out_bdput;
b125130b2   Li Zefan   blktrace: avoid a...
1577

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1578
  	mutex_lock(&bdev->bd_mutex);
cd649b8bb   Li Zefan   blktrace: remove ...
1579
1580
1581
1582
1583
1584
  
  	if (attr == &dev_attr_enable) {
  		ret = sprintf(buf, "%u
  ", !!q->blk_trace);
  		goto out_unlock_bdev;
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1585
1586
1587
1588
  	if (q->blk_trace == NULL)
  		ret = sprintf(buf, "disabled
  ");
  	else if (attr == &dev_attr_act_mask)
093419971   Li Zefan   blktrace: print h...
1589
  		ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1590
1591
1592
1593
1594
1595
1596
1597
1598
  	else if (attr == &dev_attr_pid)
  		ret = sprintf(buf, "%u
  ", q->blk_trace->pid);
  	else if (attr == &dev_attr_start_lba)
  		ret = sprintf(buf, "%llu
  ", q->blk_trace->start_lba);
  	else if (attr == &dev_attr_end_lba)
  		ret = sprintf(buf, "%llu
  ", q->blk_trace->end_lba);
cd649b8bb   Li Zefan   blktrace: remove ...
1599
1600
  
  out_unlock_bdev:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1601
1602
1603
  	mutex_unlock(&bdev->bd_mutex);
  out_bdput:
  	bdput(bdev);
01b284f9b   Arnd Bergmann   blktrace: remove ...
1604
  out:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
  	return ret;
  }
  
  static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
  					  struct device_attribute *attr,
  					  const char *buf, size_t count)
  {
  	struct block_device *bdev;
  	struct request_queue *q;
  	struct hd_struct *p;
  	u64 value;
093419971   Li Zefan   blktrace: print h...
1616
  	ssize_t ret = -EINVAL;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1617
1618
1619
1620
1621
1622
1623
  
  	if (count == 0)
  		goto out;
  
  	if (attr == &dev_attr_act_mask) {
  		if (sscanf(buf, "%llx", &value) != 1) {
  			/* Assume it is a list of trace category names */
093419971   Li Zefan   blktrace: print h...
1624
1625
  			ret = blk_trace_str2mask(buf);
  			if (ret < 0)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1626
  				goto out;
093419971   Li Zefan   blktrace: print h...
1627
  			value = ret;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1628
1629
1630
  		}
  	} else if (sscanf(buf, "%llu", &value) != 1)
  		goto out;
093419971   Li Zefan   blktrace: print h...
1631
  	ret = -ENXIO;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1632
1633
1634
  	p = dev_to_part(dev);
  	bdev = bdget(part_devt(p));
  	if (bdev == NULL)
01b284f9b   Arnd Bergmann   blktrace: remove ...
1635
  		goto out;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1636

b125130b2   Li Zefan   blktrace: avoid a...
1637
  	q = blk_trace_get_queue(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1638
1639
1640
1641
  	if (q == NULL)
  		goto out_bdput;
  
  	mutex_lock(&bdev->bd_mutex);
cd649b8bb   Li Zefan   blktrace: remove ...
1642
1643
1644
  
  	if (attr == &dev_attr_enable) {
  		if (value)
9908c3099   Li Zefan   blktrace: support...
1645
  			ret = blk_trace_setup_queue(q, bdev);
cd649b8bb   Li Zefan   blktrace: remove ...
1646
1647
1648
1649
  		else
  			ret = blk_trace_remove_queue(q);
  		goto out_unlock_bdev;
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1650
1651
  	ret = 0;
  	if (q->blk_trace == NULL)
9908c3099   Li Zefan   blktrace: support...
1652
  		ret = blk_trace_setup_queue(q, bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  
  	if (ret == 0) {
  		if (attr == &dev_attr_act_mask)
  			q->blk_trace->act_mask = value;
  		else if (attr == &dev_attr_pid)
  			q->blk_trace->pid = value;
  		else if (attr == &dev_attr_start_lba)
  			q->blk_trace->start_lba = value;
  		else if (attr == &dev_attr_end_lba)
  			q->blk_trace->end_lba = value;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1663
  	}
cd649b8bb   Li Zefan   blktrace: remove ...
1664
1665
  
  out_unlock_bdev:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1666
1667
1668
  	mutex_unlock(&bdev->bd_mutex);
  out_bdput:
  	bdput(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1669
  out:
cd649b8bb   Li Zefan   blktrace: remove ...
1670
  	return ret ? ret : count;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1671
  }
cd649b8bb   Li Zefan   blktrace: remove ...
1672

1d54ad6da   Li Zefan   blktrace: add tra...
1673
1674
1675
1676
  int blk_trace_init_sysfs(struct device *dev)
  {
  	return sysfs_create_group(&dev->kobj, &blk_trace_attr_group);
  }
48c0d4d4c   Zdenek Kabelac   Add missing blk_t...
1677
1678
1679
1680
  void blk_trace_remove_sysfs(struct device *dev)
  {
  	sysfs_remove_group(&dev->kobj, &blk_trace_attr_group);
  }
55782138e   Li Zefan   tracing/events: c...
1681
1682
1683
1684
1685
1686
1687
1688
1689
  #endif /* CONFIG_BLK_DEV_IO_TRACE */
  
  #ifdef CONFIG_EVENT_TRACING
  
  void blk_dump_cmd(char *buf, struct request *rq)
  {
  	int i, end;
  	int len = rq->cmd_len;
  	unsigned char *cmd = rq->cmd;
33659ebba   Christoph Hellwig   block: remove wra...
1690
  	if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
55782138e   Li Zefan   tracing/events: c...
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
  		buf[0] = '\0';
  		return;
  	}
  
  	for (end = len - 1; end >= 0; end--)
  		if (cmd[end])
  			break;
  	end++;
  
  	for (i = 0; i < len; i++) {
  		buf += sprintf(buf, "%s%02x", i == 0 ? "" : " ", cmd[i]);
  		if (i == end && end != len - 1) {
  			sprintf(buf, " ..");
  			break;
  		}
  	}
  }
  
  void blk_fill_rwbs(char *rwbs, u32 rw, int bytes)
  {
  	int i = 0;
c09c47cae   Namhyung Kim   blktrace: add FLU...
1712
1713
  	if (rw & REQ_FLUSH)
  		rwbs[i++] = 'F';
55782138e   Li Zefan   tracing/events: c...
1714
1715
  	if (rw & WRITE)
  		rwbs[i++] = 'W';
7b6d91dae   Christoph Hellwig   block: unify flag...
1716
  	else if (rw & REQ_DISCARD)
55782138e   Li Zefan   tracing/events: c...
1717
1718
1719
1720
1721
  		rwbs[i++] = 'D';
  	else if (bytes)
  		rwbs[i++] = 'R';
  	else
  		rwbs[i++] = 'N';
c09c47cae   Namhyung Kim   blktrace: add FLU...
1722
1723
  	if (rw & REQ_FUA)
  		rwbs[i++] = 'F';
7b6d91dae   Christoph Hellwig   block: unify flag...
1724
  	if (rw & REQ_RAHEAD)
55782138e   Li Zefan   tracing/events: c...
1725
  		rwbs[i++] = 'A';
7b6d91dae   Christoph Hellwig   block: unify flag...
1726
  	if (rw & REQ_SYNC)
55782138e   Li Zefan   tracing/events: c...
1727
  		rwbs[i++] = 'S';
7b6d91dae   Christoph Hellwig   block: unify flag...
1728
  	if (rw & REQ_META)
55782138e   Li Zefan   tracing/events: c...
1729
  		rwbs[i++] = 'M';
8d57a98cc   Adrian Hunter   block: add secure...
1730
1731
  	if (rw & REQ_SECURE)
  		rwbs[i++] = 'E';
55782138e   Li Zefan   tracing/events: c...
1732
1733
1734
  
  	rwbs[i] = '\0';
  }
55782138e   Li Zefan   tracing/events: c...
1735
  #endif /* CONFIG_EVENT_TRACING */