Message ID | 1403189450-18729-10-git-send-email-jlayton@primarydata.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jun 19, 2014 at 10:49:15AM -0400, Jeff Layton wrote: > Add a function that can tell us whether a file description has had a > lease set on it. The code looks good, but how is this information useful given that it will be stable as soon as i_lock is dropped? -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 23 Jun 2014 09:12:54 -0700 Christoph Hellwig <hch@infradead.org> wrote: > On Thu, Jun 19, 2014 at 10:49:15AM -0400, Jeff Layton wrote: > > Add a function that can tell us whether a file description has had a > > lease set on it. > > The code looks good, but how is this information useful given that it > will be stable as soon as i_lock is dropped? > The next patch is what uses it. I can squash the two together, but I figured it was best to keep them separate since we're touching two different subsystems here. The basic idea here is to avoid calling vfs_setlease under a spinlock. The next patch does that and then takes the spinlocks and hash the delegation once the lease is set. Problem: what if the delegation got broken before we could hash it? The workqueue job that's queued by break_deleg will take the state_lock spinlock before it can unhash the delegation. So, we take the state_lock and then call file_has_lease. If the lease is still present then we know that it hasn't been (and won't be) broken before we could hash it.
diff --git a/fs/locks.c b/fs/locks.c index da57c9b7e844..402169f95502 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1308,6 +1308,32 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker) } /** + * file_has_lease - does the given file have a lease set on it? + * @file: struct file on which we want to check the lease + * + * Returns true if a lease was is set on the given file description, + * false otherwise. + */ +bool +file_has_lease(struct file *file) +{ + bool ret = false; + struct inode *inode = file_inode(file); + struct file_lock *fl; + + spin_lock(&inode->i_lock); + for (fl = inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) { + if (fl->fl_file == file) { + ret = true; + break; + } + } + spin_unlock(&inode->i_lock); + return ret; +} +EXPORT_SYMBOL(file_has_lease); + +/** * __break_lease - revoke all outstanding leases on file * @inode: the inode of the file to return * @mode: O_RDONLY: break only write leases; O_WRONLY or O_RDWR: diff --git a/include/linux/fs.h b/include/linux/fs.h index 338e6f758c6d..7937523c21ca 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -953,6 +953,7 @@ extern int vfs_test_lock(struct file *, struct file_lock *); extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *); 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 bool file_has_lease(struct file *file); extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); extern void lease_get_mtime(struct inode *, struct timespec *time); extern int generic_setlease(struct file *, long, struct file_lock **); @@ -1064,6 +1065,11 @@ static inline int flock_lock_file_wait(struct file *filp, return -ENOLCK; } +static inline bool file_has_lease(struct file *file) +{ + return false; +} + static inline int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) { return 0;
Add a function that can tell us whether a file description has had a lease set on it. Signed-off-by: Jeff Layton <jlayton@primarydata.com> --- fs/locks.c | 26 ++++++++++++++++++++++++++ include/linux/fs.h | 6 ++++++ 2 files changed, 32 insertions(+)