--- linux-2.5.59-orig/fs/lockd/svclock.c Thu Jan 16 20:21:49 2003 +++ linux-2.5.59-new/fs/lockd/svclock.c Thu Jan 23 16:32:16 2003 @@ -315,7 +315,7 @@ again: if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) { - error = posix_lock_file(&file->f_file, &lock->fl); + error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl); if (block) nlmsvc_delete_block(block, 0); @@ -419,7 +419,7 @@ nlmsvc_cancel_blocked(file, lock); lock->fl.fl_type = F_UNLCK; - error = posix_lock_file(&file->f_file, &lock->fl); + error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl); return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; } @@ -523,7 +523,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) { + if ((error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl)) < 0) { printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", -error, __FUNCTION__); nlmsvc_insert_block(block, 10 * HZ); --- linux-2.5.59-orig/fs/lockd/svcsubs.c Thu Jan 16 20:22:21 2003 +++ linux-2.5.59-new/fs/lockd/svcsubs.c Thu Jan 23 16:32:16 2003 @@ -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) { + if (posix_lock_file(file->f_file.f_dentry->d_inode, &lock) < 0) { printk("lockd: unlock failure in %s:%d\n", __FILE__, __LINE__); return 1; --- linux-2.5.59-orig/fs/locks.c Thu Jan 16 20:22:44 2003 +++ linux-2.5.59-new/fs/locks.c Thu Jan 23 16:32:19 2003 @@ -678,27 +678,52 @@ struct file_lock fl; int error; + INIT_LIST_HEAD(&fl.fl_link); + INIT_LIST_HEAD(&fl.fl_block); + init_waitqueue_head(&fl.fl_wait); + fl.fl_owner = current->files; fl.fl_pid = current->tgid; fl.fl_file = filp; - fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP; + + /* If the O_NONBLOCK flag is used don't sleep while */ + /* the lock is present -RW */ + if ((filp != NULL) && (filp->f_flags & O_NONBLOCK)) + fl.fl_flags = FL_POSIX | FL_ACCESS; + else + fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP; + fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; fl.fl_start = offset; fl.fl_end = offset + count - 1; + fl.fl_next = NULL; + fl.fl_notify = NULL; + fl.fl_insert = NULL; + fl.fl_remove = NULL; + fl.fl_fasync = NULL; for (;;) { - error = posix_lock_file(filp, &fl); - if (error != -EAGAIN) + error = posix_lock_file(inode, &fl); + + /* If the returned error is EAGAIN, filp is */ + /* not NULL, and O_NONBLOCK was specified */ + /* then return the EAGAIN error -RW */ + if ((error == -EAGAIN) && (filp != NULL) && (filp->f_flags & O_NONBLOCK)) break; + + /* posix_lock_file may return EDEADLK, so */ + /* we should pass it on if this occurs -RW */ + if (error == -EDEADLK) + break; + error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); - if (!error) { - /* - * If we've been sleeping someone might have - * changed the permissions behind our back. - */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) - continue; - } + + /* + * If we've been sleeping someone might have + * changed the permissions behind our back. + */ + if ((!error) && ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID)) + break; lock_kernel(); locks_delete_block(&fl); @@ -772,9 +797,8 @@ /** * posix_lock_file: - * @filp: The file to apply the lock to - * @caller: The lock to be applied - * @wait: 1 to retry automatically, 0 to return -EAGAIN + * @inode: The inode of file to apply the lock to + * @request: The lock to be applied * * Add a POSIX style lock to a file. * We merge adjacent locks whenever possible. POSIX locks are sorted by owner @@ -788,14 +812,13 @@ * To all purists: Yes, I use a few goto's. Just pass on to the next function. */ -int posix_lock_file(struct file *filp, struct file_lock *request) +int posix_lock_file(struct inode *inode, struct file_lock *request) { struct file_lock *fl; struct file_lock *new_fl, *new_fl2; struct file_lock *left = NULL; struct file_lock *right = NULL; struct file_lock **before; - struct inode * inode = filp->f_dentry->d_inode; int error, added = 0; /* @@ -1460,7 +1483,7 @@ } for (;;) { - error = posix_lock_file(filp, file_lock); + error = posix_lock_file(inode, file_lock); if ((error != -EAGAIN) || (cmd == F_SETLK)) break; error = wait_event_interruptible(file_lock->fl_wait, @@ -1600,7 +1623,7 @@ } for (;;) { - error = posix_lock_file(filp, file_lock); + error = posix_lock_file(inode, file_lock); if ((error != -EAGAIN) || (cmd == F_SETLK64)) break; error = wait_event_interruptible(file_lock->fl_wait, @@ -1650,7 +1673,7 @@ /* Ignore any error -- we must remove the locks anyway */ } - posix_lock_file(filp, &lock); + posix_lock_file(filp->f_dentry->d_inode, &lock); } /* @@ -1717,7 +1740,7 @@ } else { unlock_kernel(); waiter->fl_type = F_UNLCK; - posix_lock_file(filp, waiter); + posix_lock_file(filp->f_dentry->d_inode, waiter); } } --- linux-2.5.59-orig/include/linux/fs.h Thu Jan 16 20:21:47 2003 +++ linux-2.5.59-new/include/linux/fs.h Thu Jan 23 16:31:56 2003 @@ -568,7 +568,7 @@ extern void locks_remove_posix(struct file *, fl_owner_t); 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 *); +extern int posix_lock_file(struct inode *, struct file_lock *); extern void posix_block_lock(struct file_lock *, struct file_lock *); extern void posix_unblock_lock(struct file *, struct file_lock *); extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);