[PATCH RFC v2 17/28] filelock: add an inode_lease_ignore_mask helper

From: Jeff Layton
Date: Mon Jun 02 2025 - 10:12:24 EST


Add a new routine that returns a mask of all dir change events that are
currently ignored by any leases. nfsd will use this to determine how to
configure the fsnotify_mark mask.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
fs/locks.c | 32 ++++++++++++++++++++++++++++++++
include/linux/filelock.h | 1 +
2 files changed, 33 insertions(+)

diff --git a/fs/locks.c b/fs/locks.c
index 95270a1fab4a1792a6fcad738cc9d937d99ad2af..522455196353f64d3150c45c9d1cd260751bd7b9 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1526,6 +1526,38 @@ any_leases_conflict(struct inode *inode, struct file_lease *breaker)
return false;
}

+#define IGNORE_MASK (FL_IGN_DIR_CREATE | FL_IGN_DIR_DELETE | FL_IGN_DIR_RENAME)
+
+/**
+ * inode_lease_ignore_mask - return union of all ignored inode events for this inode
+ * @inode: inode of which to get ignore mask
+ *
+ * Walk the list of leases, and return the result of all of
+ * their FL_IGN_DIR_* bits or'ed together.
+ */
+u32
+inode_lease_ignore_mask(struct inode *inode)
+{
+ struct file_lock_context *ctx;
+ struct file_lock_core *flc;
+ u32 mask = 0;
+
+ ctx = locks_inode_context(inode);
+ if (!ctx)
+ return 0;
+
+ spin_lock(&ctx->flc_lock);
+ list_for_each_entry(flc, &ctx->flc_lease, flc_list) {
+ mask |= flc->flc_flags & IGNORE_MASK;
+ /* If we already have everything, we can stop */
+ if (mask == IGNORE_MASK)
+ break;
+ }
+ spin_unlock(&ctx->flc_lock);
+ return mask;
+}
+EXPORT_SYMBOL_GPL(inode_lease_ignore_mask);
+
static bool
ignore_dir_deleg_break(struct file_lease *fl, unsigned int flags)
{
diff --git a/include/linux/filelock.h b/include/linux/filelock.h
index 32b30c14f5fd52727b1a18957e9dbc930c922941..4513a8dad3974bf5fb08e0df4f085d71155e04f5 100644
--- a/include/linux/filelock.h
+++ b/include/linux/filelock.h
@@ -244,6 +244,7 @@ int generic_setlease(struct file *, int, struct file_lease **, void **priv);
int kernel_setlease(struct file *, int, struct file_lease **, void **);
int vfs_setlease(struct file *, int, struct file_lease **, void **);
int lease_modify(struct file_lease *, int, struct list_head *);
+u32 inode_lease_ignore_mask(struct inode *inode);

struct notifier_block;
int lease_register_notifier(struct notifier_block *);

--
2.49.0