From a9933cea7a1d80dd9efae9f1acd857f5dce742b9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 7 Jun 2007 17:09:49 -0400 Subject: locks: rename lease functions to reflect locks.c conventions We've been using the convention that vfs_foo is the function that calls a filesystem-specific foo method if it exists, or falls back on a generic method if it doesn't; thus vfs_foo is what is called when some other part of the kernel (normally lockd or nfsd) wants to get a lock, whereas foo is what filesystems call to use the underlying local functionality as part of their lock implementation. So rename setlease to vfs_setlease (which will call a filesystem-specific setlease after a later patch) and __setlease to setlease. Also, vfs_setlease need only be GPL-exported as long as it's only needed by lockd and nfsd. Signed-off-by: "J. Bruce Fields" --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 98205f680476..a24f029accc0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -872,7 +872,7 @@ extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl); extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); extern int __break_lease(struct inode *inode, unsigned int flags); extern void lease_get_mtime(struct inode *, struct timespec *time); -extern int setlease(struct file *, long, struct file_lock **); +extern int vfs_setlease(struct file *, long, struct file_lock **); extern int lease_modify(struct file_lock **, int); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); -- cgit v1.2.3 From f9ffed26d6f3e6ac9988947242821579d615fda7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 14 Nov 2006 15:51:40 -0500 Subject: locks: provide a file lease method enabling cluster-coherent leases Currently leases are only kept locally, so there's no way for a distributed filesystem to enforce them against multiple clients. We're particularly interested in the case of nfsd exporting a cluster filesystem, in which case nfsd needs cluster-coherent leases in order to implement delegations correctly. Also add some documentation. Signed-off-by: J. Bruce Fields --- fs/locks.c | 24 ++++++++++++++++++++++-- include/linux/fs.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/locks.c b/fs/locks.c index a65d85c1fdc2..94f5d8065e3a 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1429,7 +1429,24 @@ out: * @lease: file_lock to use * * Call this to establish a lease on the file. - * The fl_lmops fl_break function is required by break_lease + * The (*lease)->fl_lmops->fl_break operation must be set; if not, + * break_lease will oops! + * + * This will call the filesystem's setlease file method, if + * defined. Note that there is no getlease method; instead, the + * filesystem setlease method should call back to setlease() to + * add a lease to the inode's lease list, where fcntl_getlease() can + * find it. Since fcntl_getlease() only reports whether the current + * task holds a lease, a cluster filesystem need only do this for + * leases held by processes on this node. + * + * There is also no break_lease method; filesystems that + * handle their own leases shoud break leases themselves from the + * filesystem's open, create, and (on truncate) setattr methods. + * + * Warning: the only current setlease methods exist only to disable + * leases in certain cases. More vfs changes may be required to + * allow a full filesystem lease implementation. */ int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) @@ -1437,7 +1454,10 @@ int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) int error; lock_kernel(); - error = setlease(filp, arg, lease); + if (filp->f_op && filp->f_op->setlease) + error = filp->f_op->setlease(filp, arg, lease); + else + error = setlease(filp, arg, lease); unlock_kernel(); return error; diff --git a/include/linux/fs.h b/include/linux/fs.h index a24f029accc0..c8ddf34e9710 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1122,6 +1122,7 @@ struct file_operations { int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); + int (*setlease)(struct file *, long, struct file_lock **); }; struct inode_operations { -- cgit v1.2.3 From 4698afe8e3a725576366f86560a8a8242b21b9f7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 4 Jul 2007 17:21:37 -0400 Subject: locks: export setlease to filesystems Export setlease so it can used by filesystems to implement their lease methods. Signed-off-by: "J. Bruce Fields" --- fs/locks.c | 3 ++- include/linux/fs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/fs/locks.c b/fs/locks.c index 94f5d8065e3a..4c73b857dded 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1336,7 +1336,7 @@ int fcntl_getlease(struct file *filp) * * Called with kernel lock held. */ -static int setlease(struct file *filp, long arg, struct file_lock **flp) +int setlease(struct file *filp, long arg, struct file_lock **flp) { struct file_lock *fl, **before, **my_before = NULL, *lease; struct dentry *dentry = filp->f_path.dentry; @@ -1421,6 +1421,7 @@ static int setlease(struct file *filp, long arg, struct file_lock **flp) out: return error; } +EXPORT_SYMBOL(setlease); /** * vfs_setlease - sets a lease on an open file diff --git a/include/linux/fs.h b/include/linux/fs.h index c8ddf34e9710..b188c2e5338d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -872,6 +872,7 @@ extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl); extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); extern int __break_lease(struct inode *inode, unsigned int flags); extern void lease_get_mtime(struct inode *, struct timespec *time); +extern int setlease(struct file *, long, struct file_lock **); extern int vfs_setlease(struct file *, long, struct file_lock **); extern int lease_modify(struct file_lock **, int); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); -- cgit v1.2.3 From 6d34ac199a4af5c678a3a8f3275aeb2586b72da3 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 11 May 2007 16:09:32 -0400 Subject: locks: make posix_test_lock() interface more consistent Since posix_test_lock(), like fcntl() and ->lock(), indicates absence or presence of a conflict lock by setting fl_type to, respectively, F_UNLCK or something other than F_UNLCK, the return value is no longer needed. Signed-off-by: "J. Bruce Fields" --- fs/locks.c | 10 ++++------ fs/nfs/file.c | 4 +++- include/linux/fs.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/fs/locks.c b/fs/locks.c index 4c73b857dded..4a8072736efa 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -659,7 +659,7 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w return result; } -int +void posix_test_lock(struct file *filp, struct file_lock *fl) { struct file_lock *cfl; @@ -671,14 +671,12 @@ posix_test_lock(struct file *filp, struct file_lock *fl) if (posix_locks_conflict(cfl, fl)) break; } - if (cfl) { + if (cfl) __locks_copy_lock(fl, cfl); - unlock_kernel(); - return 1; - } else + else fl->fl_type = F_UNLCK; unlock_kernel(); - return 0; + return; } EXPORT_SYMBOL(posix_test_lock); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 13ac6fa2b62b..c87dc713b5d7 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -402,7 +402,9 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) lock_kernel(); /* Try local locking first */ - if (posix_test_lock(filp, fl)) { + posix_test_lock(filp, fl); + if (fl->fl_type != F_UNLCK) { + /* found a conflict */ goto out; } diff --git a/include/linux/fs.h b/include/linux/fs.h index b188c2e5338d..80deaaf1b746 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -862,7 +862,7 @@ extern void locks_init_lock(struct file_lock *); extern void locks_copy_lock(struct file_lock *, struct file_lock *); extern void locks_remove_posix(struct file *, fl_owner_t); extern void locks_remove_flock(struct file *); -extern int posix_test_lock(struct file *, struct file_lock *); +extern void posix_test_lock(struct file *, struct file_lock *); extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *); extern int posix_lock_file_wait(struct file *, struct file_lock *); extern int posix_unblock_lock(struct file *, struct file_lock *); -- cgit v1.2.3