Blame view

kernel/trace/blktrace.c 42.3 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>
a404d5576   Jan Kara   blktrace: Send BL...
29
  #include <linux/list.h>
55782138e   Li Zefan   tracing/events: c...
30
31
  
  #include <trace/events/block.h>
2db270a80   Frederic Weisbecker   tracing/blktrace:...
32
  #include "trace_output.h"
2056a782f   Jens Axboe   [PATCH] Block que...
33

55782138e   Li Zefan   tracing/events: c...
34
  #ifdef CONFIG_BLK_DEV_IO_TRACE
2056a782f   Jens Axboe   [PATCH] Block que...
35
  static unsigned int blktrace_seq __read_mostly = 1;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
36
  static struct trace_array *blk_tr;
5006ea73f   Li Zefan   blktrace: make bl...
37
  static bool blk_tracer_enabled __read_mostly;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
38

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

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
83
84
  	if (!bt->rchan)
  		return;
be1c63411   Olaf Kirch   [PATCH] blktrace:...
85
  	t = relay_reserve(bt->rchan, sizeof(*t) + len);
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
86
  	if (t) {
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
87
  		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
2997c8c4a   Ingo Molnar   block: fix blktra...
88
  		t->time = ktime_to_ns(ktime_get());
18cea4591   Li Zefan   blktrace: print o...
89
  record_it:
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
90
91
92
93
94
95
  		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...
96
97
  
  		if (blk_tracer)
e77405ad8   Steven Rostedt   tracing: pass aro...
98
  			trace_buffer_unlock_commit(buffer, event, 0, pc);
d3d9d2a5e   Jens Axboe   [PATCH] blktrace:...
99
  	}
be1c63411   Olaf Kirch   [PATCH] blktrace:...
100
101
102
  }
  
  /*
2056a782f   Jens Axboe   [PATCH] Block que...
103
104
105
   * Send out a notify for this process, if we haven't done so since a trace
   * started
   */
a404d5576   Jan Kara   blktrace: Send BL...
106
  static void trace_note_tsk(struct task_struct *tsk)
2056a782f   Jens Axboe   [PATCH] Block que...
107
  {
a404d5576   Jan Kara   blktrace: Send BL...
108
109
  	unsigned long flags;
  	struct blk_trace *bt;
a863055b1   Jens Axboe   [PATCH] blktrace:...
110
  	tsk->btrace_seq = blktrace_seq;
a404d5576   Jan Kara   blktrace: Send BL...
111
112
113
114
115
116
  	spin_lock_irqsave(&running_trace_lock, flags);
  	list_for_each_entry(bt, &running_trace_list, running_list) {
  		trace_note(bt, tsk->pid, BLK_TN_PROCESS, tsk->comm,
  			   sizeof(tsk->comm));
  	}
  	spin_unlock_irqrestore(&running_trace_lock, flags);
be1c63411   Olaf Kirch   [PATCH] blktrace:...
117
  }
2056a782f   Jens Axboe   [PATCH] Block que...
118

be1c63411   Olaf Kirch   [PATCH] blktrace:...
119
120
121
122
123
124
125
126
127
128
129
130
131
  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...
