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