Skip to content

Commit ab1ddef

Browse files
committed
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 <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jeff Layton <[email protected]>
1 parent 7e8e5cc commit ab1ddef

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
@@ -2672,6 +2672,29 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
26722672
}
26732673
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
26742674

2675+
/**
2676+
* vfs_inode_has_locks - are any file locks held on @inode?
2677+
* @inode: inode to check for locks
2678+
*
2679+
* Return true if there are any FL_POSIX or FL_FLOCK locks currently
2680+
* set on @inode.
2681+
*/
2682+
bool vfs_inode_has_locks(struct inode *inode)
2683+
{
2684+
struct file_lock_context *ctx;
2685+
bool ret;
2686+
2687+
ctx = smp_load_acquire(&inode->i_flctx);
2688+
if (!ctx)
2689+
return false;
2690+
2691+
spin_lock(&ctx->flc_lock);
2692+
ret = !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_flock);
2693+
spin_unlock(&ctx->flc_lock);
2694+
return ret;
2695+
}
2696+
EXPORT_SYMBOL_GPL(vfs_inode_has_locks);
2697+
26752698
#ifdef CONFIG_PROC_FS
26762699
#include <linux/proc_fs.h>
26772700
#include <linux/seq_file.h>

include/linux/fs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ extern int locks_delete_block(struct file_lock *);
11701170
extern int vfs_test_lock(struct file *, struct file_lock *);
11711171
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
11721172
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
1173+
bool vfs_inode_has_locks(struct inode *inode);
11731174
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
11741175
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
11751176
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)
12841285
return 0;
12851286
}
12861287

1288+
static inline bool vfs_inode_has_locks(struct inode *inode)
1289+
{
1290+
return false;
1291+
}
1292+
12871293
static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
12881294
{
12891295
return -ENOLCK;

0 commit comments

Comments
 (0)