aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndy Adamson <andros@citi.umich.edu>2006-03-26 04:37:26 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:56:56 -0500
commit5842add2f3b519111b6401f3a35862bd00a3aa7e (patch)
tree299e5653ec2b7dfc9fa565920d7320bbf1c9c07e /fs
parent6dc0fe8f8b40854982929e4f24d8c65115769b60 (diff)
[PATCH] VFS,fs/locks.c,NFSD4: add race_free posix_lock_file_conf() interface
Lockd and the NFSv4 server both exercise a race condition where posix_test_lock() is called either before or after posix_lock_file() to deal with a denied lock request due to a conflicting lock. Remove the race condition for the NFSv4 server by adding a new conflicting lock parameter to __posix_lock_file() , changing the name to __posix_lock_file_conf(). Keep posix_lock_file() interface, add posix_lock_conf() interface, both call __posix_lock_file_conf(). [akpm@osdl.org: Put the EXPORT_SYMBOL() where it belongs] Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/locks.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 4badf6a0e7b6..4d9e71d43e7e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -792,9 +792,7 @@ out:
792 return error; 792 return error;
793} 793}
794 794
795EXPORT_SYMBOL(posix_lock_file); 795static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
796
797static int __posix_lock_file(struct inode *inode, struct file_lock *request)
798{ 796{
799 struct file_lock *fl; 797 struct file_lock *fl;
800 struct file_lock *new_fl, *new_fl2; 798 struct file_lock *new_fl, *new_fl2;
@@ -818,6 +816,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
818 continue; 816 continue;
819 if (!posix_locks_conflict(request, fl)) 817 if (!posix_locks_conflict(request, fl))
820 continue; 818 continue;
819 if (conflock)
820 locks_copy_lock(conflock, fl);
821 error = -EAGAIN; 821 error = -EAGAIN;
822 if (!(request->fl_flags & FL_SLEEP)) 822 if (!(request->fl_flags & FL_SLEEP))
823 goto out; 823 goto out;
@@ -987,8 +987,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
987 */ 987 */
988int posix_lock_file(struct file *filp, struct file_lock *fl) 988int posix_lock_file(struct file *filp, struct file_lock *fl)
989{ 989{
990 return __posix_lock_file(filp->f_dentry->d_inode, fl); 990 return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
991}
992EXPORT_SYMBOL(posix_lock_file);
993
994/**
995 * posix_lock_file_conf - Apply a POSIX-style lock to a file
996 * @filp: The file to apply the lock to
997 * @fl: The lock to be applied
998 * @conflock: Place to return a copy of the conflicting lock, if found.
999 *
1000 * Except for the conflock parameter, acts just like posix_lock_file.
1001 */
1002int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
1003 struct file_lock *conflock)
1004{
1005 return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
991} 1006}
1007EXPORT_SYMBOL(posix_lock_file_conf);
992 1008
993/** 1009/**
994 * posix_lock_file_wait - Apply a POSIX-style lock to a file 1010 * posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -1004,7 +1020,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
1004 int error; 1020 int error;
1005 might_sleep (); 1021 might_sleep ();
1006 for (;;) { 1022 for (;;) {
1007 error = __posix_lock_file(filp->f_dentry->d_inode, fl); 1023 error = posix_lock_file(filp, fl);
1008 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) 1024 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
1009 break; 1025 break;
1010 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); 1026 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1076,7 +1092,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
1076 fl.fl_end = offset + count - 1; 1092 fl.fl_end = offset + count - 1;
1077 1093
1078 for (;;) { 1094 for (;;) {
1079 error = __posix_lock_file(inode, &fl); 1095 error = __posix_lock_file_conf(inode, &fl, NULL);
1080 if (error != -EAGAIN) 1096 if (error != -EAGAIN)
1081 break; 1097 break;
1082 if (!(fl.fl_flags & FL_SLEEP)) 1098 if (!(fl.fl_flags & FL_SLEEP))
@@ -1689,7 +1705,7 @@ again:
1689 error = filp->f_op->lock(filp, cmd, file_lock); 1705 error = filp->f_op->lock(filp, cmd, file_lock);
1690 else { 1706 else {
1691 for (;;) { 1707 for (;;) {
1692 error = __posix_lock_file(inode, file_lock); 1708 error = posix_lock_file(filp, file_lock);
1693 if ((error != -EAGAIN) || (cmd == F_SETLK)) 1709 if ((error != -EAGAIN) || (cmd == F_SETLK))
1694 break; 1710 break;
1695 error = wait_event_interruptible(file_lock->fl_wait, 1711 error = wait_event_interruptible(file_lock->fl_wait,
@@ -1832,7 +1848,7 @@ again:
1832 error = filp->f_op->lock(filp, cmd, file_lock); 1848 error = filp->f_op->lock(filp, cmd, file_lock);
1833 else { 1849 else {
1834 for (;;) { 1850 for (;;) {
1835 error = __posix_lock_file(inode, file_lock); 1851 error = posix_lock_file(filp, file_lock);
1836 if ((error != -EAGAIN) || (cmd == F_SETLK64)) 1852 if ((error != -EAGAIN) || (cmd == F_SETLK64))
1837 break; 1853 break;
1838 error = wait_event_interruptible(file_lock->fl_wait, 1854 error = wait_event_interruptible(file_lock->fl_wait,