Re: NFSv4 file lock reporting interface request

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 07 Aug 2018, J. Bruce Fields wrote:

> On Thu, Aug 02, 2018 at 08:50:20PM +0200, Cedric Blancher wrote:
> > Solaris and FreeBSD dtrace facility supports this functionality.
> > Unfortunately, Linux rejected dtrace for license issues, and instead
> > did... nothing.
> 
> I didn't think was this sort of question tracing was designed to
> answer--it's a question about the system state at a given time (who
> holds what locks), rather than a list of events.  But I know nothing
> about dtrace.

FWIW a couple of years ago I wrote a systemtap script (attached) that
dumps out some NFSv4 state info (mostly lock info) from nfsd.  I ran
it on a recent RHEL 7 kernel and it still works, so it should work on
Centos 7.

-Scott

> 
> --b.
> 
> > 
> > Ced
> > 
> > On 10 July 2018 at 04:28, Peter Scott <pjscott@xxxxxxxxxxxx> wrote:
> > > Hello.  I am with the institutional hosting service at NASA's Jet Propulsion
> > > Laboratory and we have been trying to find the answer to an apparently
> > > simple question.
> > >
> > > We are running an NFSv4 server on Centos 7 and we need to get the server to
> > > tell us which files it thinks are locked by which clients.  This is because
> > > we have observed failure modes where something apparently has a lock
> > > (because attempting to lock the file again blocks) but we can't find a
> > > client that has the lock. Finding out what the server believes would be
> > > critical to troubleshooting this.
> > >
> > > We tracked down Trond Myklebust and Neil Brown and conversation suggests
> > > that this is a function that is (a) not currently available and (b)
> > > reasonable to ask for.  So this is me suggesting that an interface be
> > > provided to have knfsd output its list of locked files and clients.
> > >
> > > Regards,
> > > Peter Scott
> > > Office of the CIO
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> > > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > 
> > 
> > -- 
> > Cedric Blancher <cedric.blancher@xxxxxxxxx>
> > [https://plus.google.com/u/0/+CedricBlancher/]
> > Institute Pasteur
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
#!/usr/bin/env stap
/*
 * nfsd4.stp: Systemtap script to dump out a lot of nfs4 state info
 *            (RHEL 7 only, sorry)
 *
 * Author: Scott Mayhew <smayhew@xxxxxxxxxx>
 *
 * Usage: stap -g nfsd4.stp
 *
 */

global width = 3

function output(depth:long, msg:string)
{
	printf("%*s%s\n", depth*width, "", msg)
}

%{
#include <linux/fs.h>
%}

function fl_type_str:string(type:long)
%{
	long type = (long)STAP_ARG_type;
	int len;
	STAP_RETVALUE[0] = '\0';
	switch (type) {
	case F_RDLCK:
		strlcat(STAP_RETVALUE, "F_RDLCK", MAXSTRINGLEN);
		break;
	case F_WRLCK:
		strlcat(STAP_RETVALUE, "F_WRLCK", MAXSTRINGLEN);
		break;
	case F_UNLCK:
		strlcat(STAP_RETVALUE, "F_UNLCK", MAXSTRINGLEN);
		break;
	}
	len = strlen(STAP_RETVALUE);
	if (len)
		STAP_RETVALUE[len] = '\0';
	else
		strlcat(STAP_RETVALUE, "0", MAXSTRINGLEN);

%}

function fl_flags_str:string(flags:long)
%{
	long flags = (long)STAP_ARG_flags;
	int len;
	STAP_RETVALUE[0] = '\0';
	if (flags & FL_POSIX)
		strlcat(STAP_RETVALUE, "FL_POSIX|", MAXSTRINGLEN);
	if (flags & FL_FLOCK)
		strlcat(STAP_RETVALUE, "FL_FLOCK|", MAXSTRINGLEN);
	if (flags & FL_DELEG)
		strlcat(STAP_RETVALUE, "FL_DELEG|", MAXSTRINGLEN);
	if (flags & FL_ACCESS)
		strlcat(STAP_RETVALUE, "FL_ACCESS|", MAXSTRINGLEN);
	if (flags & FL_EXISTS)
		strlcat(STAP_RETVALUE, "FL_EXISTS|", MAXSTRINGLEN);
	if (flags & FL_LEASE)
		strlcat(STAP_RETVALUE, "FL_LEASE|", MAXSTRINGLEN);
	if (flags & FL_CLOSE)
		strlcat(STAP_RETVALUE, "FL_CLOSE|", MAXSTRINGLEN);
	if (flags & FL_SLEEP)
		strlcat(STAP_RETVALUE, "FL_SLEEP|", MAXSTRINGLEN);
	if (flags & FL_DOWNGRADE_PENDING)
		strlcat(STAP_RETVALUE, "FL_DOWNGRADE_PENDING|", MAXSTRINGLEN);
	if (flags & FL_UNLOCK_PENDING)
		strlcat(STAP_RETVALUE, "FL_UNLOCK_PENDING|", MAXSTRINGLEN);
	if (flags & FL_LAYOUT)
		strlcat(STAP_RETVALUE, "FL_LAYOUT|", MAXSTRINGLEN);
	len = strlen(STAP_RETVALUE);
	if (len)
		STAP_RETVALUE[len - 1] = '\0';
	else
		strlcat(STAP_RETVALUE, "0", MAXSTRINGLEN);
%}

function net_generic:long(net:long, id:long)
{
	ng = rcu_dereference(@cast(net, "net")->gen)
	ptr = @cast(ng, "net_generic")->ptr[id-1]
	return(ptr)
}

function print_file_lock_info(filp, lo)
{
	output(4, sprintf("filp: %p", filp))
	d = @cast(filp, "file")->f_path->dentry
	output(5, sprintf("dentry: %p", d))
	output(6, sprintf("d_name: %s", d_name(d)))
	i = @cast(filp, "file")->f_inode
	output(5, sprintf("inode: %p", i))
	output(6, sprintf("ino: %d", @cast(i, "inode")->i_ino))
	fl = @cast(i, "inode")->i_flock
	while (fl != 0) {
		if (@cast(fl, "file_lock")->fl_owner == lo) {
			output(6, sprintf("file_lock: %p", fl))
			output(7, sprintf("fl_owner: %p", @cast(fl, "file_lock")->fl_owner))
			output(7, sprintf("fl_flags: %s", fl_flags_str(@cast(fl, "file_lock")->fl_flags)))
			output(7, sprintf("fl_type: %s", fl_type_str(@cast(fl, "file_lock")->fl_type)))
			output(7, sprintf("fl_start: %x", @cast(fl, "file_lock")->fl_start))
			output(7, sprintf("fl_end: %x", @cast(fl, "file_lock")->fl_end))
			o = @cast(fl, "file_lock")->fl_lmops
			output(7, sprintf("fl_lmops: %p", o))
		}
		fl = @cast(fl, "file_lock")->fl_next
	}
}

function print_nfs4_lock_stateid(stp:long)
{
	lo = @cast(stp, "nfs4_ol_stateid", "nfsd")->st_stateowner
	output(4, sprintf("nfs4_lockowner: %p", lo))
	for (i = 2; i >=0; i--) {
		filp = @cast(stp, "nfs4_ol_stateid", "nfsd")->st_stid->sc_file->fi_fds[i]
		if (filp != 0) {
			print_file_lock_info(filp, lo)
			break
		}
	}
}

function print_nfs4_openowner(oop:long)
{
	st_next = &@cast(oop, "nfs4_openowner", "nfsd")->oo_owner->so_stateids->next
	n = st_next
	while (@cast(n, "list_head")->next != st_next) {
		n = @cast(n, "list_head")->next
		stp = &@module_container_of(n, "nfsd", "nfs4_ol_stateid", st_perstateowner)
		output(3, sprintf("open stateid: %p", stp))
		lst_next = &@cast(stp, "nfs4_ol_stateid", "nfsd")->st_locks->next
		m = lst_next
		while (@cast(m, "list_head")->next != lst_next) {
			m = @cast(m, "list_head")->next
			lst = &@module_container_of(m, "nfsd", "nfs4_ol_stateid", st_locks)
			output(3, sprintf("lock stateid: %p", lst))
			print_nfs4_lock_stateid(lst)
		}
	}
}

function print_nfs4_client(clp:long)
{
	a = &@cast(clp, "nfs4_client", "nfsd")->cl_addr
	if (@cast(a, "sockaddr")->sa_family == 2) {
		output(2, sprintf("cl_addr: %s",
				format_ipaddr(@cast(a, "sockaddr_in")->sin_addr->s_addr, 2)))
        } else if (@cast(a, "sockaddr")->sa_family == 10) {
		output(2, sprintf("cl_addr: [%s]",
				format_ipaddr(&@cast(a, "sockaddr_in6")->sin6_addr, 10)))
	}
	cl_openowners = &@cast(clp, "nfs4_client", "nfsd")->cl_openowners
	n = cl_openowners
	while (@cast(n, "list_head")->next != cl_openowners) {
		n = @cast(n, "list_head")->next
		oop = &@module_container_of(n, "nfsd", "nfs4_openowner", oo_perclient)
		output(2, sprintf("nfs4_openowner: %p", oop))
		print_nfs4_openowner(oop)
	}
}

probe begin
{
	nfsd_net_id = kernel_int(&@var("nfsd_net_id@fs/nfsd/nfsctl.c", "nfsd"))
	output(0, sprintf("nfsd_net_id: %d", nfsd_net_id))
	nfsd_net = net_generic(&@var("init_net@net/core/net_namespace.c"), nfsd_net_id)
	output(0, sprintf("nfsd_net: %p", nfsd_net))
	client_lru = &@cast(nfsd_net, "nfsd_net", "nfsd")->client_lru
	output(0, sprintf("client_lru: %p", client_lru))
	n = client_lru
	while (@cast(n, "list_head")->next != client_lru) {
		n = @cast(n, "list_head")->next
		clp = &@module_container_of(n, "nfsd", "nfs4_client", cl_lru)
		output(1, sprintf("nfs4_client: %p", clp))
		print_nfs4_client(clp)
	}
	exit()
}

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux