diff options
author | Andy Adamson <andros@citi.umich.edu> | 2006-03-26 04:37:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-26 11:56:56 -0500 |
commit | 5842add2f3b519111b6401f3a35862bd00a3aa7e (patch) | |
tree | 299e5653ec2b7dfc9fa565920d7320bbf1c9c07e /fs/locks.c | |
parent | 6dc0fe8f8b40854982929e4f24d8c65115769b60 (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/locks.c')
-rw-r--r-- | fs/locks.c | 32 |
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 | ||
795 | EXPORT_SYMBOL(posix_lock_file); | 795 | static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) |
796 | |||
797 | static 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 | */ |
988 | int posix_lock_file(struct file *filp, struct file_lock *fl) | 988 | int 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 | } | ||
992 | EXPORT_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 | */ | ||
1002 | int 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 | } |
1007 | EXPORT_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, |