Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Sep 2007 22:14:52 GMT
From:      Zach Loafman <zachary.loafman@isilon.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/116679: lockd replies with DENIED for blocking lock if held by underlying FS
Message-ID:  <200709262214.l8QMEqVt000224@www.freebsd.org>
Resent-Message-ID: <200709262220.l8QMK25s029071@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         116679
>Category:       kern
>Synopsis:       lockd replies with DENIED for blocking lock if held by underlying FS
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 26 22:20:02 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Zach Loafman
>Release:        6.1-RELEASE
>Organization:
Isilon Systems
>Environment:
FreeBSD you.dont.care 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Sun May  7 04:32:43 UTC 2006     root@opus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
If lockd gets a request to an NLM request to lock a file but the non-blocking lockf() call on the exported file system fails, lockd will reply with NLM4_DENIED. In this situation, lockd needs to return NLM4_BLOCKED and actually set up some sort of structure to deal with it (however, there exists no way for the FS to notify lockd that the lock could be acquired).

The result of this is that an NFS client may try for a blocking lock, but still get EAGAIN ("Resource temporarily unavailable"), which is counter-intuitive. 
>How-To-Repeat:
# cat > locker_two_path.c <<EOF
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

static void
do_lock(int fd, int exclusive, int waitok)
{
	int rc;
	time_t start_time;
	struct flock flock;

	start_time = time(0);

	flock.l_start = 0;
	flock.l_len = 0;
	flock.l_type = exclusive ? F_WRLCK : F_RDLCK;
	flock.l_whence = SEEK_SET;
	rc = fcntl(fd, waitok ? F_SETLKW : F_SETLK,
	    &flock);
	if (rc < 0) {
		perror("fcntl lock");
		exit(1);
	}

	printf("%d: waited %d seconds for lock\n",
	    getpid(), time(0) - start_time);
}

int
main(int argc, char *argv[])
{
	int local_fd, nfs_fd;

	if (argc != 3) {
		printf("usage: %s <local path> <nfs path>", argv[0]);
		exit(1);
	}

	local_fd = open(argv[1], O_RDWR|O_CREAT, 0666);
	if (local_fd < 0) {
		perror("open");
		exit(1);
	}

	nfs_fd = open(argv[2], O_RDWR|O_CREAT, 0666);
	if (nfs_fd < 0) {
		perror("open");
		exit(1);
	}

	do_lock(local_fd, 1, 1);
	do_lock(nfs_fd, 1, 1);
	
	return 0;
}
EOF

# cc -Wall -o locker_two_path locker_two_path.c
# mount -otcp,intr localhost:/local /mnt/test
# ./locker_two_path /local/foobar /mnt/test/foobar
99086: waited 0 seconds for lock
fcntl lock: Resource temporarily unavailable

>Fix:
Serious work.

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200709262214.l8QMEqVt000224>