132
  }
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
133
134
135
136
  void __trace_note_message(struct blk_trace *bt, const char *fmt, ...)
  {
  	int n;
  	va_list args;
14a73f547   Carl Henrik Lunde   block: disable IR...
137
  	unsigned long flags;
64565911c   Jens Axboe   block: make blktr...
138
  	char *buf;
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
139

18cea4591   Li Zefan   blktrace: print o...
140
141
  	if (unlikely(bt->trace_state != Blktrace_running &&
  		     !blk_tracer_enabled))
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
142
  		return;
490da40d8   Tao Ma   blktrace: Don't o...
143
144
145
146
147
148
  	/*
  	 * 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...
149
  	local_irq_save(flags);
d8a0349c0   Shan Wei   tracing: Use this...
150
  	buf = this_cpu_ptr(bt->msg_data);
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
151
  	va_start(args, fmt);
64565911c   Jens Axboe   block: make blktr...
152
  	n = vscnprintf(buf, BLK_TN_MAX_MSG, fmt, args);
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
153
  	va_end(args);
64565911c   Jens Axboe   block: make blktr...
154
  	trace_note(bt, 0, BLK_TN_MESSAGE, buf, n);
14a73f547   Carl Henrik Lunde   block: disable IR...
155
  	local_irq_restore(flags);
9d5f09a42   Alan D. Brunelle   Added in MESSAGE ...
156
157
  }
  EXPORT_SYMBOL_GPL(__trace_note_message);
2056a782f   Jens Axboe   [PATCH] Block que...
158
159
160
161
162
  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...
163
  	if (sector && (sector < bt->start_lba || sector > bt->end_lba))
2056a782f   Jens Axboe   [PATCH] Block que...
164
165
166
167
168
169
170
171
172
173
  		return 1;
  	if (bt->pid && pid != bt->pid)
  		return 1;
  
  	return 0;
  }
  
  /*
   * Data direction bit lookup
   */
e4955c998   Li Zefan   blktrace: mark dd...
174
175
  static const u32 ddir_act[2] = { BLK_TC_ACT(BLK_TC_READ),
  				 BLK_TC_ACT(BLK_TC_WRITE) };
2056a782f   Jens Axboe   [PATCH] Block que...
176

7b6d91dae   Christoph Hellwig   block: unify flag...
177
  #define BLK_TC_RAHEAD		BLK_TC_AHEAD
35ba8f708   David Woodhouse   blktrace: simplif...
178
  /* The ilog2() calls fall out because they're constant */
7b6d91dae   Christoph Hellwig   block: unify flag...
179
180
  #define MASK_TC_BIT(rw, __name) ((rw & REQ_ ## __name) << \
  	  (ilog2(BLK_TC_ ## __name) + BLK_TC_SHIFT - __REQ_ ## __name))
2056a782f   Jens Axboe   [PATCH] Block que...
181
182
183
184
185
  
  /*
   * 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...
186
  static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
2056a782f   Jens Axboe   [PATCH] Block que...
187
188
189
  		     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...
190
  	struct ring_buffer_event *event = NULL;
e77405ad8   Steven Rostedt   tracing: pass aro...
191
  	struct ring_buffer *buffer = NULL;
2056a782f   Jens Axboe   [PATCH] Block que...
192
  	struct blk_io_trace *t;
0a9877514   Arnaldo Carvalho de Melo   ring_buffer: remo...
193
  	unsigned long flags = 0;
2056a782f   Jens Axboe   [PATCH] Block que...
194
195
  	unsigned long *sequence;
  	pid_t pid;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
196
  	int cpu, pc = 0;
18cea4591   Li Zefan   blktrace: print o...
197
  	bool blk_tracer = blk_tracer_enabled;
2056a782f   Jens Axboe   [PATCH] Block que...
198

18cea4591   Li Zefan   blktrace: print o...
199
  	if (unlikely(bt->trace_state != Blktrace_running && !blk_tracer))
2056a782f   Jens Axboe   [PATCH] Block que...
200
201
202
  		return;
  
  	what |= ddir_act[rw & WRITE];
7b6d91dae   Christoph Hellwig   block: unify flag...
203
204
  	what |= MASK_TC_BIT(rw, SYNC);
  	what |= MASK_TC_BIT(rw, RAHEAD);
35ba8f708   David Woodhouse   blktrace: simplif...
205
206
  	what |= MASK_TC_BIT(rw, META);
  	what |= MASK_TC_BIT(rw, DISCARD);
c09c47cae   Namhyung Kim   blktrace: add FLU...
207
208
  	what |= MASK_TC_BIT(rw, FLUSH);
  	what |= MASK_TC_BIT(rw, FUA);
2056a782f   Jens Axboe   [PATCH] Block que...
209
210
  
  	pid = tsk->pid;
d0deef5b1   Shawn Du   blktrace: support...
211
  	if (act_log_check(bt, what, sector, pid))
2056a782f   Jens Axboe   [PATCH] Block que...
212
  		return;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
213
  	cpu = raw_smp_processor_id();
18cea4591   Li Zefan   blktrace: print o...
214
  	if (blk_tracer) {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
215
  		tracing_record_cmdline(current);
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
216
  		buffer = blk_tr->trace_buffer.buffer;
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
217
  		pc = preempt_count();
e77405ad8   Steven Rostedt   tracing: pass aro...
218
  		event = trace_buffer_lock_reserve(buffer, TRACE_BLK,
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
219
220
  						  sizeof(*t) + pdu_len,
  						  0, pc);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
221
222
  		if (!event)
  			return;
51a763dd8   Arnaldo Carvalho de Melo   tracing: Introduc...
223
  		t = ring_buffer_event_data(event);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
224
225
  		goto record_it;
  	}
2056a782f   Jens Axboe   [PATCH] Block que...
226

a404d5576   Jan Kara   blktrace: Send BL...
227
228
  	if (unlikely(tsk->btrace_seq != blktrace_seq))
  		trace_note_tsk(tsk);
2056a782f   Jens Axboe   [PATCH] Block que...
229
230
231
  	/*
  	 * 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...
232
  	 * from coming in and stepping on our toes.
2056a782f   Jens Axboe   [PATCH] Block que...
233
234
  	 */
  	local_irq_save(flags);
2056a782f   Jens Axboe   [PATCH] Block que...
235
236
  	t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len);
  	if (t) {
2056a782f   Jens Axboe   [PATCH] Block que...
237
238
239
240
  		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...
241
  		t->time = ktime_to_ns(ktime_get());
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
242
  record_it:
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
243
  		/*
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
244
245
246
247
248
249
250
  		 * 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...
251

2056a782f   Jens Axboe   [PATCH] Block que...
252
253
254
  		t->sector = sector;
  		t->bytes = bytes;
  		t->action = what;
2056a782f   Jens Axboe   [PATCH] Block que...
255
  		t->device = bt->dev;
2056a782f   Jens Axboe   [PATCH] Block que...
256
257
258
259
260
  		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...
261

18cea4591   Li Zefan   blktrace: print o...
262
  		if (blk_tracer) {
e77405ad8   Steven Rostedt   tracing: pass aro...
263
  			trace_buffer_unlock_commit(buffer, event, 0, pc);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
264
265
  			return;
  		}
2056a782f   Jens Axboe   [PATCH] Block que...
266
267
268
269
  	}
  
  	local_irq_restore(flags);
  }
2056a782f   Jens Axboe   [PATCH] Block que...
270
  static struct dentry *blk_tree_root;
11a57153e   Jens Axboe   blktrace: kill th...
271
  static DEFINE_MUTEX(blk_tree_mutex);
2056a782f   Jens Axboe   [PATCH] Block que...
272

ad5dd5493   Li Zefan   blktrace: fix mem...
273
  static void blk_trace_free(struct blk_trace *bt)
2056a782f   Jens Axboe   [PATCH] Block que...
274
  {
02c62304e   Alan D. Brunelle   Added in user-inj...
275
  	debugfs_remove(bt->msg_file);
2056a782f   Jens Axboe   [PATCH] Block que...
276
  	debugfs_remove(bt->dropped_file);
f48fc4d32   Jens Axboe   block: get rid of...
277
  	relay_close(bt->rchan);
39cbb602b   Alan D. Brunelle   Remove double rem...
278
  	debugfs_remove(bt->dir);
2056a782f   Jens Axboe   [PATCH] Block que...
279
  	free_percpu(bt->sequence);
64565911c   Jens Axboe   block: make blktr...
280
  	free_percpu(bt->msg_data);
2056a782f   Jens Axboe   [PATCH] Block que...
281
  	kfree(bt);
ad5dd5493   Li Zefan   blktrace: fix mem...
282
283
284
285
286
  }
  
  static void blk_trace_cleanup(struct blk_trace *bt)
  {
  	blk_trace_free(bt);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
287
288
  	if (atomic_dec_and_test(&blk_probes_ref))
  		blk_unregister_tracepoints();
2056a782f   Jens Axboe   [PATCH] Block que...
289
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
290
  int blk_trace_remove(struct request_queue *q)
2056a782f   Jens Axboe   [PATCH] Block que...
291
292
293
294
295
296
  {
  	struct blk_trace *bt;
  
  	bt = xchg(&q->blk_trace, NULL);
  	if (!bt)
  		return -EINVAL;
555472048   Li Zefan   blktrace: fix the...
297
  	if (bt->trace_state != Blktrace_running)
2056a782f   Jens Axboe   [PATCH] Block que...
298
299
300
301
  		blk_trace_cleanup(bt);
  
  	return 0;
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
302
  EXPORT_SYMBOL_GPL(blk_trace_remove);
2056a782f   Jens Axboe   [PATCH] Block que...
303

2056a782f   Jens Axboe   [PATCH] Block que...
304
305
306
307
308
309
310
311
312
313
314
  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...
315
  static const struct file_operations blk_dropped_fops = {
2056a782f   Jens Axboe   [PATCH] Block que...
316
  	.owner =	THIS_MODULE,
234e34058   Stephen Boyd   simple_open: auto...
317
  	.open =		simple_open,
2056a782f   Jens Axboe   [PATCH] Block que...
318
  	.read =		blk_dropped_read,
6038f373a   Arnd Bergmann   llseek: automatic...
319
  	.llseek =	default_llseek,
2056a782f   Jens Axboe   [PATCH] Block que...
320
  };
02c62304e   Alan D. Brunelle   Added in user-inj...
321
322
323
324
325
  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...
326
  	if (count >= BLK_TN_MAX_MSG)
02c62304e   Alan D. Brunelle   Added in user-inj...
327
  		return -EINVAL;
a4b3ada83   Carl Henrik Lunde   blktrace: NUL-ter...
328
  	msg = kmalloc(count + 1, GFP_KERNEL);
02c62304e   Alan D. Brunelle   Added in user-inj...
329
330
331
332
333
334
335
  	if (msg == NULL)
  		return -ENOMEM;
  
  	if (copy_from_user(msg, buffer, count)) {
  		kfree(msg);
  		return -EFAULT;
  	}
a4b3ada83   Carl Henrik Lunde   blktrace: NUL-ter...
336
  	msg[count] = '\0';
02c62304e   Alan D. Brunelle   Added in user-inj...
337
338
339
340
341
342
343
344
345
  	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,
234e34058   Stephen Boyd   simple_open: auto...
346
  	.open =		simple_open,
02c62304e   Alan D. Brunelle   Added in user-inj...
347
  	.write =	blk_msg_write,
6038f373a   Arnd Bergmann   llseek: automatic...
348
  	.llseek =	noop_llseek,
02c62304e   Alan D. Brunelle   Added in user-inj...
349
  };
2056a782f   Jens Axboe   [PATCH] Block que...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  /*
   * 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...
370

2056a782f   Jens Axboe   [PATCH] Block que...
371
372
373
374
375
  	return 0;
  }
  
  static struct dentry *blk_create_buf_file_callback(const char *filename,
  						   struct dentry *parent,
f4ae40a6a   Al Viro   switch debugfs to...
376
  						   umode_t mode,
2056a782f   Jens Axboe   [PATCH] Block que...
377
378
379
380
381
382
383
384
385
386
387
388
  						   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...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  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...
405
406
407
  /*
   * Setup everything required to start tracing
   */
6da127ad0   Christof Schmitt   blktrace: Add blk...
408
  int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
d0deef5b1   Shawn Du   blktrace: support...
409
410
  		       struct block_device *bdev,
  		       struct blk_user_trace_setup *buts)
2056a782f   Jens Axboe   [PATCH] Block que...
411
  {
2056a782f   Jens Axboe   [PATCH] Block que...
412
413
  	struct blk_trace *old_bt, *bt = NULL;
  	struct dentry *dir = NULL;
2056a782f   Jens Axboe   [PATCH] Block que...
414
  	int ret, i;
171044d44   Arnd Bergmann   compat_ioctl: han...
415
  	if (!buts->buf_size || !buts->buf_nr)
2056a782f   Jens Axboe   [PATCH] Block que...
416
  		return -EINVAL;
0497b345e   Jens Axboe   blktrace: use BLK...
417
418
  	strncpy(buts->name, name, BLKTRACE_BDEV_SIZE);
  	buts->name[BLKTRACE_BDEV_SIZE - 1] = '\0';
2056a782f   Jens Axboe   [PATCH] Block que...
419
420
421
422
423
  
  	/*
  	 * some device names have larger paths - convert the slashes
  	 * to underscores for this to work as expected
  	 */
171044d44   Arnd Bergmann   compat_ioctl: han...
424
425
426
  	for (i = 0; i < strlen(buts->name); i++)
  		if (buts->name[i] == '/')
  			buts->name[i] = '_';
2056a782f   Jens Axboe   [PATCH] Block que...
427

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

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

b5230b56e   Li Zefan   blktrace: fix a r...
441
  	mutex_lock(&blk_tree_mutex);
f48fc4d32   Jens Axboe   block: get rid of...
442
443
  	if (!blk_tree_root) {
  		blk_tree_root = debugfs_create_dir("block", NULL);
b5230b56e   Li Zefan   blktrace: fix a r...
444
445
  		if (!blk_tree_root) {
  			mutex_unlock(&blk_tree_mutex);
1a17662ea   Li Zefan   blktrace: fix pos...
446
  			goto err;
b5230b56e   Li Zefan   blktrace: fix a r...
447
  		}
f48fc4d32   Jens Axboe   block: get rid of...
448
  	}
b5230b56e   Li Zefan   blktrace: fix a r...
449
  	mutex_unlock(&blk_tree_mutex);
f48fc4d32   Jens Axboe   block: get rid of...
450
451
  
  	dir = debugfs_create_dir(buts->name, blk_tree_root);
2056a782f   Jens Axboe   [PATCH] Block que...
452
453
454
455
  	if (!dir)
  		goto err;
  
  	bt->dir = dir;
6da127ad0   Christof Schmitt   blktrace: Add blk...
456
  	bt->dev = dev;
2056a782f   Jens Axboe   [PATCH] Block que...
457
  	atomic_set(&bt->dropped, 0);
a404d5576   Jan Kara   blktrace: Send BL...
458
  	INIT_LIST_HEAD(&bt->running_list);
2056a782f   Jens Axboe   [PATCH] Block que...
459
460
  
  	ret = -EIO;
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
461
462
  	bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt,
  					       &blk_dropped_fops);
2056a782f   Jens Axboe   [PATCH] Block que...
463
464
  	if (!bt->dropped_file)
  		goto err;
02c62304e   Alan D. Brunelle   Added in user-inj...
465
466
467
  	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...
468
469
  	bt->rchan = relay_open("trace", dir, buts->buf_size,
  				buts->buf_nr, &blk_relay_callbacks, bt);
2056a782f   Jens Axboe   [PATCH] Block que...
470
471
  	if (!bt->rchan)
  		goto err;
2056a782f   Jens Axboe   [PATCH] Block que...
472

171044d44   Arnd Bergmann   compat_ioctl: han...
473
  	bt->act_mask = buts->act_mask;
2056a782f   Jens Axboe   [PATCH] Block que...
474
475
  	if (!bt->act_mask)
  		bt->act_mask = (u16) -1;
9908c3099   Li Zefan   blktrace: support...
476
  	blk_trace_setup_lba(bt, bdev);
2056a782f   Jens Axboe   [PATCH] Block que...
477

d0deef5b1   Shawn Du   blktrace: support...
478
479
480
481
482
  	/* 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...
483
  	bt->pid = buts->pid;
2056a782f   Jens Axboe   [PATCH] Block que...
484
485
486
487
488
489
490
491
  	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...
492
  	if (atomic_inc_return(&blk_probes_ref) == 1)
cbe28296e   Li Zefan   blktrace: don't i...
493
  		blk_register_tracepoints();
2056a782f   Jens Axboe   [PATCH] Block que...
494
495
  	return 0;
  err:
ad5dd5493   Li Zefan   blktrace: fix mem...
496
  	blk_trace_free(bt);
2056a782f   Jens Axboe   [PATCH] Block que...
497
498
  	return ret;
  }
171044d44   Arnd Bergmann   compat_ioctl: han...
499

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

62c2a7d96   Arnd Bergmann   block: push BKL i...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  #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,
  	};
62c2a7d96   Arnd Bergmann   block: push BKL i...
541
542
543
544
  
  	ret = do_blk_trace_setup(q, name, dev, bdev, &buts);
  	if (ret)
  		return ret;
f8c5e9448   Chen Gang   kernel: trace: bl...
545
  	if (copy_to_user(arg, &buts.name, ARRAY_SIZE(buts.name))) {
62c2a7d96   Arnd Bergmann   block: push BKL i...
546
547
548
549
550
551
552
  		blk_trace_remove(q);
  		return -EFAULT;
  	}
  
  	return 0;
  }
  #endif
6da127ad0   Christof Schmitt   blktrace: Add blk...
553
  int blk_trace_startstop(struct request_queue *q, int start)
2056a782f   Jens Axboe   [PATCH] Block que...
554
  {
2056a782f   Jens Axboe   [PATCH] Block que...
555
  	int ret;
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
556
  	struct blk_trace *bt = q->blk_trace;
2056a782f   Jens Axboe   [PATCH] Block que...
557

939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
558
  	if (bt == NULL)
2056a782f   Jens Axboe   [PATCH] Block que...
559
560
561
562
563
564
565
566
567
568
569
570
571
  		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;
a404d5576   Jan Kara   blktrace: Send BL...
572
573
574
  			spin_lock_irq(&running_trace_lock);
  			list_add(&bt->running_list, &running_trace_list);
  			spin_unlock_irq(&running_trace_lock);
be1c63411   Olaf Kirch   [PATCH] blktrace:...
575
576
  
  			trace_note_time(bt);
2056a782f   Jens Axboe   [PATCH] Block que...
577
578
579
580
581
  			ret = 0;
  		}
  	} else {
  		if (bt->trace_state == Blktrace_running) {
  			bt->trace_state = Blktrace_stopped;
a404d5576   Jan Kara   blktrace: Send BL...
582
583
584
  			spin_lock_irq(&running_trace_lock);
  			list_del_init(&bt->running_list);
  			spin_unlock_irq(&running_trace_lock);
2056a782f   Jens Axboe   [PATCH] Block que...
585
586
587
588
589
590
591
  			relay_flush(bt->rchan);
  			ret = 0;
  		}
  	}
  
  	return ret;
  }
6da127ad0   Christof Schmitt   blktrace: Add blk...
592
  EXPORT_SYMBOL_GPL(blk_trace_startstop);
2056a782f   Jens Axboe   [PATCH] Block que...
593
594
595
596
  
  /**
   * blk_trace_ioctl: - handle the ioctls associated with tracing
   * @bdev:	the block device
ef18012b2   Steven Rostedt   tracing: remove f...
597
   * @cmd:	the ioctl cmd
2056a782f   Jens Axboe   [PATCH] Block que...
598
599
600
601
602
   * @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...
603
  	struct request_queue *q;
2056a782f   Jens Axboe   [PATCH] Block que...
604
  	int ret, start = 0;
6da127ad0   Christof Schmitt   blktrace: Add blk...
605
  	char b[BDEVNAME_SIZE];
2056a782f   Jens Axboe   [PATCH] Block que...
606
607
608
609
610
611
612
613
614
  
  	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...
615
  		bdevname(bdev, b);
d0deef5b1   Shawn Du   blktrace: support...
616
  		ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
2056a782f   Jens Axboe   [PATCH] Block que...
617
  		break;
62c2a7d96   Arnd Bergmann   block: push BKL i...
618
619
620
621
622
623
  #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...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
  	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...
646
  void blk_trace_shutdown(struct request_queue *q)
2056a782f   Jens Axboe   [PATCH] Block que...
647
  {
6c5c93415   Alexey Dobriyan   [PATCH] ifdef blk...
648
649
650
651
  	if (q->blk_trace) {
  		blk_trace_startstop(q, 0);
  		blk_trace_remove(q);
  	}
2056a782f   Jens Axboe   [PATCH] Block que...
652
  }
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
653
654
655
656
657
658
659
660
661
  
  /*
   * blktrace probes
   */
  
  /**
   * blk_add_trace_rq - Add a trace for a request oriented action
   * @q:		queue the io is for
   * @rq:		the source request
af5040da0   Roman Pen   blktrace: fix acc...
662
   * @nr_bytes:	number of completed bytes
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
663
664
665
666
667
668
669
   * @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,
af5040da0   Roman Pen   blktrace: fix acc...
670
  			     unsigned int nr_bytes, 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);
af5040da0   Roman Pen   blktrace: fix acc...
678
  		__blk_add_trace(bt, 0, nr_bytes, 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);
af5040da0   Roman Pen   blktrace: fix acc...
682
  		__blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
805f6b5e1   Tao Ma   blktrace: Use rq-...
683
  				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
  {
af5040da0   Roman Pen   blktrace: fix acc...
689
  	blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_ABORT);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
690
  }
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
  {
af5040da0   Roman Pen   blktrace: fix acc...
694
  	blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_INSERT);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
695
  }
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
  {
af5040da0   Roman Pen   blktrace: fix acc...
699
  	blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_ISSUE);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
700
  }
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
  {
af5040da0   Roman Pen   blktrace: fix acc...
705
  	blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_REQUEUE);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
706
  }
38516ab59   Steven Rostedt   tracing: Let trac...
707
708
  static void blk_add_trace_rq_complete(void *ignore,
  				      struct request_queue *q,
af5040da0   Roman Pen   blktrace: fix acc...
709
710
  				      struct request *rq,
  				      unsigned int nr_bytes)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
711
  {
af5040da0   Roman Pen   blktrace: fix acc...
712
  	blk_add_trace_rq(q, rq, nr_bytes, BLK_TA_COMPLETE);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
713
714
715
716
717
718
719
  }
  
  /**
   * 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...
720
   * @error:	error, if any
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
721
722
723
724
725
726
   *
   * 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...
727
  			      u32 what, int error)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
728
729
730
731
732
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (likely(!bt))
  		return;
797a455d2   Jens Axboe   block: ensure tha...
733
734
  	if (!error && !bio_flagged(bio, BIO_UPTODATE))
  		error = EIO;
4f024f379   Kent Overstreet   block: Abstract o...
735
736
  	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
  			bio->bi_rw, what, error, 0, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
737
  }
38516ab59   Steven Rostedt   tracing: Let trac...
738
739
  static void blk_add_trace_bio_bounce(void *ignore,
  				     struct request_queue *q, struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
740
  {
797a455d2   Jens Axboe   block: ensure tha...
741
  	blk_add_trace_bio(q, bio, BLK_TA_BOUNCE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
742
  }
0a82a8d13   Linus Torvalds   Revert "block: ad...
743
744
745
  static void blk_add_trace_bio_complete(void *ignore,
  				       struct request_queue *q, struct bio *bio,
  				       int error)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
746
  {
797a455d2   Jens Axboe   block: ensure tha...
747
  	blk_add_trace_bio(q, bio, BLK_TA_COMPLETE, error);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
748
  }
38516ab59   Steven Rostedt   tracing: Let trac...
749
750
  static void blk_add_trace_bio_backmerge(void *ignore,
  					struct request_queue *q,
8c1cf6bb0   Tejun Heo   block: add @req t...
751
  					struct request *rq,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
752
  					struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
753
  {
797a455d2   Jens Axboe   block: ensure tha...
754
  	blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
755
  }
38516ab59   Steven Rostedt   tracing: Let trac...
756
757
  static void blk_add_trace_bio_frontmerge(void *ignore,
  					 struct request_queue *q,
8c1cf6bb0   Tejun Heo   block: add @req t...
758
  					 struct request *rq,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
759
  					 struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
760
  {
797a455d2   Jens Axboe   block: ensure tha...
761
  	blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
762
  }
38516ab59   Steven Rostedt   tracing: Let trac...
763
764
  static void blk_add_trace_bio_queue(void *ignore,
  				    struct request_queue *q, struct bio *bio)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
765
  {
797a455d2   Jens Axboe   block: ensure tha...
766
  	blk_add_trace_bio(q, bio, BLK_TA_QUEUE, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
767
  }
38516ab59   Steven Rostedt   tracing: Let trac...
768
769
  static void blk_add_trace_getrq(void *ignore,
  				struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
770
  				struct bio *bio, int rw)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
771
772
  {
  	if (bio)
797a455d2   Jens Axboe   block: ensure tha...
773
  		blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
774
775
776
777
778
779
780
  	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...
781
782
  static void blk_add_trace_sleeprq(void *ignore,
  				  struct request_queue *q,
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
783
  				  struct bio *bio, int rw)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
784
785
  {
  	if (bio)
797a455d2   Jens Axboe   block: ensure tha...
786
  		blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
787
788
789
790
  	else {
  		struct blk_trace *bt = q->blk_trace;
  
  		if (bt)
939b36697   Arnaldo Carvalho de Melo   blktrace: fix cod...
791
792
  			__blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
  					0, 0, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
793
794
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
795
  static void blk_add_trace_plug(void *ignore, struct request_queue *q)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
796
797
798
799
800
801
  {
  	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...
802
803
  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...
804
805
806
807
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (bt) {
94b5eb28b   Jens Axboe   block: fixup bloc...
808
  		__be64 rpdu = cpu_to_be64(depth);
49cac01e1   Jens Axboe   block: make unplu...
809
  		u32 what;
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
810

49cac01e1   Jens Axboe   block: make unplu...
811
812
813
814
815
816
  		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...
817
818
  	}
  }
38516ab59   Steven Rostedt   tracing: Let trac...
819
820
  static void blk_add_trace_split(void *ignore,
  				struct request_queue *q, struct bio *bio,
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
821
822
823
824
825
826
  				unsigned int pdu)
  {
  	struct blk_trace *bt = q->blk_trace;
  
  	if (bt) {
  		__be64 rpdu = cpu_to_be64(pdu);
4f024f379   Kent Overstreet   block: Abstract o...
827
828
829
  		__blk_add_trace(bt, bio->bi_iter.bi_sector,
  				bio->bi_iter.bi_size, bio->bi_rw, BLK_TA_SPLIT,
  				!bio_flagged(bio, BIO_UPTODATE),
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
830
831
832
833
834
  				sizeof(rpdu), &rpdu);
  	}
  }
  
  /**
d07335e51   Mike Snitzer   block: Rename "bl...
835
   * blk_add_trace_bio_remap - Add a trace for a bio-remap operation
546cf44a1   Randy Dunlap   blktrace: Fix new...
836
   * @ignore:	trace callback data parameter (not used)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
837
838
839
   * @q:		queue the io is for
   * @bio:	the source bio
   * @dev:	target device
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
840
   * @from:	source sector
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
841
842
843
844
845
846
   *
   * 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...
847
848
849
  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...
850
851
852
853
854
855
  {
  	struct blk_trace *bt = q->blk_trace;
  	struct blk_io_trace_remap r;
  
  	if (likely(!bt))
  		return;
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
856
857
858
  	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...
859

4f024f379   Kent Overstreet   block: Abstract o...
860
861
862
  	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
  			bio->bi_rw, BLK_TA_REMAP,
  			!bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
863
864
865
  }
  
  /**
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
866
   * blk_add_trace_rq_remap - Add a trace for a request-remap operation
546cf44a1   Randy Dunlap   blktrace: Fix new...
867
   * @ignore:	trace callback data parameter (not used)
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
868
869
870
871
872
873
874
875
876
877
   * @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...
878
879
  static void blk_add_trace_rq_remap(void *ignore,
  				   struct request_queue *q,
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
  				   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...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
   * 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...
917
  	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
2e46e8b27   Tejun Heo   block: drop reque...
918
919
  		__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...
920
  	else
2e46e8b27   Tejun Heo   block: drop reque...
921
922
  		__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...
923
924
  }
  EXPORT_SYMBOL_GPL(blk_add_driver_data);
3c289ba7c   Li Zefan   blktrace: remove ...
925
  static void blk_register_tracepoints(void)
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
926
927
  {
  	int ret;
38516ab59   Steven Rostedt   tracing: Let trac...
928
  	ret = register_trace_block_rq_abort(blk_add_trace_rq_abort, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
929
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
930
  	ret = register_trace_block_rq_insert(blk_add_trace_rq_insert, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
931
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
932
  	ret = register_trace_block_rq_issue(blk_add_trace_rq_issue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
933
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
934
  	ret = register_trace_block_rq_requeue(blk_add_trace_rq_requeue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
935
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
936
  	ret = register_trace_block_rq_complete(blk_add_trace_rq_complete, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
937
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
938
  	ret = register_trace_block_bio_bounce(blk_add_trace_bio_bounce, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
939
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
940
  	ret = register_trace_block_bio_complete(blk_add_trace_bio_complete, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
941
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
942
  	ret = register_trace_block_bio_backmerge(blk_add_trace_bio_backmerge, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
943
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
944
  	ret = register_trace_block_bio_frontmerge(blk_add_trace_bio_frontmerge, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
945
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
946
  	ret = register_trace_block_bio_queue(blk_add_trace_bio_queue, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
947
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
948
  	ret = register_trace_block_getrq(blk_add_trace_getrq, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
949
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
950
  	ret = register_trace_block_sleeprq(blk_add_trace_sleeprq, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
951
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
952
  	ret = register_trace_block_plug(blk_add_trace_plug, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
953
  	WARN_ON(ret);
49cac01e1   Jens Axboe   block: make unplu...
954
  	ret = register_trace_block_unplug(blk_add_trace_unplug, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
955
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
956
  	ret = register_trace_block_split(blk_add_trace_split, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
957
  	WARN_ON(ret);
d07335e51   Mike Snitzer   block: Rename "bl...
958
  	ret = register_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
959
  	WARN_ON(ret);
38516ab59   Steven Rostedt   tracing: Let trac...
960
  	ret = register_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
b0da3f0da   Jun'ichi Nomura   Add a tracepoint ...
961
  	WARN_ON(ret);
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
962
963
964
965
  }
  
  static void blk_unregister_tracepoints(void)
  {
38516ab59   Steven Rostedt   tracing: Let trac...
966
  	unregister_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
d07335e51   Mike Snitzer   block: Rename "bl...
967
  	unregister_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
38516ab59   Steven Rostedt   tracing: Let trac...
968
  	unregister_trace_block_split(blk_add_trace_split, NULL);
49cac01e1   Jens Axboe   block: make unplu...
969
  	unregister_trace_block_unplug(blk_add_trace_unplug, NULL);
38516ab59   Steven Rostedt   tracing: Let trac...
970
971
972
973
974
975
976
977
978
979
980
981
982
  	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...
983
984
985
  
  	tracepoint_synchronize_unregister();
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
986
987
988
989
990
991
992
  
  /*
   * 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:...
993
  	int i = 0;
65796348e   Li Zefan   blktrace: fix wro...
994
  	int tc = t->action >> BLK_TC_SHIFT;
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
995

18cea4591   Li Zefan   blktrace: print o...
996
997
998
999
  	if (t->action == BLK_TN_MESSAGE) {
  		rwbs[i++] = 'N';
  		goto out;
  	}
c09c47cae   Namhyung Kim   blktrace: add FLU...
1000
1001
  	if (tc & BLK_TC_FLUSH)
  		rwbs[i++] = 'F';
65796348e   Li Zefan   blktrace: fix wro...
1002
  	if (tc & BLK_TC_DISCARD)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1003
  		rwbs[i++] = 'D';
65796348e   Li Zefan   blktrace: fix wro...
1004
  	else if (tc & BLK_TC_WRITE)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1005
1006
1007
1008
1009
  		rwbs[i++] = 'W';
  	else if (t->bytes)
  		rwbs[i++] = 'R';
  	else
  		rwbs[i++] = 'N';
c09c47cae   Namhyung Kim   blktrace: add FLU...
1010
1011
  	if (tc & BLK_TC_FUA)
  		rwbs[i++] = 'F';
65796348e   Li Zefan   blktrace: fix wro...
1012
  	if (tc & BLK_TC_AHEAD)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1013
  		rwbs[i++] = 'A';
65796348e   Li Zefan   blktrace: fix wro...
1014
  	if (tc & BLK_TC_SYNC)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1015
  		rwbs[i++] = 'S';
65796348e   Li Zefan   blktrace: fix wro...
1016
  	if (tc & BLK_TC_META)
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1017
  		rwbs[i++] = 'M';
18cea4591   Li Zefan   blktrace: print o...
1018
  out:
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1019
  	rwbs[i] = '\0';
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
  }
  
  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...
1032
1033
1034
1035
1036
1037
1038
1039
1040
  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...
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  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...
1053
  	return te_blk_io_trace(ent)->error;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  }
  
  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...
1066
  	__u64 sector_from = __r->sector_from;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1067

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1068
  	r->device_from = be32_to_cpu(__r->device_from);
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1069
1070
  	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...
1071
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1072
  typedef void (blk_log_action_t) (struct trace_iterator *iter, const char *act);
b6a4b0c3a   Li Zefan   blktrace: extract...
1073

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

66de7792c   Li Zefan   blktrace: fix out...
1136
  	if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1137
1138
1139
1140
  		trace_seq_printf(s, "%u ", t_bytes(ent));
  		blk_log_dump_pdu(s, ent);
  		trace_seq_printf(s, "[%s]
  ", cmd);
66de7792c   Li Zefan   blktrace: fix out...
1141
1142
  	} else {
  		if (t_sec(ent))
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1143
1144
  			trace_seq_printf(s, "%llu + %u [%s]
  ",
66de7792c   Li Zefan   blktrace: fix out...
1145
  						t_sector(ent), t_sec(ent), cmd);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1146
1147
1148
  		else
  			trace_seq_printf(s, "[%s]
  ", cmd);
66de7792c   Li Zefan   blktrace: fix out...
1149
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1150
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1151
  static void blk_log_with_error(struct trace_seq *s,
157f9c00e   Arnaldo Carvalho de Melo   tracing/blktrace:...
1152
  			      const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1153
  {
66de7792c   Li Zefan   blktrace: fix out...
1154
  	if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1155
1156
1157
  		blk_log_dump_pdu(s, ent);
  		trace_seq_printf(s, "[%d]
  ", t_error(ent));
66de7792c   Li Zefan   blktrace: fix out...
1158
1159
  	} else {
  		if (t_sec(ent))
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1160
1161
1162
1163
1164
1165
1166
1167
  			trace_seq_printf(s, "%llu + %u [%d]
  ",
  					 t_sector(ent),
  					 t_sec(ent), t_error(ent));
  		else
  			trace_seq_printf(s, "%llu [%d]
  ",
  					 t_sector(ent), t_error(ent));
66de7792c   Li Zefan   blktrace: fix out...
1168
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1169
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1170
  static void blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1171
  {
a42aaa3bb   Alan D. Brunelle   blktrace: correct...
1172
  	struct blk_io_trace_remap r = { .device_from = 0, };
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1173
1174
  
  	get_pdu_remap(ent, &r);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1175
1176
1177
1178
1179
  	trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu
  ",
  			 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...
1180
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1181
  static void blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1182
  {
4ca530852   Steven Rostedt   tracing: protect ...
1183
1184
1185
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1186
1187
  	trace_seq_printf(s, "[%s]
  ", cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1188
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1189
  static void blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1190
  {
4ca530852   Steven Rostedt   tracing: protect ...
1191
1192
1193
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1194
1195
  	trace_seq_printf(s, "[%s] %llu
  ", cmd, get_pdu_int(ent));
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1196
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1197
  static void blk_log_split(struct trace_seq *s, const struct trace_entry *ent)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1198
  {
4ca530852   Steven Rostedt   tracing: protect ...
1199
1200
1201
  	char cmd[TASK_COMM_LEN];
  
  	trace_find_cmdline(ent->pid, cmd);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1202
1203
1204
  	trace_seq_printf(s, "%llu / %llu [%s]
  ", t_sector(ent),
  			 get_pdu_int(ent), cmd);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1205
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1206
  static void blk_log_msg(struct trace_seq *s, const struct trace_entry *ent)
18cea4591   Li Zefan   blktrace: print o...
1207
  {
18cea4591   Li Zefan   blktrace: print o...
1208
  	const struct blk_io_trace *t = te_blk_io_trace(ent);
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1209
1210
1211
  	trace_seq_putmem(s, t + 1, t->pdu_len);
  	trace_seq_putc(s, '
  ');
18cea4591   Li Zefan   blktrace: print o...
1212
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  /*
   * 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...
1229
  	blk_tracer_enabled = true;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1230
1231
1232
1233
1234
1235
  }
  
  static int blk_tracer_init(struct trace_array *tr)
  {
  	blk_tr = tr;
  	blk_tracer_start(tr);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1236
1237
1238
1239
1240
  	return 0;
  }
  
  static void blk_tracer_stop(struct trace_array *tr)
  {
ad5dd5493   Li Zefan   blktrace: fix mem...
1241
  	blk_tracer_enabled = false;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1242
1243
1244
1245
  }
  
  static void blk_tracer_reset(struct trace_array *tr)
  {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1246
1247
  	blk_tracer_stop(tr);
  }
e4955c998   Li Zefan   blktrace: mark dd...
1248
  static const struct {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1249
  	const char *act[2];
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1250
  	void	   (*print)(struct trace_seq *s, const struct trace_entry *ent);
e4955c998   Li Zefan   blktrace: mark dd...
1251
  } what2act[] = {
ef18012b2   Steven Rostedt   tracing: remove f...
1252
  	[__BLK_TA_QUEUE]	= {{  "Q", "queue" },	   blk_log_generic },
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1253
1254
1255
1256
1257
1258
1259
1260
1261
  	[__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...
1262
  	[__BLK_TA_UNPLUG_TIMER]	= {{ "UT", "unplug_timer" }, blk_log_unplug },
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1263
1264
1265
1266
1267
  	[__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...
1268
1269
  static enum print_line_t print_one_line(struct trace_iterator *iter,
  					bool classic)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1270
  {
2c9b238eb   Arnaldo Carvalho de Melo   trace: Change str...
1271
  	struct trace_seq *s = &iter->seq;
b6a4b0c3a   Li Zefan   blktrace: extract...
1272
1273
  	const struct blk_io_trace *t;
  	u16 what;
b6a4b0c3a   Li Zefan   blktrace: extract...
1274
1275
  	bool long_act;
  	blk_log_action_t *log_action;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1276

b6a4b0c3a   Li Zefan   blktrace: extract...
1277
1278
1279
1280
  	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...
1281

18cea4591   Li Zefan   blktrace: print o...
1282
  	if (t->action == BLK_TN_MESSAGE) {
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1283
1284
  		log_action(iter, long_act ? "message" : "m");
  		blk_log_msg(s, iter->ent);
18cea4591   Li Zefan   blktrace: print o...
1285
  	}
eb08f8eb0   Li Zefan   blktrace: fix off...
1286
  	if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act)))
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1287
1288
  		trace_seq_printf(s, "Unknown action %x
  ", what);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1289
  	else {
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1290
1291
  		log_action(iter, what2act[what].act[long_act]);
  		what2act[what].print(s, iter->ent);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1292
  	}
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1293
1294
  
  	return trace_handle_return(s);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1295
  }
b6a4b0c3a   Li Zefan   blktrace: extract...
1296
  static enum print_line_t blk_trace_event_print(struct trace_iterator *iter,
a9a577638   Steven Rostedt   tracing: Allow ev...
1297
  					       int flags, struct trace_event *event)
b6a4b0c3a   Li Zefan   blktrace: extract...
1298
  {
b6a4b0c3a   Li Zefan   blktrace: extract...
1299
1300
  	return print_one_line(iter, false);
  }
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1301
  static void blk_trace_synthesize_old_trace(struct trace_iterator *iter)
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1302
1303
1304
1305
1306
1307
  {
  	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...
1308
  		.time     = iter->ts,
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1309
  	};
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1310
1311
1312
  	trace_seq_putmem(s, &old, offset);
  	trace_seq_putmem(s, &t->sector,
  			 sizeof(old) - offset + t->pdu_len);
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1313
  }
ae7462b4f   Arnaldo Carvalho de Melo   trace: make the t...
1314
  static enum print_line_t
a9a577638   Steven Rostedt   tracing: Allow ev...
1315
1316
  blk_trace_event_print_binary(struct trace_iterator *iter, int flags,
  			     struct trace_event *event)
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1317
  {
f4a1d08ce   Steven Rostedt (Red Hat)   blktrace/tracing:...
1318
1319
1320
  	blk_trace_synthesize_old_trace(iter);
  
  	return trace_handle_return(&iter->seq);
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1321
  }
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1322
1323
  static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter)
  {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1324
1325
  	if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC))
  		return TRACE_TYPE_UNHANDLED;
b6a4b0c3a   Li Zefan   blktrace: extract...
1326
  	return print_one_line(iter, true);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1327
  }
8c1a49aed   Steven Rostedt (Red Hat)   tracing: Pass tra...
1328
1329
  static int
  blk_tracer_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
f3948f885   Li Zefan   blktrace: fix con...
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
  {
  	/* 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...
1340
1341
1342
1343
1344
1345
1346
1347
1348
  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...
1349
  	.set_flag	= blk_tracer_set_flag,
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1350
  };
a9a577638   Steven Rostedt   tracing: Allow ev...
1351
  static struct trace_event_functions trace_blk_event_funcs = {
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1352
  	.trace		= blk_trace_event_print,
08a06b83f   Arnaldo Carvalho de Melo   blkftrace: binary...
1353
  	.binary		= blk_trace_event_print_binary,
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1354
  };
a9a577638   Steven Rostedt   tracing: Allow ev...
1355
1356
1357
1358
  static struct trace_event trace_blk_event = {
  	.type		= TRACE_BLK,
  	.funcs		= &trace_blk_event_funcs,
  };
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
  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...
1386
1387
  	if (atomic_dec_and_test(&blk_probes_ref))
  		blk_unregister_tracepoints();
ad5dd5493   Li Zefan   blktrace: fix mem...
1388
  	blk_trace_free(bt);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1389
1390
1391
1392
1393
1394
  	return 0;
  }
  
  /*
   * Setup everything required to start tracing
   */
9908c3099   Li Zefan   blktrace: support...
1395
1396
  static int blk_trace_setup_queue(struct request_queue *q,
  				 struct block_device *bdev)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1397
1398
  {
  	struct blk_trace *old_bt, *bt = NULL;
18cea4591   Li Zefan   blktrace: print o...
1399
  	int ret = -ENOMEM;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1400

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1401
1402
  	bt = kzalloc(sizeof(*bt), GFP_KERNEL);
  	if (!bt)
15152e448   Li Zefan   blktrace: report ...
1403
  		return -ENOMEM;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1404

18cea4591   Li Zefan   blktrace: print o...
1405
1406
1407
  	bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char));
  	if (!bt->msg_data)
  		goto free_bt;
9908c3099   Li Zefan   blktrace: support...
1408
  	bt->dev = bdev->bd_dev;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1409
  	bt->act_mask = (u16)-1;
9908c3099   Li Zefan   blktrace: support...
1410
1411
  
  	blk_trace_setup_lba(bt, bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1412
1413
1414
1415
  
  	old_bt = xchg(&q->blk_trace, bt);
  	if (old_bt != NULL) {
  		(void)xchg(&q->blk_trace, old_bt);
18cea4591   Li Zefan   blktrace: print o...
1416
1417
  		ret = -EBUSY;
  		goto free_bt;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1418
  	}
15152e448   Li Zefan   blktrace: report ...
1419

17ba97e34   Li Zefan   blktrace: fix blk...
1420
1421
  	if (atomic_inc_return(&blk_probes_ref) == 1)
  		blk_register_tracepoints();
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1422
  	return 0;
18cea4591   Li Zefan   blktrace: print o...
1423
1424
1425
1426
  
  free_bt:
  	blk_trace_free(bt);
  	return ret;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1427
1428
1429
1430
1431
  }
  
  /*
   * sysfs interface to enable and configure tracing
   */
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
  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 ...
1442
  static BLK_TRACE_DEVICE_ATTR(enable);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  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...
1461
1462
1463
1464
1465
1466
  static const struct {
  	int mask;
  	const char *str;
  } mask_maps[] = {
  	{ BLK_TC_READ,		"read"		},
  	{ BLK_TC_WRITE,		"write"		},
c09c47cae   Namhyung Kim   blktrace: add FLU...
1467
  	{ BLK_TC_FLUSH,		"flush"		},
093419971   Li Zefan   blktrace: print h...
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
  	{ 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...
1479
  	{ BLK_TC_FUA,		"fua"		},
093419971   Li Zefan   blktrace: print h...
1480
1481
1482
  };
  
  static int blk_trace_str2mask(const char *str)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1483
  {
093419971   Li Zefan   blktrace: print h...
1484
  	int i;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1485
  	int mask = 0;
9eb85125c   Li Zefan   blktrace: pass th...
1486
  	char *buf, *s, *token;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1487

9eb85125c   Li Zefan   blktrace: pass th...
1488
1489
  	buf = kstrdup(str, GFP_KERNEL);
  	if (buf == NULL)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1490
  		return -ENOMEM;
9eb85125c   Li Zefan   blktrace: pass th...
1491
  	s = strstrip(buf);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1492
1493
  
  	while (1) {
093419971   Li Zefan   blktrace: print h...
1494
1495
  		token = strsep(&s, ",");
  		if (token == NULL)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1496
  			break;
093419971   Li Zefan   blktrace: print h...
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  		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...
1510
  	}
9eb85125c   Li Zefan   blktrace: pass th...
1511
  	kfree(buf);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1512
1513
1514
  
  	return mask;
  }
093419971   Li Zefan   blktrace: print h...
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
  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...
1531
1532
1533
1534
1535
1536
1537
  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...
1538
1539
1540
1541
1542
1543
1544
1545
  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...
1546
1547
  	bdev = bdget(part_devt(p));
  	if (bdev == NULL)
01b284f9b   Arnd Bergmann   blktrace: remove ...
1548
  		goto out;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1549

b125130b2   Li Zefan   blktrace: avoid a...
1550
  	q = blk_trace_get_queue(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1551
1552
  	if (q == NULL)
  		goto out_bdput;
b125130b2   Li Zefan   blktrace: avoid a...
1553

c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1554
  	mutex_lock(&bdev->bd_mutex);
cd649b8bb   Li Zefan   blktrace: remove ...
1555
1556
1557
1558
1559
1560
  
  	if (attr == &dev_attr_enable) {
  		ret = sprintf(buf, "%u
  ", !!q->blk_trace);
  		goto out_unlock_bdev;
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1561
1562
1563
1564
  	if (q->blk_trace == NULL)
  		ret = sprintf(buf, "disabled
  ");
  	else if (attr == &dev_attr_act_mask)
093419971   Li Zefan   blktrace: print h...
1565
  		ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1566
1567
1568
1569
1570
1571
1572
1573
1574
  	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 ...
1575
1576
  
  out_unlock_bdev:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1577
1578
1579
  	mutex_unlock(&bdev->bd_mutex);
  out_bdput:
  	bdput(bdev);
01b284f9b   Arnd Bergmann   blktrace: remove ...
1580
  out:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
  	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...
1592
  	ssize_t ret = -EINVAL;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1593
1594
1595
1596
1597
1598
1599
  
  	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...
1600
1601
  			ret = blk_trace_str2mask(buf);
  			if (ret < 0)
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1602
  				goto out;
093419971   Li Zefan   blktrace: print h...
1603
  			value = ret;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1604
1605
1606
  		}
  	} else if (sscanf(buf, "%llu", &value) != 1)
  		goto out;
093419971   Li Zefan   blktrace: print h...
1607
  	ret = -ENXIO;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1608
1609
1610
  	p = dev_to_part(dev);
  	bdev = bdget(part_devt(p));
  	if (bdev == NULL)
01b284f9b   Arnd Bergmann   blktrace: remove ...
1611
  		goto out;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1612

b125130b2   Li Zefan   blktrace: avoid a...
1613
  	q = blk_trace_get_queue(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1614
1615
1616
1617
  	if (q == NULL)
  		goto out_bdput;
  
  	mutex_lock(&bdev->bd_mutex);
cd649b8bb   Li Zefan   blktrace: remove ...
1618
1619
1620
  
  	if (attr == &dev_attr_enable) {
  		if (value)
9908c3099   Li Zefan   blktrace: support...
1621
  			ret = blk_trace_setup_queue(q, bdev);
cd649b8bb   Li Zefan   blktrace: remove ...
1622
1623
1624
1625
  		else
  			ret = blk_trace_remove_queue(q);
  		goto out_unlock_bdev;
  	}
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1626
1627
  	ret = 0;
  	if (q->blk_trace == NULL)
9908c3099   Li Zefan   blktrace: support...
1628
  		ret = blk_trace_setup_queue(q, bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
  
  	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...
1639
  	}
cd649b8bb   Li Zefan   blktrace: remove ...
1640
1641
  
  out_unlock_bdev:
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1642
1643
1644
  	mutex_unlock(&bdev->bd_mutex);
  out_bdput:
  	bdput(bdev);
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1645
  out:
cd649b8bb   Li Zefan   blktrace: remove ...
1646
  	return ret ? ret : count;
c71a89615   Arnaldo Carvalho de Melo   blktrace: add ftr...
1647
  }
cd649b8bb   Li Zefan   blktrace: remove ...
1648

1d54ad6da   Li Zefan   blktrace: add tra...
1649
1650
1651
1652
  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...
1653
1654
1655
1656
  void blk_trace_remove_sysfs(struct device *dev)
  {
  	sysfs_remove_group(&dev->kobj, &blk_trace_attr_group);
  }
55782138e   Li Zefan   tracing/events: c...
1657
1658
1659
1660
1661
1662
1663
1664
1665
  #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...
1666
  	if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
55782138e   Li Zefan   tracing/events: c...
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
  		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...
1688
1689
  	if (rw & REQ_FLUSH)
  		rwbs[i++] = 'F';
55782138e   Li Zefan   tracing/events: c...
1690
1691
  	if (rw & WRITE)
  		rwbs[i++] = 'W';
7b6d91dae   Christoph Hellwig   block: unify flag...
1692
  	else if (rw & REQ_DISCARD)
55782138e   Li Zefan   tracing/events: c...
1693
1694
1695
1696
1697
  		rwbs[i++] = 'D';
  	else if (bytes)
  		rwbs[i++] = 'R';
  	else
  		rwbs[i++] = 'N';
c09c47cae   Namhyung Kim   blktrace: add FLU...
1698
1699
  	if (rw & REQ_FUA)
  		rwbs[i++] = 'F';
7b6d91dae   Christoph Hellwig   block: unify flag...
1700
  	if (rw & REQ_RAHEAD)
55782138e   Li Zefan   tracing/events: c...
1701
  		rwbs[i++] = 'A';
7b6d91dae   Christoph Hellwig   block: unify flag...
1702
  	if (rw & REQ_SYNC)
55782138e   Li Zefan   tracing/events: c...
1703
  		rwbs[i++] = 'S';
7b6d91dae   Christoph Hellwig   block: unify flag...
1704
  	if (rw & REQ_META)
55782138e   Li Zefan   tracing/events: c...
1705
  		rwbs[i++] = 'M';
8d57a98cc   Adrian Hunter   block: add secure...
1706
1707
  	if (rw & REQ_SECURE)
  		rwbs[i++] = 'E';
55782138e   Li Zefan   tracing/events: c...
1708
1709
1710
  
  	rwbs[i] = '\0';
  }
9ca8f8e51   Kent Overstreet   Export blk_fill_r...
1711
  EXPORT_SYMBOL_GPL(blk_fill_rwbs);
55782138e   Li Zefan   tracing/events: c...
1712

55782138e   Li Zefan   tracing/events: c...
1713
  #endif /* CONFIG_EVENT_TRACING */