filelock: new helper: vfs_inode_has_locks
Ceph has a need to know whether a particular inode has any locks set on it. It's currently tracking that by a num_locks field in its filp->private_data, but that's problematic as it tries to decrement this field when releasing locks and that can race with the file being torn down. Add a new vfs_inode_has_locks helper that just returns whether any locks are currently held on the inode. Reviewed-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Jeff Layton <jlayton@kernel.org>
This commit is contained in:
parent
7e8e5cc818
commit
ab1ddef98a
23
fs/locks.c
23
fs/locks.c
|
@ -2672,6 +2672,29 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
|
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vfs_inode_has_locks - are any file locks held on @inode?
|
||||||
|
* @inode: inode to check for locks
|
||||||
|
*
|
||||||
|
* Return true if there are any FL_POSIX or FL_FLOCK locks currently
|
||||||
|
* set on @inode.
|
||||||
|
*/
|
||||||
|
bool vfs_inode_has_locks(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct file_lock_context *ctx;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
ctx = smp_load_acquire(&inode->i_flctx);
|
||||||
|
if (!ctx)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
spin_lock(&ctx->flc_lock);
|
||||||
|
ret = !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_flock);
|
||||||
|
spin_unlock(&ctx->flc_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(vfs_inode_has_locks);
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
|
|
@ -1170,6 +1170,7 @@ extern int locks_delete_block(struct file_lock *);
|
||||||
extern int vfs_test_lock(struct file *, struct file_lock *);
|
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_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 vfs_cancel_lock(struct file *filp, struct file_lock *fl);
|
||||||
|
bool vfs_inode_has_locks(struct inode *inode);
|
||||||
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
|
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
|
||||||
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
|
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
|
||||||
extern void lease_get_mtime(struct inode *, struct timespec64 *time);
|
extern void lease_get_mtime(struct inode *, struct timespec64 *time);
|
||||||
|
@ -1284,6 +1285,11 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool vfs_inode_has_locks(struct inode *inode)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
|
static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
|
||||||
{
|
{
|
||||||
return -ENOLCK;
|
return -ENOLCK;
|
||||||
|
|
Loading…
Reference in New Issue