1184610Salfred#!/usr/sbin/dtrace -s
2184610Salfred/*
3184610Salfred * fspaging.d - file system read/write and paging tracing.
4184610Salfred *              Written using DTrace (Solaris 10 3/05)
5184610Salfred *
6184610Salfred * This traces file related activity: system call reads and writes,
7184610Salfred * vnode logical read and writes (fop), vnode putpage and getpage activity,
8184610Salfred * and disk I/O. It can be used to examine the behaviour of each I/O
9184610Salfred * layer, from the syscall interface to what the disk is doing. Behaviour
10184610Salfred * such as read-ahead, and max I/O size breakup can be observed.
11184610Salfred *
12184610Salfred * This is a verbose version of fsrw.d, as this also traces paging activity.
13184610Salfred *
14184610Salfred * $Id: fspaging.d 3 2007-08-01 10:50:08Z brendan $
15184610Salfred *
16184610Salfred * USAGE:	fspaging.d
17184610Salfred *
18184610Salfred * FIELDS:
19184610Salfred *		Event		Traced event (see EVENTS below)
20184610Salfred *		Device		Device, for disk I/O
21184610Salfred *		RW		Either Read or Write
22184610Salfred *		Size		Size of I/O in bytes, if known
23184610Salfred *		Offset		Offset of I/O in kilobytes, if known
24184610Salfred *		Path		Path to file on disk
25184610Salfred *
26184610Salfred * EVENTS:
27184610Salfred *		sc-read		System call read
28184610Salfred *		sc-write	System call write
29184610Salfred *		fop_read	Logical read
30184610Salfred *		fop_write	Logical write
31184610Salfred *		fop_getpage	Logical get page
32184610Salfred *		fop_putpage	Logical put page
33184610Salfred *		disk_io		Physical disk I/O
34184610Salfred *		disk_ra		Physical disk I/O, read ahead
35184610Salfred *
36184610Salfred * The events are drawn with a level of indentation, which can sometimes
37188412Sthompsa * help identify related events.
38188412Sthompsa *
39184610Salfred * SEE ALSO: fsrw.d
40184610Salfred *
41184610Salfred * IDEA: Richard McDougall, Solaris Internals 2nd Ed, FS Chapter.
42184610Salfred *
43184610Salfred * COPYRIGHT: Copyright (c) 2006 Brendan Gregg.
44184610Salfred *
45184610Salfred * CDDL HEADER START
46184610Salfred *
47184610Salfred *  The contents of this file are subject to the terms of the
48184610Salfred *  Common Development and Distribution License, Version 1.0 only
49184610Salfred *  (the "License").  You may not use this file except in compliance
50184610Salfred *  with the License.
51184610Salfred *
52184610Salfred *  You can obtain a copy of the license at Docs/cddl1.txt
53184610Salfred *  or http://www.opensolaris.org/os/licensing.
54184610Salfred *  See the License for the specific language governing permissions
55184610Salfred *  and limitations under the License.
56184610Salfred *
57184610Salfred * CDDL HEADER END
58184610Salfred *
59184610Salfred * ToDo: readv()
60184610Salfred *
61184610Salfred * 20-Mar-2006  Brendan Gregg   Created this.
62184610Salfred * 23-Apr-2006	   "      "	Last update.
63184610Salfred */
64184610Salfred
65184610Salfred#pragma D option quiet
66184610Salfred#pragma D option switchrate=10hz
67184610Salfred
68184610Salfreddtrace:::BEGIN
69184610Salfred{
70184610Salfred	printf("%-13s %10s %2s %8s %6s %s\n",
71184610Salfred	    "Event", "Device", "RW", "Size", "Offset", "Path");
72184610Salfred}
73184610Salfred
74184610Salfredsyscall::*read:entry,
75184610Salfredsyscall::*write*:entry
76184610Salfred{
77184610Salfred	/*
78184610Salfred	 * starting with a file descriptior, dig out useful info
79194677Sthompsa	 * from the corresponding file_t and vnode_t.
80194677Sthompsa	 */
81194677Sthompsa	this->filistp = curthread->t_procp->p_user.u_finfo.fi_list;
82194677Sthompsa	this->ufentryp = (uf_entry_t *)((uint64_t)this->filistp +
83194677Sthompsa	    (uint64_t)arg0 * (uint64_t)sizeof (uf_entry_t));
84194677Sthompsa	this->filep = this->ufentryp->uf_file;
85194677Sthompsa	self->offset = this->filep->f_offset;
86194677Sthompsa	this->vnodep = this->filep != 0 ? this->filep->f_vnode : 0;
87194677Sthompsa	self->vpath = this->vnodep ? (this->vnodep->v_path != 0 ?
88194677Sthompsa	    cleanpath(this->vnodep->v_path) : "<unknown>") : "<unknown>";
89194677Sthompsa	self->sc_trace = this->vnodep ? this->vnodep->v_type == 1 ||
90194677Sthompsa	    this->vnodep->v_type == 2 ? 1 : 0 : 0;
91194677Sthompsa}
92194677Sthompsa
93194677Sthompsasyscall::*read:entry
94194677Sthompsa/self->sc_trace/
95194677Sthompsa{
96194677Sthompsa	printf("sc-%-10s %10s %2s %8d %6d %s\n", probefunc, ".", "R",
97194677Sthompsa	    (int)arg2, self->offset / 1024, self->vpath);
98194677Sthompsa}
99194677Sthompsa
100194677Sthompsasyscall::*write*:entry
101194677Sthompsa/self->sc_trace/
102188746Sthompsa{
103184610Salfred	printf("sc-%-10s %10s %2s %8d %6d %s\n", probefunc, ".", "W",
104184610Salfred	    (int)arg2, self->offset / 1024, self->vpath);
105194677Sthompsa}
106188942Sthompsa
107184610Salfredsyscall::*read:return,
108188942Sthompsasyscall::*write*:return
109188942Sthompsa{
110184610Salfred	self->vpath = 0;
111188412Sthompsa	self->offset = 0;
112188412Sthompsa	self->sc_trace = 0;
113188412Sthompsa}
114188412Sthompsa
115188412Sthompsafbt::fop_putpage:entry,
116188412Sthompsafbt::fop_getpage:entry
117188412Sthompsa/self->sc_trace && args[0]->v_path/
118188412Sthompsa{
119188412Sthompsa	printf("  %-11s %10s %2s %8d %6d %s\n", probefunc, ".",
120188412Sthompsa	    probefunc == "fop_getpage" ? "R" : "W", (uint64_t)arg2,
121188412Sthompsa	    args[1] / 1024, cleanpath(args[0]->v_path));
122188412Sthompsa}
123188412Sthompsa
124188412Sthompsa
125184610Salfredfbt::fop_read:entry,
126207077Sthompsafbt::fop_write:entry
127184610Salfred/self->sc_trace && args[0]->v_path/
128184610Salfred{
129192502Sthompsa	printf("  %-11s %10s %2s %8d %6d %s\n", probefunc, ".",
130192502Sthompsa	    probefunc == "fop_read" ? "R" : "W", args[1]->uio_resid,
131184610Salfred	    args[1]->_uio_offset._f / 1024, cleanpath(args[0]->v_path));
132184610Salfred}
133184610Salfred
134184610Salfredfbt:ufs:ufs_getpage_ra:entry
135184610Salfred{
136184610Salfred	/* fetch the real offset (file_t is unaware of this) */
137192984Sthompsa	self->offset = ((inode_t *)args[0]->v_data)->i_nextrio;
138201028Sthompsa	self->read_ahead = 1;
139201028Sthompsa}
140201028Sthompsa
141201028Sthompsafbt:ufs:ufs_getpage_ra:return
142201028Sthompsa{
143201028Sthompsa	self->read_ahead = 0;
144201028Sthompsa	self->offset = 0;
145201028Sthompsa}
146201028Sthompsa
147201028Sthompsaio::bdev_strategy:start
148201028Sthompsa{
149201028Sthompsa	this->offset = self->read_ahead ? self->offset : args[2]->fi_offset;
150201028Sthompsa	printf("    %-9s %10s %2s %8d %6d %s\n",
151201028Sthompsa	    self->read_ahead ? "disk_ra" : "disk_io", args[1]->dev_statname,
152201028Sthompsa	    args[0]->b_flags & B_READ ? "R" : "W", args[0]->b_bcount,
153201028Sthompsa	    this->offset / 1024, args[2]->fi_pathname);
154201028Sthompsa}
155201028Sthompsa