diff -urNX dontdiff linux-2.4.2/fs/lockd/svclock.c linux-willy/fs/lockd/svclock.c
--- linux-2.4.2/fs/lockd/svclock.c      Tue Nov  7 11:18:57 2000
+++ linux-willy/fs/lockd/svclock.c      Fri Mar  2 00:21:00 2001
@@ -237,7 +237,7 @@
       if (unlock && block->b_granted) {
               dprintk("lockd: deleting granted lock\n");
               fl->fl_type = F_UNLCK;
-               posix_lock_file(&block->b_file->f_file, fl, 0);
+               posix_lock_file(&block->b_file->f_file, fl, F_GETLK);
               block->b_granted = 0;
       } else {
               dprintk("lockd: unblocking blocked lock\n");
@@ -319,7 +319,7 @@

again:
       if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
-               error = posix_lock_file(&file->f_file, &lock->fl, 0);
+               error = posix_lock_file(&file->f_file, &lock->fl, F_GETLK);

               if (block)
                       nlmsvc_delete_block(block, 0);
@@ -343,32 +343,39 @@
               }
       }

-       if (!wait) {
-               up(&file->f_sema);
-               return nlm_lck_denied;
-       }
+       error = nlm_lck_denied;
+
+       if (!wait)
+               goto out;

       /* If we don't have a block, create and initialize it. Then
        * retry because we may have slept in kmalloc. */
       if (block == NULL) {
               dprintk("lockd: blocking on this lock (allocating).\n");
-               if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie)))
-                       return nlm_lck_denied_nolocks;
-               goto again;
+               error = nlm_lck_denied_nolocks;
+               block = nlmsvc_create_block(rqstp, file, lock, cookie);
+               if (block)
+                       goto again;
+               goto out;
       }

       /* Append to list of blocked */
       nlmsvc_insert_block(block, NLM_NEVER);

+       error = nlm_lck_blocked;
+
       if (list_empty(&block->b_call.a_args.lock.fl.fl_block)) {
               /* Now add block to block list of the conflicting lock
                  if we haven't done so. */
               dprintk("lockd: blocking on this lock.\n");
-               posix_block_lock(conflock, &block->b_call.a_args.lock.fl);
+               if (posix_block_lock(conflock, &block->b_call.a_args.lock.fl))
+                       error = nlm_lck_denied;
       }

+ out:
+
       up(&file->f_sema);
-       return nlm_lck_blocked;
+       return error;
}

/*
@@ -423,7 +430,7 @@
       nlmsvc_cancel_blocked(file, lock);

       lock->fl.fl_type = F_UNLCK;
-       error = posix_lock_file(&file->f_file, &lock->fl, 0);
+       error = posix_lock_file(&file->f_file, &lock->fl, F_GETLK);

       return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
}
@@ -528,7 +535,7 @@
        * following yields an error, this is most probably due to low
        * memory. Retry the lock in a few seconds.
        */
