X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-linux.git;a=blobdiff_plain;f=fs%2Flocks.c;h=add3eeb79acecc4a0b8d7dcc393c76a9ffc18582;hp=2a54c800a22391cbd78af02f2d9a70804519c815;hb=e6b81abe2d9940cf210adb0799b6aabc1622d822;hpb=d8cc3972b2178f9fe532306330f76bf51cb0d8bd diff --git a/fs/locks.c b/fs/locks.c index 2a54c800a223..add3eeb79ace 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1780,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 @@ -1800,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 @@ -2696,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; }