Commit 5842add2f3b519111b6401f3a35862bd00a3aa7e

Authored by Andy Adamson
Committed by Linus Torvalds
1 parent 6dc0fe8f8b

[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>

Showing 2 changed files with 25 additions and 8 deletions Side-by-side Diff

... ... @@ -792,9 +792,7 @@
792 792 return error;
793 793 }
794 794  
795   -EXPORT_SYMBOL(posix_lock_file);
796   -
797   -static int __posix_lock_file(struct inode *inode, struct file_lock *request)
  795 +static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
798 796 {
799 797 struct file_lock *fl;
800 798 struct file_lock *new_fl, *new_fl2;
... ... @@ -818,6 +816,8 @@
818 816 continue;
819 817 if (!posix_locks_conflict(request, fl))
820 818 continue;
  819 + if (conflock)
  820 + locks_copy_lock(conflock, fl);
821 821 error = -EAGAIN;
822 822 if (!(request->fl_flags & FL_SLEEP))
823 823 goto out;
824 824  
825 825  
... ... @@ -987,10 +987,26 @@
987 987 */
988 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 991 }
  992 +EXPORT_SYMBOL(posix_lock_file);
992 993  
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);
  1006 +}
  1007 +EXPORT_SYMBOL(posix_lock_file_conf);
  1008 +
  1009 +/**
994 1010 * posix_lock_file_wait - Apply a POSIX-style lock to a file
995 1011 * @filp: The file to apply the lock to
996 1012 * @fl: The lock to be applied
... ... @@ -1004,7 +1020,7 @@
1004 1020 int error;
1005 1021 might_sleep ();
1006 1022 for (;;) {
1007   - error = __posix_lock_file(filp->f_dentry->d_inode, fl);
  1023 + error = posix_lock_file(filp, fl);
1008 1024 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
1009 1025 break;
1010 1026 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
... ... @@ -1076,7 +1092,7 @@
1076 1092 fl.fl_end = offset + count - 1;
1077 1093  
1078 1094 for (;;) {
1079   - error = __posix_lock_file(inode, &fl);
  1095 + error = __posix_lock_file_conf(inode, &fl, NULL);
1080 1096 if (error != -EAGAIN)
1081 1097 break;
1082 1098 if (!(fl.fl_flags & FL_SLEEP))
... ... @@ -1689,7 +1705,7 @@
1689 1705 error = filp->f_op->lock(filp, cmd, file_lock);
1690 1706 else {
1691 1707 for (;;) {
1692   - error = __posix_lock_file(inode, file_lock);
  1708 + error = posix_lock_file(filp, file_lock);
1693 1709 if ((error != -EAGAIN) || (cmd == F_SETLK))
1694 1710 break;
1695 1711 error = wait_event_interruptible(file_lock->fl_wait,
... ... @@ -1832,7 +1848,7 @@
1832 1848 error = filp->f_op->lock(filp, cmd, file_lock);
1833 1849 else {
1834 1850 for (;;) {
1835   - error = __posix_lock_file(inode, file_lock);
  1851 + error = posix_lock_file(filp, file_lock);
1836 1852 if ((error != -EAGAIN) || (cmd == F_SETLK64))
1837 1853 break;
1838 1854 error = wait_event_interruptible(file_lock->fl_wait,
... ... @@ -763,6 +763,7 @@
763 763 extern void locks_remove_posix(struct file *, fl_owner_t);
764 764 extern void locks_remove_flock(struct file *);
765 765 extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *);
  766 +extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *);
766 767 extern int posix_lock_file(struct file *, struct file_lock *);
767 768 extern int posix_lock_file_wait(struct file *, struct file_lock *);
768 769 extern int posix_unblock_lock(struct file *, struct file_lock *);