-       if ((error = posix_lock_file(&file->f_file, &lock->fl, 0)) < 0) {
+       if ((error = posix_lock_file(&file->f_file, &lock->fl, F_GETLK)) < 0) {
               printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
                               -error, __FUNCTION__);
               nlmsvc_insert_block(block, 10 * HZ);
diff -urNX dontdiff linux-2.4.2/fs/lockd/svcsubs.c linux-willy/fs/lockd/svcsubs.c
--- linux-2.4.2/fs/lockd/svcsubs.c      Fri Jun 23 22:12:53 2000
+++ linux-willy/fs/lockd/svcsubs.c      Fri Mar  2 00:20:25 2001
@@ -176,7 +176,7 @@
                       lock.fl_type  = F_UNLCK;
                       lock.fl_start = 0;
                       lock.fl_end   = OFFSET_MAX;
-                       if (posix_lock_file(&file->f_file, &lock, 0) < 0) {
+                       if (posix_lock_file(&file->f_file, &lock, F_GETLK) < 0) {
                               printk("lockd: unlock failure in %s:%d\n",
                                               __FILE__, __LINE__);
                               return 1;
diff -urNX dontdiff linux-2.4.2/fs/locks.c linux-willy/fs/locks.c
--- linux-2.4.2/fs/locks.c      Fri Feb  9 12:29:44 2001
+++ linux-willy/fs/locks.c      Fri Mar  2 00:30:48 2001
@@ -618,6 +618,21 @@
{
       struct file_lock *cfl;

+       if (filp->f_op && filp->f_op->lock) {
+               int error = filp->f_op->lock(filp, F_GETLK, fl);
+               if (error < 0) {
+                       return ERR_PTR(error);
+               } else if (error == LOCK_USE_CLNT) {
+                       /* NFS with no locking - 2.0 compatibility.  Drop
+                        * out and use client-side locking instead.
+                        */
+               } else if (fl->fl_type == F_UNLCK) {
+                       return NULL;
+               } else {
+                       return fl;
+               }
+       }
+
       lock_kernel();
       for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
               if (!(cfl->fl_flags & FL_POSIX))
@@ -627,7 +642,7 @@
       }
       unlock_kernel();

-       return (cfl);
+       return cfl;
}

/* This function tests for deadlock condition before putting a process to
@@ -839,7 +854,7 @@
 */

int posix_lock_file(struct file *filp, struct file_lock *caller,
-                          unsigned int wait)
+                          unsigned int cmd)
{
       struct file_lock *fl;
       struct file_lock *new_fl, *new_fl2;
@@ -848,6 +863,7 @@
       struct file_lock **before;
       struct inode * inode = filp->f_dentry->d_inode;
       int error, added = 0;
+       int wait = (cmd == F_SETLKW) || (cmd == F_SETLKW64);

       /*
        * We may need two file_lock structures for this operation,
@@ -859,6 +875,13 @@
       if (!(new_fl && new_fl2))
               goto out;

+       /* Check the underlying filesystem will allow us to lock */
+       if (filp->f_op && filp->f_op->lock != NULL) {
+               error = filp->f_op->lock(filp, cmd, caller);
+               if (error < 0)
+                       goto out;
+       }
+
       lock_kernel();
       if (caller->fl_type != F_UNLCK) {
  repeat:
@@ -1356,17 +1379,10 @@
       if (!flock_to_posix_lock(filp, &file_lock, &flock))
               goto out_putf;

-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
-               if (error < 0)
-                       goto out_putf;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
-       } else {
-               fl = posix_test_lock(filp, &file_lock);
+       fl = posix_test_lock(filp, &file_lock);
+       if (IS_ERR(fl)) {
+               error = PTR_ERR(fl);
+               goto out_putf;
       }

       flock.l_type = F_UNLCK;
@@ -1480,12 +1496,7 @@
               goto out_putf;
       }

-       if (filp->f_op && filp->f_op->lock != NULL) {
-               error = filp->f_op->lock(filp, cmd, file_lock);
-               if (error < 0)
-                       goto out_putf;
-       }
-       error = posix_lock_file(filp, file_lock, cmd == F_SETLKW);
+       error = posix_lock_file(filp, file_lock, cmd);

out_putf:
       fput(filp);
@@ -1521,17 +1532,10 @@
       if (!flock64_to_posix_lock(filp, &file_lock, &flock))
               goto out_putf;

-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
-               if (error < 0)
-                       goto out_putf;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
-       } else {
-               fl = posix_test_lock(filp, &file_lock);
+       fl = posix_test_lock(filp, &file_lock);
+       if (IS_ERR(fl)) {
+               error = PTR_ERR(fl);
+               goto out_putf;
       }

       flock.l_type = F_UNLCK;
@@ -1618,12 +1622,7 @@
               goto out_putf;
       }

-       if (filp->f_op && filp->f_op->lock != NULL) {
-               error = filp->f_op->lock(filp, cmd, file_lock);
-               if (error < 0)
-                       goto out_putf;
-       }
-       error = posix_lock_file(filp, file_lock, cmd == F_SETLKW64);
+       error = posix_lock_file(filp, file_lock, cmd);

out_putf:
       fput(filp);
@@ -1695,15 +1694,21 @@

/**
 *     posix_block_lock - blocks waiting for a file lock
- *     @blocker: the lock which is blocking
- *     @waiter: the lock which conflicts and has to wait
+ *     @blocker: the existing lock which has been granted
+ *     @waiter: the new lock which must sleep
 *
- * lockd needs to block waiting for locks.
+ * This routine is for the use of lockd alone.  It allows lockd to block
+ * waiting for locks by putting the lock in the list of blocking locks
+ * without actually going to sleep itself.
 */
-void
+int
posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
{
-       locks_insert_block(blocker, waiter);
+       int error;
+       error = posix_locks_deadlock(waiter, blocker);
+       if (!error)
+               locks_insert_block(blocker, waiter);
+       return error;
}

/**
diff -urNX dontdiff linux-2.4.2/include/linux/fs.h linux-willy/include/linux/fs.h
--- linux-2.4.2/include/linux/fs.h      Wed Feb 21 17:09:58 2001
+++ linux-willy/include/linux/fs.h      Thu Mar  1 23:57:06 2001
@@ -568,7 +568,7 @@
extern void locks_remove_flock(struct file *);
extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, unsigned int);
-extern void posix_block_lock(struct file_lock *, struct file_lock *);
+extern int posix_block_lock(struct file_lock *, struct file_lock *);
extern void posix_unblock_lock(struct file_lock *);
extern int __get_lease(struct inode *inode, unsigned int flags);
extern time_t lease_get_mtime(struct inode *);