Skip to content

Commit 54e72ce

Browse files
jtlaytongregkh
authored andcommitted
filelock: new helper: vfs_inode_has_locks
[ Upstream commit ab1ddef ] 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> Stable-dep-of: 461ab10 ("ceph: switch to vfs_inode_has_locks() to fix file lock bug") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f34b03c commit 54e72ce

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

fs/locks.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,6 +2703,29 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
27032703
}
27042704
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
27052705

2706+
/**
2707+
* vfs_inode_has_locks - are any file locks held on @inode?
2708+
* @inode: inode to check for locks
2709+
*
2710+
* Return true if there are any FL_POSIX or FL_FLOCK locks currently
2711+
* set on @inode.
2712+
*/
2713+
bool vfs_inode_has_locks(struct inode *inode)
2714+
{
2715+
struct file_lock_context *ctx;
2716+
bool ret;
2717+
2718+
ctx = smp_load_acquire(&inode->i_flctx);
2719+
if (!ctx)
2720+
return false;
2721+
2722+
spin_lock(&ctx->flc_lock);
2723+
ret = !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_flock);
2724+
spin_unlock(&ctx->flc_lock);
2725+
return ret;
2726+
}
2727+
EXPORT_SYMBOL_GPL(vfs_inode_has_locks);
2728+
27062729
#ifdef CONFIG_PROC_FS
27072730
#include <linux/proc_fs.h>
27082731
#include <linux/seq_file.h>

include/linux/fs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ extern int locks_delete_block(struct file_lock *);
11951195
extern int vfs_test_lock(struct file *, struct file_lock *);
11961196
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
11971197
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
1198+
bool vfs_inode_has_locks(struct inode *inode);
11981199
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
11991200
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
12001201
extern void lease_get_mtime(struct inode *, struct timespec64 *time);
@@ -1307,6 +1308,11 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
13071308
return 0;
13081309
}
13091310

1311+
static inline bool vfs_inode_has_locks(struct inode *inode)
1312+
{
1313+
return false;
1314+
}
1315+
13101316
static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
13111317
{
13121318
return -ENOLCK;

0 commit comments

Comments
 (0)