Date: Wed, 3 Dec 2014 15:19:31 -0800 From: <dteske@FreeBSD.org> To: <markj@freebsd.org> Cc: 'Devin Teske' <dteske@freebsd.org>, 'Julian Elischer' <julian@freebsd.org>, freebsd-dtrace@freebsd.org Subject: DTrace script to trace processes entering vfs::vop_remove Message-ID: <032e01d00f4f$98a04e20$c9e0ea60$@FreeBSD.org>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Hi markj, list,
I wrote a script for $work to help me find out "who on Earth
keeps deleting files XYZ?" from a particular storage server.
Please find attached a copy of watch_vop_remove.d which
has the following sample output:
2014 Dec 3 11:58:52 rm[75596]: /tmp/foo
-+= 72846 0.0 -bash
\-+= 75589 0.0 /bin/bash /usr/home/support/bash_script
\-+= 75596 0.0 rm -f /tmp/foo
The above sample output was displayed when executing the following shell
script:
#!/bin/bash
touch /tmp/foo
rm -f /tmp/foo
The output format displayed for each vop_remove() call is as follows:
DATE process[PID]: PATH_TO_DELETE
-+= GPID UID.GID grandparent_process [arguments (up to 3)]
\-+= PPID UID.GID parent_process [arguments (up to 3)]
\-+= PID UID.GID process [arguments (up to 3)]
NB: Requires "kldload dtraceall" to be performed prior to execution
--
Cheers,
Devin
[-- Attachment #2 --]
#!/usr/sbin/dtrace -s
/* -
* Copyright (c) 2014 Devin Teske <dteske@FreeBSD.org>
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Title: dtrace(1) script to log process(es) entering vfs::vop_remove $
*/
#pragma D option quiet
#pragma D option dynvarsize=16m
#pragma D option switchrate=10hz
/*********************************************************/
vfs::vop_remove:entry
{
this->vp = (struct vnode *)arg0;
this->ncp = &(this->vp->v_cache_dst) != NULL ?
this->vp->v_cache_dst.tqh_first : 0;
this->fi_name = args[1] ? (
args[1]->a_cnp != NULL ?
stringof(args[1]->a_cnp->cn_nameptr) : ""
) : "";
this->mount = this->vp->v_mount; /* ptr to vfs we are in */
this->fi_fs = this->mount != 0 ?
stringof(this->mount->mnt_stat.f_fstypename) : "";
this->fi_mount = this->mount != 0 ?
stringof(this->mount->mnt_stat.f_mntonname) : "";
this->d_name = args[0]->v_cache_dd != NULL ?
stringof(args[0]->v_cache_dd->nc_name) : "";
this->ts = timestamp;
@c = count();
}
vfs::vop_remove:entry /this->vp == 0 || this->fi_fs == 0 ||
this->fi_fs == "devfs" || this->fi_fs == "" ||
this->fi_name == ""/
{
this->ncp = 0;
}
/*********************************************************/
vfs::vop_remove:entry /this->ncp/ /* depth == 1 */
{
this->dvp = this->ncp->nc_dvp != NULL ? (
&(this->ncp->nc_dvp->v_cache_dst) != NULL ?
this->ncp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->depth = 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /self->name[1] == 0 || this->fi_fs == 0 ||
this->fi_fs == "devfs" || this->fi_fs == "" ||
self->name[1] == "/" || self->name[1] == ""/
{
this->dvp = 0;
}
/*********************************************************/
/*
* BEGIN Pathname-depth iterators (copy/paste as many times as-desired)
*/
vfs::vop_remove:entry /this->dvp/ /* depth == 2 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 3 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 4 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 5 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 6 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 7 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 8 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 9 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 10 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 11 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 12 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 13 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 14 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 15 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 16 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 17 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 18 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 19 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
vfs::vop_remove:entry /this->dvp/ /* depth == 20 */
{
this->dvp = this->dvp->nc_dvp != NULL ? (
&(this->dvp->nc_dvp->v_cache_dst) != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0
) : 0;
self->name[++self->depth] = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
/*
* END Pathname-depth iterators
*/
/*********************************************************/
vfs::vop_remove:entry /this->fi_mount != 0/
{
printf("%Y %s[%d]: ", timestamp + 1406598400000000000, execname, pid);
/*
* Print full path of file to delete
* NB: Up-to but not including the parent directory (printed below)
*/
printf("%s%s", this->fi_mount, this->fi_mount != 0 ? (
this->fi_mount == "/" ? "" : "/"
) : "/");
name = self->name[self->depth--]; /* 20 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 19 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 18 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 17 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 16 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 15 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 14 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 13 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 12 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 11 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 10 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 9 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 8 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 7 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 6 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 5 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 4 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 3 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 2 */
printf("%s%s", name, name != "" ? "/" : "");
name = self->name[self->depth--]; /* 1 */
printf("%s%s", name, name != "" ? "/" : "");
/* Print the parent directory name */
printf("%s%s", this->d_name != 0 ? this->d_name : "",
this->d_name != 0 ? "/" : "");
/* Print the entry name */
printf("%s", this->fi_name != 0 ? this->fi_name : "");
printf("\n");
/*
* Examine process, parent process, and grandparent process details
*/
/******************* CURPROC *******************/
pn = 0;
proc = curthread->td_proc;
_pid[pn] = proc->p_pid;
_uid[pn] = proc->p_ucred->cr_uid;
_gid[pn] = proc->p_ucred->cr_rgid;
p_args = proc->p_args;
ar_length = p_args ? p_args->ar_length : 0;
ar_args = (char *)(p_args ? p_args->ar_args : 0);
ad = 0;
arg[pn,ad++] = ar_length > 0 ? stringof(ar_args) : proc->p_comm;
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? "..." : "";
/******************* PPARENT *******************/
pn++;
proc = proc->p_pptr;
_pid[pn] = proc->p_pid;
_uid[pn] = proc->p_ucred->cr_uid;
_gid[pn] = proc->p_ucred->cr_rgid;
p_args = proc ? proc->p_args : 0;
ar_length = p_args ? p_args->ar_length : 0;
ar_args = (char *)(p_args ? p_args->ar_args : 0);
ad = 0;
offset = 0;
arg[pn,ad++] = ar_length > 0 ? ar_args : proc->p_comm;
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? "..." : "";
/******************* GPARENT *******************/
pn++;
proc = proc->p_pptr;
_pid[pn] = proc->p_pid;
_uid[pn] = proc->p_ucred->cr_uid;
_gid[pn] = proc->p_ucred->cr_rgid;
p_args = proc ? proc->p_args : 0;
ar_length = p_args ? p_args->ar_length : 0;
ar_args = (char *)(p_args ? p_args->ar_args : 0);
ad = 0;
offset = 0;
arg[pn,ad++] = ar_length > 0 ? ar_args : proc->p_comm;
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? ar_args : "";
len = ar_length > 0 ? strlen(ar_args) + 1 : 0;
ar_args += len;
ar_length -= len;
arg[pn,ad++] = ar_length > 0 ? "..." : "";
/***********************************************/
/*
* Print process, parent, and grandparent details
*/
printf(" -+= %05d %d.%d %s", _pid[pn], _uid[pn], _gid[pn], arg[pn,0]);
printf("%s%s", arg[pn,1] != "" ? " " : "", arg[pn,1]);
printf("%s%s", arg[pn,2] != "" ? " " : "", arg[pn,2]);
printf("%s%s", arg[pn,3] != "" ? " " : "", arg[pn,3]);
printf("%s%s", arg[pn,4] != "" ? " " : "", arg[pn,4]);
printf("%s", arg[pn,0] != "" ? "\n" : "");
pn--;
printf(" \-+= %05d %d.%d %s",
_pid[pn], _uid[pn], _gid[pn], arg[pn,0]);
printf("%s%s", arg[pn,1] != "" ? " " : "", arg[pn,1]);
printf("%s%s", arg[pn,2] != "" ? " " : "", arg[pn,2]);
printf("%s%s", arg[pn,3] != "" ? " " : "", arg[pn,3]);
printf("%s%s", arg[pn,4] != "" ? " " : "", arg[pn,4]);
printf("%s", arg[pn,0] != "" ? "\n" : "");
pn--;
printf(" \-+= %05d %d.%d %s",
_pid[pn], _uid[pn], _gid[pn], arg[pn,0]);
printf("%s%s", arg[pn,1] != "" ? " " : "", arg[pn,1]);
printf("%s%s", arg[pn,2] != "" ? " " : "", arg[pn,2]);
printf("%s%s", arg[pn,3] != "" ? " " : "", arg[pn,3]);
printf("%s%s", arg[pn,4] != "" ? " " : "", arg[pn,4]);
printf("%s", arg[pn,0] != "" ? "\n" : "");
}
/*********************************************************/
vfs::vop_remove:entry
{
self->name[self->depth++] = 0;
self->name[2] = 0;
self->name[3] = 0;
self->name[4] = 0;
self->name[5] = 0;
self->name[6] = 0;
self->name[7] = 0;
self->name[8] = 0;
self->name[9] = 0;
self->name[10] = 0;
self->name[11] = 0;
self->name[12] = 0;
self->name[13] = 0;
self->name[14] = 0;
self->name[15] = 0;
self->name[16] = 0;
self->name[17] = 0;
self->name[18] = 0;
self->name[19] = 0;
self->name[20] = 0;
self->depth = 0;
}
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?032e01d00f4f$98a04e20$c9e0ea60$>
