lkml.org 
[lkml]   [1998]   [Aug]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: NFS file locking broken (take 2)


On Sat, 22 Aug 1998, Bill Hawes wrote:

> Steven N. Hirsch wrote:
>
> > I built and installed HJ's latest userland knfs utitilities in hopes that
> > file locking would work. No luck.

> Hi Steve,
>
> I'd like to track down the NFS locking problems you've reported, and wondered
> if you could send a copy of the script you're using for testing, or any other
> simple example to illustrate the problem.
>
> I don't use NFS locking for everyday work, but have tested it in the past
> with seeming success, so my assumption is that some recent change has caused
> (or simply revealed) the problem.

Hi Bill,


HJ Liu confirmed that things were, in fact, broken. I've attached his
kernel patch (modified slightly to apply against 2.1.117) which seems to
set things straight.

> Any idea which kernel release first showed the locking problems?

None whatever. I never even tried locking until 2.1.116!

It would be lovely if you, Alan and hj could pool your efforts towards
squashing the few remaining NFS bugs. Echoing the sentiments of others,
I'd say that the improved performance will be a major motivation behind
the typical Linux user upgrading to 2.2. I'd hate to see it get a bad rap
because of a few warts.

Alan had asked about repeatable bugs. The only ones that I've observed
across multiple kernel versions (~2.1.7x through present) are:

- Occasional file corruption and truncation when copying files from client
to server. This is incredibly rare, and I've found no good way to
reproduce it. Since it is never accompanied by error messages, I usually
find out later when, e.g. attempts at unpacking a downloaded tarball fail
with "tar archive truncated.." messages.

n.b. Alan: The Ooops's didn't appear until 2.1.117, AFAIK. They have not
been a longstanding issue.

- More commonly, a mass 'cp -a' of the entire kernel source tree from
server to client will result in one or more target directories being
completely empty. Again, not easily reproducible and no error messages.

- When building the kernel on an NFS mounted directory, a 'make mrproper'
will sometimes fail with numerous complaints about "files in use" when
trying to remove the linux/include/config hierarchy. Usually, the second
attempt succeeds.

I know this is not much to go on, but perhaps it may suggest a set of
functions to instrument? Again, these are quite rare but have persisted
over quite a number of kernel revs.

Steve




