1#!/usr/sbin/dtrace -s
2/* -
3 * Copyright (c) 2014 Devin Teske <dteske@FreeBSD.org>
4 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Title: dtrace(1) script to log process(es) entering vfs::vop_remove $
27 * $FreeBSD$
28 */
29
30#pragma D option quiet
31#pragma D option dynvarsize=16m
32#pragma D option switchrate=10hz
33
34/*********************************************************/
35
36vfs::vop_remove:entry /* probe ID 1 */
37{
38	this->vp = (struct vnode *)arg0;
39	this->ncp = &(this->vp->v_cache_dst) != NULL ?
40		this->vp->v_cache_dst.tqh_first : 0;
41        this->fi_name = args[1] ? (
42		args[1]->a_cnp != NULL ?
43			stringof(args[1]->a_cnp->cn_nameptr) : ""
44	) : "";
45	this->mount = this->vp->v_mount; /* ptr to vfs we are in */
46	this->fi_fs = this->mount != 0 ?
47		stringof(this->mount->mnt_stat.f_fstypename) : "";
48	this->fi_mount = this->mount != 0 ?
49		stringof(this->mount->mnt_stat.f_mntonname) : "";
50	this->d_name = args[0]->v_cache_dd != NULL ?
51		stringof(args[0]->v_cache_dd->nc_name) : "";
52}
53
54vfs::vop_remove:entry /this->vp == 0 || this->fi_fs == 0 ||
55	this->fi_fs == "devfs" || this->fi_fs == "" ||
56	this->fi_name == ""/ /* probe ID 2 */
57{
58	this->ncp = 0;
59}
60
61/*********************************************************/
62
63vfs::vop_remove:entry /this->ncp/ /* probe ID 3 (depth 1) */
64{
65	this->dvp = this->ncp->nc_dvp != NULL ? (
66		&(this->ncp->nc_dvp->v_cache_dst) != NULL ?
67			this->ncp->nc_dvp->v_cache_dst.tqh_first : 0
68	) : 0;
69	this->name1 = this->dvp != 0 ? (
70		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
71	) : "";
72}
73
74vfs::vop_remove:entry /this->name1 == 0 || this->fi_fs == 0 ||
75	this->fi_fs == "devfs" || this->fi_fs == "" ||
76	this->name1 == "/" || this->name1 == ""/ /* probe ID 4 */
77{
78	this->dvp = 0;
79}
80
81/*********************************************************/
82
83/*
84 * BEGIN Pathname-depth iterators (copy/paste as many times as-desired)
85 */
86
87vfs::vop_remove:entry /this->dvp/ /* probe ID 5 (depth 2) */
88{
89	this->dvp = this->dvp->nc_dvp != NULL ? (
90		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
91			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
92	) : 0;
93	this->name2 = this->dvp != 0 ? (
94		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
95	) : "";
96}
97
98vfs::vop_remove:entry /this->dvp/ /* probe ID 6 (depth 3) */
99{
100	this->dvp = this->dvp->nc_dvp != NULL ? (
101		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
102			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
103	) : 0;
104	this->name3 = this->dvp != 0 ? (
105		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
106	) : "";
107}
108
109vfs::vop_remove:entry /this->dvp/ /* probe ID 7 (depth 4) */
110{
111	this->dvp = this->dvp->nc_dvp != NULL ? (
112		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
113			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
114	) : 0;
115	this->name4 = this->dvp != 0 ? (
116		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
117	) : "";
118}
119
120vfs::vop_remove:entry /this->dvp/ /* probe ID 8 (depth 5) */
121{
122	this->dvp = this->dvp->nc_dvp != NULL ? (
123		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
124			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
125	) : 0;
126	this->name5 = this->dvp != 0 ? (
127		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
128	) : "";
129}
130
131vfs::vop_remove:entry /this->dvp/ /* probe ID 9 (depth 6) */
132{
133	this->dvp = this->dvp->nc_dvp != NULL ? (
134		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
135			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
136	) : 0;
137	this->name6 = this->dvp != 0 ? (
138		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
139	) : "";
140}
141
142vfs::vop_remove:entry /this->dvp/ /* probe ID 10 (depth 7) */
143{
144	this->dvp = this->dvp->nc_dvp != NULL ? (
145		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
146			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
147	) : 0;
148	this->name7 = this->dvp != 0 ? (
149		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
150	) : "";
151}
152
153vfs::vop_remove:entry /this->dvp/ /* probe ID 11 (depth 8) */
154{
155	this->dvp = this->dvp->nc_dvp != NULL ? (
156		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
157			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
158	) : 0;
159	this->name8 = this->dvp != 0 ? (
160		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
161	) : "";
162}
163
164vfs::vop_remove:entry /this->dvp/ /* probe ID 12 (depth 9) */
165{
166	this->dvp = this->dvp->nc_dvp != NULL ? (
167		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
168			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
169	) : 0;
170	this->name9 = this->dvp != 0 ? (
171		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
172	) : "";
173}
174
175vfs::vop_remove:entry /this->dvp/ /* probe ID 13 (depth 10) */
176{
177	this->dvp = this->dvp->nc_dvp != NULL ? (
178		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
179			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
180	) : 0;
181	this->name10 = this->dvp != 0 ? (
182		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
183	) : "";
184}
185
186vfs::vop_remove:entry /this->dvp/ /* probe ID 14 (depth 11) */
187{
188	this->dvp = this->dvp->nc_dvp != NULL ? (
189		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
190			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
191	) : 0;
192	this->name11 = this->dvp != 0 ? (
193		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
194	) : "";
195}
196
197vfs::vop_remove:entry /this->dvp/ /* probe ID 15 (depth 12) */
198{
199	this->dvp = this->dvp->nc_dvp != NULL ? (
200		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
201			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
202	) : 0;
203	this->name12 = this->dvp != 0 ? (
204		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
205	) : "";
206}
207
208vfs::vop_remove:entry /this->dvp/ /* probe ID 16 (depth 13) */
209{
210	this->dvp = this->dvp->nc_dvp != NULL ? (
211		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
212			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
213	) : 0;
214	this->name13 = this->dvp != 0 ? (
215		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
216	) : "";
217}
218
219vfs::vop_remove:entry /this->dvp/ /* probe ID 17 (depth 14) */
220{
221	this->dvp = this->dvp->nc_dvp != NULL ? (
222		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
223			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
224	) : 0;
225	this->name14 = this->dvp != 0 ? (
226		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
227	) : "";
228}
229
230vfs::vop_remove:entry /this->dvp/ /* probe ID 18 (depth 15) */
231{
232	this->dvp = this->dvp->nc_dvp != NULL ? (
233		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
234			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
235	) : 0;
236	this->name15 = this->dvp != 0 ? (
237		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
238	) : "";
239}
240
241vfs::vop_remove:entry /this->dvp/ /* probe ID 19 (depth 16) */
242{
243	this->dvp = this->dvp->nc_dvp != NULL ? (
244		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
245			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
246	) : 0;
247	this->name16 = this->dvp != 0 ? (
248		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
249	) : "";
250}
251
252vfs::vop_remove:entry /this->dvp/ /* probe ID 20 (depth 17) */
253{
254	this->dvp = this->dvp->nc_dvp != NULL ? (
255		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
256			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
257	) : 0;
258	this->name17 = this->dvp != 0 ? (
259		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
260	) : "";
261}
262
263vfs::vop_remove:entry /this->dvp/ /* probe ID 21 (depth 18) */
264{
265	this->dvp = this->dvp->nc_dvp != NULL ? (
266		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
267			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
268	) : 0;
269	this->name18 = this->dvp != 0 ? (
270		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
271	) : "";
272}
273
274vfs::vop_remove:entry /this->dvp/ /* probe ID 22 (depth 19) */
275{
276	this->dvp = this->dvp->nc_dvp != NULL ? (
277		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
278			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
279	) : 0;
280	this->name19 = this->dvp != 0 ? (
281		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
282	) : "";
283}
284
285vfs::vop_remove:entry /this->dvp/ /* probe ID 23 (depth 20) */
286{
287	this->dvp = this->dvp->nc_dvp != NULL ? (
288		&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
289			this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
290	) : 0;
291	this->name20 = this->dvp != 0 ? (
292		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
293	) : "";
294}
295
296/*
297 * END Pathname-depth iterators
298 */
299
300/*********************************************************/
301
302vfs::vop_remove:entry /this->fi_mount != 0/ /* probe ID 24 */
303{
304	printf("%Y %s[%d]: ", timestamp + 1406598400000000000, execname, pid);
305
306	/*
307	 * Print full path of file to delete
308	 * NB: Up-to but not including the parent directory (printed below)
309	 */
310	printf("%s%s", this->fi_mount, this->fi_mount != 0 ? (
311		this->fi_mount == "/" ? "" : "/"
312	) : "/");
313	printf("%s%s", this->name = this->name20, this->name != "" ? "/" : "");
314	printf("%s%s", this->name = this->name19, this->name != "" ? "/" : "");
315	printf("%s%s", this->name = this->name18, this->name != "" ? "/" : "");
316	printf("%s%s", this->name = this->name17, this->name != "" ? "/" : "");
317	printf("%s%s", this->name = this->name16, this->name != "" ? "/" : "");
318	printf("%s%s", this->name = this->name15, this->name != "" ? "/" : "");
319	printf("%s%s", this->name = this->name14, this->name != "" ? "/" : "");
320	printf("%s%s", this->name = this->name13, this->name != "" ? "/" : "");
321	printf("%s%s", this->name = this->name12, this->name != "" ? "/" : "");
322	printf("%s%s", this->name = this->name11, this->name != "" ? "/" : "");
323	printf("%s%s", this->name = this->name10, this->name != "" ? "/" : "");
324	printf("%s%s", this->name = this->name9, this->name != "" ? "/" : "");
325	printf("%s%s", this->name = this->name8, this->name != "" ? "/" : "");
326	printf("%s%s", this->name = this->name7, this->name != "" ? "/" : "");
327	printf("%s%s", this->name = this->name6, this->name != "" ? "/" : "");
328	printf("%s%s", this->name = this->name5, this->name != "" ? "/" : "");
329	printf("%s%s", this->name = this->name4, this->name != "" ? "/" : "");
330	printf("%s%s", this->name = this->name3, this->name != "" ? "/" : "");
331	printf("%s%s", this->name = this->name2, this->name != "" ? "/" : "");
332	printf("%s%s", this->name = this->name1, this->name != "" ? "/" : "");
333
334	/* Print the parent directory name */
335	this->name = this->d_name != 0 ? this->d_name : "";
336	printf("%s%s", this->name, this->name != "" ? "/" : "");
337
338	/* Print the entry name */
339	this->name = this->fi_name != 0 ? this->fi_name : "";
340	printf("%s", this->name);
341
342	printf("\n");
343
344	/*
345	 * Examine process, parent process, and grandparent process details
346	 */
347
348	/******************* CURPROC *******************/
349
350	this->proc = curthread->td_proc;
351	this->pid0 = this->proc->p_pid;
352	this->uid0 = this->proc->p_ucred->cr_uid;
353	this->gid0 = this->proc->p_ucred->cr_rgid;
354	this->p_args = this->proc->p_args;
355	this->ar_length = this->p_args ? this->p_args->ar_length : 0;
356	this->ar_args = (char *)(this->p_args ? this->p_args->ar_args : 0);
357
358	this->arg0_0 = this->ar_length > 0 ?
359		this->ar_args : stringof(this->proc->p_comm);
360	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
361	this->ar_args += this->len;
362	this->ar_length -= this->len;
363
364	this->arg0_1 = this->ar_length > 0 ? this->ar_args : "";
365	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
366	this->ar_args += this->len;
367	this->ar_length -= this->len;
368
369	this->arg0_2 = this->ar_length > 0 ? this->ar_args : "";
370	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
371	this->ar_args += this->len;
372	this->ar_length -= this->len;
373
374	this->arg0_3 = this->ar_length > 0 ? this->ar_args : "";
375	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
376	this->ar_args += this->len;
377	this->ar_length -= this->len;
378
379	this->arg0_4 = this->ar_length > 0 ? "..." : "";
380
381	/******************* PPARENT *******************/
382
383	this->proc = this->proc->p_pptr;
384	this->pid1 = this->proc->p_pid;
385	this->uid1 = this->proc->p_ucred->cr_uid;
386	this->gid1 = this->proc->p_ucred->cr_rgid;
387	this->p_args = this->proc ? this->proc->p_args : 0;
388	this->ar_length = this->p_args ? this->p_args->ar_length : 0;
389	this->ar_args = (char *)(this->p_args ? this->p_args->ar_args : 0);
390
391	this->arg1_0 = this->ar_length > 0 ?
392		this->ar_args : stringof(this->proc->p_comm);
393	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
394	this->ar_args += this->len;
395	this->ar_length -= this->len;
396
397	this->arg1_1 = this->ar_length > 0 ? this->ar_args : "";
398	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
399	this->ar_args += this->len;
400	this->ar_length -= this->len;
401
402	this->arg1_2 = this->ar_length > 0 ? this->ar_args : "";
403	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
404	this->ar_args += this->len;
405	this->ar_length -= this->len;
406
407	this->arg1_3 = this->ar_length > 0 ? this->ar_args : "";
408	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
409	this->ar_args += this->len;
410	this->ar_length -= this->len;
411
412	this->arg1_4 = this->ar_length > 0 ? "..." : "";
413
414	/******************* GPARENT *******************/
415
416	this->proc = this->proc->p_pptr;
417	this->pid2 = this->proc->p_pid;
418	this->uid2 = this->proc->p_ucred->cr_uid;
419	this->gid2 = this->proc->p_ucred->cr_rgid;
420	this->p_args = this->proc ? this->proc->p_args : 0;
421	this->ar_length = this->p_args ? this->p_args->ar_length : 0;
422	this->ar_args = (char *)(this->p_args ? this->p_args->ar_args : 0);
423
424	this->arg2_0 = this->ar_length > 0 ?
425		this->ar_args : stringof(this->proc->p_comm);
426	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
427	this->ar_args += this->len;
428	this->ar_length -= this->len;
429
430	this->arg2_1 = this->ar_length > 0 ? this->ar_args : "";
431	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
432	this->ar_args += this->len;
433	this->ar_length -= this->len;
434
435	this->arg2_2 = this->ar_length > 0 ? this->ar_args : "";
436	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
437	this->ar_args += this->len;
438	this->ar_length -= this->len;
439
440	this->arg2_3 = this->ar_length > 0 ? this->ar_args : "";
441	this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0;
442	this->ar_args += this->len;
443	this->ar_length -= this->len;
444
445	this->arg2_4 = this->ar_length > 0 ? "..." : "";
446
447	/***********************************************/
448
449	/*
450	 * Print process, parent, and grandparent details
451	 */
452
453	printf(" -+= %05d %d.%d %s",
454		this->pid2, this->uid2, this->gid2, this->arg2_0);
455	printf("%s%s", this->arg2_1 != "" ? " " : "", this->arg2_1);
456	printf("%s%s", this->arg2_2 != "" ? " " : "", this->arg2_2);
457	printf("%s%s", this->arg2_3 != "" ? " " : "", this->arg2_3);
458	printf("%s%s", this->arg2_4 != "" ? " " : "", this->arg2_4);
459	printf("%s", this->arg2_0 != "" ? "\n" : "");
460
461	printf("  \-+= %05d %d.%d %s",
462		this->pid1, this->uid1, this->gid1, this->arg1_0);
463	printf("%s%s", this->arg1_1 != "" ? " " : "", this->arg1_1);
464	printf("%s%s", this->arg1_2 != "" ? " " : "", this->arg1_2);
465	printf("%s%s", this->arg1_3 != "" ? " " : "", this->arg1_3);
466	printf("%s%s", this->arg1_4 != "" ? " " : "", this->arg1_4);
467	printf("%s", this->arg1_0 != "" ? "\n" : "");
468
469	printf("    \-+= %05d %d.%d %s",
470		this->pid0, this->uid0, this->gid0, this->arg0_0);
471	printf("%s%s", this->arg0_1 != "" ? " " : "", this->arg0_1);
472	printf("%s%s", this->arg0_2 != "" ? " " : "", this->arg0_2);
473	printf("%s%s", this->arg0_3 != "" ? " " : "", this->arg0_3);
474	printf("%s%s", this->arg0_4 != "" ? " " : "", this->arg0_4);
475	printf("%s", this->arg0_0 != "" ? "\n" : "");
476}
477