aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Eshel <eshel@almaden.ibm.com>2007-01-18 16:15:35 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2007-05-06 19:23:24 -0400
commit150b393456e5a23513cace286a019e87151e47f0 (patch)
tree91599ec9b759f7e3c5defcb8dd361acd7288154c
parent7723ec9777d9832849b76475b1a21a2872a40d20 (diff)
locks: allow {vfs,posix}_lock_file to return conflicting lock
The nfsv4 protocol's lock operation, in the case of a conflict, returns information about the conflicting lock. It's unclear how clients can use this, so for now we're not going so far as to add a filesystem method that can return a conflicting lock, but we may as well return something in the local case when it's easy to. Signed-off-by: Marc Eshel <eshel@almaden.ibm.com> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
-rw-r--r--fs/lockd/svclock.c6
-rw-r--r--fs/lockd/svcsubs.c2
-rw-r--r--fs/locks.c45
-rw-r--r--fs/nfsd/nfs4state.c10
-rw-r--r--include/linux/fs.h5
5 files changed, 32 insertions, 36 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 97b0160ef10f..3b0e7a4b817b 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -363,7 +363,7 @@ again:
363 } else 363 } else
364 lock = &block->b_call->a_args.lock; 364 lock = &block->b_call->a_args.lock;
365 365
366 error = posix_lock_file(file->f_file, &lock->fl); 366 error = posix_lock_file(file->f_file, &lock->fl, NULL);
367 lock->fl.fl_flags &= ~FL_SLEEP; 367 lock->fl.fl_flags &= ~FL_SLEEP;
368 368
369 dprintk("lockd: posix_lock_file returned %d\n", error); 369 dprintk("lockd: posix_lock_file returned %d\n", error);
@@ -467,7 +467,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
467 nlmsvc_cancel_blocked(file, lock); 467 nlmsvc_cancel_blocked(file, lock);
468 468
469 lock->fl.fl_type = F_UNLCK; 469 lock->fl.fl_type = F_UNLCK;
470 error = posix_lock_file(file->f_file, &lock->fl); 470 error = posix_lock_file(file->f_file, &lock->fl, NULL);
471 471
472 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; 472 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
473} 473}
@@ -569,7 +569,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
569 569
570 /* Try the lock operation again */ 570 /* Try the lock operation again */
571 lock->fl.fl_flags |= FL_SLEEP; 571 lock->fl.fl_flags |= FL_SLEEP;
572 error = posix_lock_file(file->f_file, &lock->fl); 572 error = posix_lock_file(file->f_file, &lock->fl, NULL);
573 lock->fl.fl_flags &= ~FL_SLEEP; 573 lock->fl.fl_flags &= ~FL_SLEEP;
574 574
575 switch (error) { 575 switch (error) {
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index c0df00c74ce3..50957089be1f 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -182,7 +182,7 @@ again:
182 lock.fl_type = F_UNLCK; 182 lock.fl_type = F_UNLCK;
183 lock.fl_start = 0; 183 lock.fl_start = 0;
184 lock.fl_end = OFFSET_MAX; 184 lock.fl_end = OFFSET_MAX;
185 if (posix_lock_file(file->f_file, &lock) < 0) { 185 if (posix_lock_file(file->f_file, &lock, NULL) < 0) {
186 printk("lockd: unlock failure in %s:%d\n", 186 printk("lockd: unlock failure in %s:%d\n",
187 __FILE__, __LINE__); 187 __FILE__, __LINE__);
188 return 1; 188 return 1;
diff --git a/fs/locks.c b/fs/locks.c
index f4fd1515b6e2..ee46584c1a40 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -801,7 +801,7 @@ out:
801 return error; 801 return error;
802} 802}
803 803
804static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 804static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
805{ 805{
806 struct file_lock *fl; 806 struct file_lock *fl;
807 struct file_lock *new_fl = NULL; 807 struct file_lock *new_fl = NULL;
@@ -1007,6 +1007,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
1007 * posix_lock_file - Apply a POSIX-style lock to a file 1007 * posix_lock_file - Apply a POSIX-style lock to a file
1008 * @filp: The file to apply the lock to 1008 * @filp: The file to apply the lock to
1009 * @fl: The lock to be applied 1009 * @fl: The lock to be applied
1010 * @conflock: Place to return a copy of the conflicting lock, if found.
1010 * 1011 *
1011 * Add a POSIX style lock to a file. 1012 * Add a POSIX style lock to a file.
1012 * We merge adjacent & overlapping locks whenever possible. 1013 * We merge adjacent & overlapping locks whenever possible.
@@ -1016,26 +1017,12 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
1016 * whether or not a lock was successfully freed by testing the return 1017 * whether or not a lock was successfully freed by testing the return
1017 * value for -ENOENT. 1018 * value for -ENOENT.
1018 */ 1019 */
1019int posix_lock_file(struct file *filp, struct file_lock *fl) 1020int posix_lock_file(struct file *filp, struct file_lock *fl,
1020{
1021 return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
1022}
1023EXPORT_SYMBOL(posix_lock_file);
1024
1025/**
1026 * posix_lock_file_conf - Apply a POSIX-style lock to a file
1027 * @filp: The file to apply the lock to
1028 * @fl: The lock to be applied
1029 * @conflock: Place to return a copy of the conflicting lock, if found.
1030 *
1031 * Except for the conflock parameter, acts just like posix_lock_file.
1032 */
1033int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
1034 struct file_lock *conflock) 1021 struct file_lock *conflock)
1035{ 1022{
1036 return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock); 1023 return __posix_lock_file(filp->f_path.dentry->d_inode, fl, conflock);
1037} 1024}
1038EXPORT_SYMBOL(posix_lock_file_conf); 1025EXPORT_SYMBOL(posix_lock_file);
1039 1026
1040/** 1027/**
1041 * posix_lock_file_wait - Apply a POSIX-style lock to a file 1028 * posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -1051,7 +1038,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
1051 int error; 1038 int error;
1052 might_sleep (); 1039 might_sleep ();
1053 for (;;) { 1040 for (;;) {
1054 error = posix_lock_file(filp, fl); 1041 error = posix_lock_file(filp, fl, NULL);
1055 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) 1042 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
1056 break; 1043 break;
1057 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); 1044 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1123,7 +1110,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
1123 fl.fl_end = offset + count - 1; 1110 fl.fl_end = offset + count - 1;
1124 1111
1125 for (;;) { 1112 for (;;) {
1126 error = __posix_lock_file_conf(inode, &fl, NULL); 1113 error = __posix_lock_file(inode, &fl, NULL);
1127 if (error != -EAGAIN) 1114 if (error != -EAGAIN)
1128 break; 1115 break;
1129 if (!(fl.fl_flags & FL_SLEEP)) 1116 if (!(fl.fl_flags & FL_SLEEP))
@@ -1703,13 +1690,21 @@ out:
1703 * @filp: The file to apply the lock to 1690 * @filp: The file to apply the lock to
1704 * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.) 1691 * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.)
1705 * @fl: The lock to be applied 1692 * @fl: The lock to be applied
1693 * @conf: Place to return a copy of the conflicting lock, if found.
1694 *
1695 * A caller that doesn't care about the conflicting lock may pass NULL
1696 * as the final argument.
1697 *
1698 * If the filesystem defines a private ->lock() method, then @conf will
1699 * be left unchanged; so a caller that cares should initialize it to
1700 * some acceptable default.
1706 */ 1701 */
1707int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl) 1702int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
1708{ 1703{
1709 if (filp->f_op && filp->f_op->lock) 1704 if (filp->f_op && filp->f_op->lock)
1710 return filp->f_op->lock(filp, cmd, fl); 1705 return filp->f_op->lock(filp, cmd, fl);
1711 else 1706 else
1712 return posix_lock_file(filp, fl); 1707 return posix_lock_file(filp, fl, conf);
1713} 1708}
1714EXPORT_SYMBOL_GPL(vfs_lock_file); 1709EXPORT_SYMBOL_GPL(vfs_lock_file);
1715 1710
@@ -1776,7 +1771,7 @@ again:
1776 goto out; 1771 goto out;
1777 1772
1778 for (;;) { 1773 for (;;) {
1779 error = vfs_lock_file(filp, cmd, file_lock); 1774 error = vfs_lock_file(filp, cmd, file_lock, NULL);
1780 if (error != -EAGAIN || cmd == F_SETLK) 1775 if (error != -EAGAIN || cmd == F_SETLK)
1781 break; 1776 break;
1782 error = wait_event_interruptible(file_lock->fl_wait, 1777 error = wait_event_interruptible(file_lock->fl_wait,
@@ -1902,7 +1897,7 @@ again:
1902 goto out; 1897 goto out;
1903 1898
1904 for (;;) { 1899 for (;;) {
1905 error = vfs_lock_file(filp, cmd, file_lock); 1900 error = vfs_lock_file(filp, cmd, file_lock, NULL);
1906 if (error != -EAGAIN || cmd == F_SETLK64) 1901 if (error != -EAGAIN || cmd == F_SETLK64)
1907 break; 1902 break;
1908 error = wait_event_interruptible(file_lock->fl_wait, 1903 error = wait_event_interruptible(file_lock->fl_wait,
@@ -1956,7 +1951,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
1956 lock.fl_ops = NULL; 1951 lock.fl_ops = NULL;
1957 lock.fl_lmops = NULL; 1952 lock.fl_lmops = NULL;
1958 1953
1959 vfs_lock_file(filp, F_SETLK, &lock); 1954 vfs_lock_file(filp, F_SETLK, &lock, NULL);
1960 1955
1961 if (lock.fl_ops && lock.fl_ops->fl_release_private) 1956 if (lock.fl_ops && lock.fl_ops->fl_release_private)
1962 lock.fl_ops->fl_release_private(&lock); 1957 lock.fl_ops->fl_release_private(&lock);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index e42c7a0eb6fa..03b0578781cb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2657,6 +2657,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2657 struct file_lock conflock; 2657 struct file_lock conflock;
2658 __be32 status = 0; 2658 __be32 status = 0;
2659 unsigned int strhashval; 2659 unsigned int strhashval;
2660 unsigned int cmd;
2660 int err; 2661 int err;
2661 2662
2662 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 2663 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -2739,10 +2740,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2739 case NFS4_READ_LT: 2740 case NFS4_READ_LT:
2740 case NFS4_READW_LT: 2741 case NFS4_READW_LT:
2741 file_lock.fl_type = F_RDLCK; 2742 file_lock.fl_type = F_RDLCK;
2743 cmd = F_SETLK;
2742 break; 2744 break;
2743 case NFS4_WRITE_LT: 2745 case NFS4_WRITE_LT:
2744 case NFS4_WRITEW_LT: 2746 case NFS4_WRITEW_LT:
2745 file_lock.fl_type = F_WRLCK; 2747 file_lock.fl_type = F_WRLCK;
2748 cmd = F_SETLK;
2746 break; 2749 break;
2747 default: 2750 default:
2748 status = nfserr_inval; 2751 status = nfserr_inval;
@@ -2769,9 +2772,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2769 2772
2770 /* XXX?: Just to divert the locks_release_private at the start of 2773 /* XXX?: Just to divert the locks_release_private at the start of
2771 * locks_copy_lock: */ 2774 * locks_copy_lock: */
2772 conflock.fl_ops = NULL; 2775 locks_init_lock(&conflock);
2773 conflock.fl_lmops = NULL; 2776 err = posix_lock_file(filp, &file_lock, &conflock);
2774 err = posix_lock_file_conf(filp, &file_lock, &conflock);
2775 switch (-err) { 2777 switch (-err) {
2776 case 0: /* success! */ 2778 case 0: /* success! */
2777 update_stateid(&lock_stp->st_stateid); 2779 update_stateid(&lock_stp->st_stateid);
@@ -2933,7 +2935,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2933 /* 2935 /*
2934 * Try to unlock the file in the VFS. 2936 * Try to unlock the file in the VFS.
2935 */ 2937 */
2936 err = posix_lock_file(filp, &file_lock); 2938 err = posix_lock_file(filp, &file_lock, NULL);
2937 if (err) { 2939 if (err) {
2938 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); 2940 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2939 goto out_nfserr; 2941 goto out_nfserr;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1d5ccdd7c68d..c92d0bdff39f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -852,12 +852,11 @@ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
852extern void locks_remove_posix(struct file *, fl_owner_t); 852extern void locks_remove_posix(struct file *, fl_owner_t);
853extern void locks_remove_flock(struct file *); 853extern void locks_remove_flock(struct file *);
854extern int posix_test_lock(struct file *, struct file_lock *); 854extern int posix_test_lock(struct file *, struct file_lock *);
855extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *); 855extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
856extern int posix_lock_file(struct file *, struct file_lock *);
857extern int posix_lock_file_wait(struct file *, struct file_lock *); 856extern int posix_lock_file_wait(struct file *, struct file_lock *);
858extern int posix_unblock_lock(struct file *, struct file_lock *); 857extern int posix_unblock_lock(struct file *, struct file_lock *);
859extern int vfs_test_lock(struct file *, struct file_lock *); 858extern int vfs_test_lock(struct file *, struct file_lock *);
860extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *); 859extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
861extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); 860extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
862extern int __break_lease(struct inode *inode, unsigned int flags); 861extern int __break_lease(struct inode *inode, unsigned int flags);
863extern void lease_get_mtime(struct inode *, struct timespec *time); 862extern void lease_get_mtime(struct inode *, struct timespec *time);