--- linux/fs/lockd/host.c.orig Wed Apr 23 22:01:26 1997
+++ linux/fs/lockd/host.c Sat Aug 22 17:54:49 1998
@@ -180,12 +180,15 @@
host->h_nextrebind - jiffies);
}
} else {
- uid_t saved_euid = current->euid;
+ uid_t saved_fsuid = current->fsuid;
+ kernel_cap_t saved_cap = current->cap_effective;

/* Create RPC socket as root user so we get a priv port */
- current->euid = 0;
+ current->fsuid = 0;
+ cap_raise (current->cap_effective, CAP_NET_BIND_SERVICE);
xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
- current->euid = saved_euid;
+ current->fsuid = saved_fsuid;
+ current->cap_effective = saved_cap;
if (xprt == NULL)
goto forgetit;

--- linux/include/linux/nfsd/const.h.orig Sat Aug 22 15:22:07 1998
+++ linux/include/linux/nfsd/const.h Sat Aug 22 17:54:49 1998
@@ -10,10 +10,14 @@
#define __NFSCONST_H__

#include <linux/limits.h>
+#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/dirent.h>
#include <linux/fs.h>
+#else
+#include <linux/nfs_fs.h>
+#endif
#include <linux/nfs.h>

/*
--- linux/include/linux/nfsd/export.h.orig Sat Aug 22 15:22:23 1998
+++ linux/include/linux/nfsd/export.h Sat Aug 22 17:54:49 1998
@@ -10,11 +10,6 @@
#ifndef NFSD_EXPORT_H
#define NFSD_EXPORT_H

-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/fs.h>
-
/*
* Important limits for the exports stuff.
*/
@@ -39,6 +34,11 @@


#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/fs.h>

/* The following are hashtable sizes and must be powers of 2 */
#define NFSCLNT_EXPMAX 16
--- linux/include/linux/nfsd/nfsfh.h.orig Sat Aug 22 15:22:07 1998
+++ linux/include/linux/nfsd/nfsfh.h Sat Aug 22 17:54:49 1998
@@ -14,11 +14,17 @@
#ifndef NFSD_FH_H
#define NFSD_FH_H

+#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/nfsd/const.h>
#include <linux/nfsd/debug.h>
+#else
+#include <asm/posix_types.h>
+#include <asm/types.h>
+#include <linux/nfs.h>
+#endif

/*
* This is the new "dentry style" Linux NFSv2 file handle.
--- linux/include/linux/nfsd/syscall.h.orig Sat Aug 22 15:33:05 1998
+++ linux/include/linux/nfsd/syscall.h Sat Aug 22 17:56:28 1998
@@ -9,14 +9,16 @@
#ifndef NFSD_SYSCALL_H
#define NFSD_SYSCALL_H

+#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h>
#include <linux/socket.h>
+#include <linux/nfsd/auth.h>
+#endif
#include <linux/posix_types.h>
#include <linux/nfsd/const.h>
#include <linux/nfsd/export.h>
#include <linux/nfsd/nfsfh.h>
-#include <linux/nfsd/auth.h>

/*
* Version of the syscall interface
--- linux/include/linux/sunrpc/debug.h.orig Sat Aug 22 15:06:48 1998
+++ linux/include/linux/sunrpc/debug.h Sat Aug 22 17:54:49 1998
@@ -9,8 +9,10 @@
#ifndef _LINUX_SUNRPC_DEBUG_H_
#define _LINUX_SUNRPC_DEBUG_H_

+#if 0
#include <linux/timer.h>
#include <linux/tqueue.h>
+#endif

/*
* Enable RPC debugging/profiling.
--- linux/include/linux/sunrpc/sched.h.orig Sat Aug 22 15:06:48 1998
+++ linux/include/linux/sunrpc/sched.h Sat Aug 22 17:54:49 1998
@@ -128,7 +128,7 @@
void rpc_execute(struct rpc_task *);
void rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
rpc_action action);
-void rpc_add_wait_queue(struct rpc_wait_queue *, struct rpc_task *);
+int rpc_add_wait_queue(struct rpc_wait_queue *, struct rpc_task *);
void rpc_remove_wait_queue(struct rpc_task *);
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
rpc_action action, rpc_action timer);
--- linux/include/linux/quota.h.orig Fri May 8 20:54:39 1998
+++ linux/include/linux/quota.h Sat Aug 22 17:54:49 1998
@@ -39,7 +39,11 @@
#ifndef _LINUX_QUOTA_
#define _LINUX_QUOTA_

+#ifdef __KERNEL__
#include <linux/errno.h>
+#else
+#include <asm/types.h>
+#endif

/*
* Convert diskblocks to blocks and the other way around.
--- linux/include/linux/nfs_fs.h.orig Sat Aug 22 15:06:48 1998
+++ linux/include/linux/nfs_fs.h Sat Aug 22 17:54:49 1998
@@ -9,6 +9,7 @@
#ifndef _LINUX_NFS_FS_H
#define _LINUX_NFS_FS_H

+#ifdef __KERNEL__
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/in.h>
@@ -16,6 +17,7 @@
#include <linux/sunrpc/sched.h>
#include <linux/nfs.h>
#include <linux/nfs_mount.h>
+#endif

/*
* Enable debugging support for nfs client.
--- linux/include/linux/socket.h.orig Sun Aug 16 20:09:41 1998
+++ linux/include/linux/socket.h Sat Aug 22 17:54:49 1998
@@ -5,8 +5,8 @@

#include <asm/socket.h> /* arch-dependent defines */
#include <linux/sockios.h> /* the SIOCxxx I/O controls */
-#include <linux/uio.h> /* iovec support */
#include <linux/types.h> /* pid_t */
+#include <linux/uio.h> /* iovec support */

typedef unsigned short sa_family_t;

--- linux/net/sunrpc/sched.c.orig Sat Aug 22 17:50:46 1998
+++ linux/net/sunrpc/sched.c Sat Aug 22 17:54:49 1998
@@ -79,13 +79,16 @@
* improve overall performance.
* Everyone else gets appended to the queue to ensure proper FIFO behavior.
*/
-void
+int
rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
{
if (task->tk_rpcwait) {
if (task->tk_rpcwait != queue)
+ {
printk(KERN_WARNING "RPC: doubly enqueued task!\n");
- return;
+ return -EWOULDBLOCK;
+ }
+ return 0;
}
if (RPC_IS_SWAPPER(task))
rpc_insert_list(&queue->task, task);
@@ -95,6 +98,8 @@

dprintk("RPC: %4d added to queue %p \"%s\"\n",
task->tk_pid, queue, rpc_qname(queue));
+
+ return 0;
}

/*
@@ -168,7 +173,13 @@
return;
}
if (RPC_IS_ASYNC(task)) {
- rpc_add_wait_queue(&schedq, task);
+ int status;
+ status = rpc_add_wait_queue(&schedq, task);
+ if (status)
+ {
+ printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
+ task->tk_status = status;
+ }
wake_up(&rpciod_idle);
} else {
wake_up(&task->tk_wait);
@@ -202,6 +213,7 @@
rpc_action action, rpc_action timer)
{
unsigned long oldflags;
+ int status;

dprintk("RPC: %4d sleep_on(queue \"%s\" time %ld)\n", task->tk_pid,
rpc_qname(q), jiffies);
@@ -211,11 +223,20 @@
*/
save_flags(oldflags); cli();

- rpc_add_wait_queue(q, task);
+ status = rpc_add_wait_queue(q, task);
+ if (status)
+ {
+ printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
+ task->tk_status = status;
+ task->tk_flags |= RPC_TASK_RUNNING;
+ }
+ else
+ {
task->tk_callback = action;
if (task->tk_timeout)
rpc_add_timer(task, timer);
task->tk_flags &= ~RPC_TASK_RUNNING;
+ }

restore_flags(oldflags);
return;
--- linux/net/sunrpc/xprt.c.orig Sat Aug 22 17:50:46 1998
+++ linux/net/sunrpc/xprt.c Sat Aug 22 17:54:49 1998
@@ -935,6 +935,7 @@
struct rpc_timeout *timeo;
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
+ int status;

/*DEBUG*/int ac_debug=xprt->snd_sent;

@@ -992,9 +993,17 @@
* the pending list now:
*/
start_bh_atomic();
- rpc_add_wait_queue(&xprt->pending, task);
+ status = rpc_add_wait_queue(&xprt->pending, task);
+ if (!status)
task->tk_callback = NULL;
end_bh_atomic();
+
+ if (status)
+ {
+ printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
+ task->tk_status = status;
+ return;
+ }

/* Continue transmitting the packet/record. We must be careful
* to cope with writespace callbacks arriving _after_ we have
\
 
 \ /
  Last update: 2005-03-22 13:44    [W:0.060 / U:0.044 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site