diff options
author | Marc Eshel <eshel@almaden.ibm.com> | 2007-01-18 22:15:35 +0100 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-05-07 01:23:24 +0200 |
commit | 150b393456e5a23513cace286a019e87151e47f0 (patch) | |
tree | 91599ec9b759f7e3c5defcb8dd361acd7288154c /fs/locks.c | |
parent | locks: factor out generic/filesystem switch from setlock code (diff) | |
download | linux-150b393456e5a23513cace286a019e87151e47f0.tar.xz linux-150b393456e5a23513cace286a019e87151e47f0.zip |
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: return error; } -static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) +static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock) { struct file_lock *fl; struct file_lock *new_fl = NULL; @@ -1007,6 +1007,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request * posix_lock_file - Apply a POSIX-style lock to a file * @filp: The file to apply the lock to * @fl: The lock to be applied + * @conflock: Place to return a copy of the conflicting lock, if found. * * Add a POSIX style lock to a file. * We merge adjacent & overlapping locks whenever possible. @@ -1016,26 +1017,12 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request * whether or not a lock was successfully freed by testing the return * value for -ENOENT. */ -int posix_lock_file(struct file *filp, struct file_lock *fl) -{ - return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL); -} -EXPORT_SYMBOL(posix_lock_file); - -/** - * posix_lock_file_conf - Apply a POSIX-style lock to a file - * @filp: The file to apply the lock to - * @fl: The lock to be applied - * @conflock: Place to return a copy of the conflicting lock, if found. - * - * Except for the conflock parameter, acts just like posix_lock_file. - */ -int posix_lock_file_conf(struct file *filp, struct file_lock *fl, +int posix_lock_file(struct file *filp, struct file_lock *fl, struct file_lock *conflock) { - return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock); + return __posix_lock_file(filp->f_path.dentry->d_inode, fl, conflock); } -EXPORT_SYMBOL(posix_lock_file_conf); +EXPORT_SYMBOL(posix_lock_file); /** * 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) int error; might_sleep (); for (;;) { - error = posix_lock_file(filp, fl); + error = posix_lock_file(filp, fl, NULL); if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) break; error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); @@ -1123,7 +1110,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, fl.fl_end = offset + count - 1; for (;;) { - error = __posix_lock_file_conf(inode, &fl, NULL); + error = __posix_lock_file(inode, &fl, NULL); if (error != -EAGAIN) break; if (!(fl.fl_flags & FL_SLEEP)) @@ -1703,13 +1690,21 @@ out: * @filp: The file to apply the lock to * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.) * @fl: The lock to be applied + * @conf: Place to return a copy of the conflicting lock, if found. + * + * A caller that doesn't care about the conflicting lock may pass NULL + * as the final argument. + * + * If the filesystem defines a private ->lock() method, then @conf will + * be left unchanged; so a caller that cares should initialize it to + * some acceptable default. */ -int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl) +int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) { if (filp->f_op && filp->f_op->lock) return filp->f_op->lock(filp, cmd, fl); else - return posix_lock_file(filp, fl); + return posix_lock_file(filp, fl, conf); } EXPORT_SYMBOL_GPL(vfs_lock_file); @@ -1776,7 +1771,7 @@ again: goto out; for (;;) { - error = vfs_lock_file(filp, cmd, file_lock); + error = vfs_lock_file(filp, cmd, file_lock, NULL); if (error != -EAGAIN || cmd == F_SETLK) break; error = wait_event_interruptible(file_lock->fl_wait, @@ -1902,7 +1897,7 @@ again: goto out; for (;;) { - error = vfs_lock_file(filp, cmd, file_lock); + error = vfs_lock_file(filp, cmd, file_lock, NULL); if (error != -EAGAIN || cmd == F_SETLK64) break; error = wait_event_interruptible(file_lock->fl_wait, @@ -1956,7 +1951,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) lock.fl_ops = NULL; lock.fl_lmops = NULL; - vfs_lock_file(filp, F_SETLK, &lock); + vfs_lock_file(filp, F_SETLK, &lock, NULL); if (lock.fl_ops && lock.fl_ops->fl_release_private) lock.fl_ops->fl_release_private(&lock); |