]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/locks.c
Merge remote-tracking branch 'orangefs/for-next'
[karo-tx-linux.git] / fs / locks.c
index d3d558ba4da7966de9699aeb98b2630bd7c6854e..add3eeb79acecc4a0b8d7dcc393c76a9ffc18582 100644 (file)
@@ -1568,6 +1568,7 @@ int fcntl_getlease(struct file *filp)
  *                         desired lease.
  * @dentry:    dentry to check
  * @arg:       type of lease that we're trying to acquire
+ * @flags:     current lock flags
  *
  * Check to see if there's an existing open fd on this file that would
  * conflict with the lease we're trying to set.
@@ -1779,6 +1780,40 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
 }
 EXPORT_SYMBOL(generic_setlease);
 
+#if IS_ENABLED(CONFIG_SRCU)
+/*
+ * Kernel subsystems can register to be notified on any attempt to set
+ * a new lease with the lease_notifier_chain. This is used by (e.g.) nfsd
+ * to close files that it may have cached when there is an attempt to set a
+ * conflicting lease.
+ */
+struct srcu_notifier_head lease_notifier_chain;
+EXPORT_SYMBOL_GPL(lease_notifier_chain);
+
+static inline void
+lease_notifier_chain_init(void)
+{
+       srcu_init_notifier_head(&lease_notifier_chain);
+}
+
+static inline void
+setlease_notifier(long arg, struct file_lock *lease)
+{
+       if (arg != F_UNLCK)
+               srcu_notifier_call_chain(&lease_notifier_chain, arg, lease);
+}
+#else /* !IS_ENABLED(CONFIG_SRCU) */
+static inline void
+lease_notifier_chain_init(void)
+{
+}
+
+static inline void
+setlease_notifier(long arg, struct file_lock *lease)
+{
+}
+#endif /* IS_ENABLED(CONFIG_SRCU) */
+
 /**
  * vfs_setlease        -       sets a lease on an open file
  * @filp:      file pointer
@@ -1799,6 +1834,8 @@ EXPORT_SYMBOL(generic_setlease);
 int
 vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
 {
+       if (lease)
+               setlease_notifier(arg, *lease);
        if (filp->f_op->setlease)
                return filp->f_op->setlease(filp, arg, lease, priv);
        else
@@ -2695,6 +2732,7 @@ static int __init filelock_init(void)
        for_each_possible_cpu(i)
                INIT_HLIST_HEAD(per_cpu_ptr(&file_lock_list, i));
 
+       lease_notifier_chain_init();
        return 0;
 }