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 *);
