diff options
author | Marc Eshel <eshel@almaden.ibm.com> | 2007-01-18 16:15:35 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-05-06 19:23:24 -0400 |
commit | 150b393456e5a23513cace286a019e87151e47f0 (patch) | |
tree | 91599ec9b759f7e3c5defcb8dd361acd7288154c /fs/locks.c | |
parent | 7723ec9777d9832849b76475b1a21a2872a40d20 (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>
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 45 |
1 files changed, 20 insertions, 25 deletions
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 | ||
804 | static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) | 804 | static 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 | */ |
1019 | int posix_lock_file(struct file *filp, struct file_lock *fl) | 1020 | int 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 | } | ||
1023 | EXPORT_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 | */ | ||
1033 | int 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 | } |
1038 | EXPORT_SYMBOL(posix_lock_file_conf); | 1025 | EXPORT_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 | */ |
1707 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl) | 1702 | int 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 | } |
1714 | EXPORT_SYMBOL_GPL(vfs_lock_file); | 1709 | EXPORT_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); |