summaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/fs/locks.c b/fs/locks.c
index a364ebc5cec3..6970f55daf54 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -212,6 +212,7 @@ struct file_lock_list_struct {
212static DEFINE_PER_CPU(struct file_lock_list_struct, file_lock_list); 212static DEFINE_PER_CPU(struct file_lock_list_struct, file_lock_list);
213DEFINE_STATIC_PERCPU_RWSEM(file_rwsem); 213DEFINE_STATIC_PERCPU_RWSEM(file_rwsem);
214 214
215
215/* 216/*
216 * The blocked_hash is used to find POSIX lock loops for deadlock detection. 217 * The blocked_hash is used to find POSIX lock loops for deadlock detection.
217 * It is protected by blocked_lock_lock. 218 * It is protected by blocked_lock_lock.
@@ -1991,6 +1992,64 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
1991} 1992}
1992EXPORT_SYMBOL(generic_setlease); 1993EXPORT_SYMBOL(generic_setlease);
1993 1994
1995#if IS_ENABLED(CONFIG_SRCU)
1996/*
1997 * Kernel subsystems can register to be notified on any attempt to set
1998 * a new lease with the lease_notifier_chain. This is used by (e.g.) nfsd
1999 * to close files that it may have cached when there is an attempt to set a
2000 * conflicting lease.
2001 */
2002static struct srcu_notifier_head lease_notifier_chain;
2003
2004static inline void
2005lease_notifier_chain_init(void)
2006{
2007 srcu_init_notifier_head(&lease_notifier_chain);
2008}
2009
2010static inline void
2011setlease_notifier(long arg, struct file_lock *lease)
2012{
2013 if (arg != F_UNLCK)
2014 srcu_notifier_call_chain(&lease_notifier_chain, arg, lease);
2015}
2016
2017int lease_register_notifier(struct notifier_block *nb)
2018{
2019 return srcu_notifier_chain_register(&lease_notifier_chain, nb);
2020}
2021EXPORT_SYMBOL_GPL(lease_register_notifier);
2022
2023void lease_unregister_notifier(struct notifier_block *nb)
2024{
2025 srcu_notifier_chain_unregister(&lease_notifier_chain, nb);
2026}
2027EXPORT_SYMBOL_GPL(lease_unregister_notifier);
2028
2029#else /* !IS_ENABLED(CONFIG_SRCU) */
2030static inline void
2031lease_notifier_chain_init(void)
2032{
2033}
2034
2035static inline void
2036setlease_notifier(long arg, struct file_lock *lease)
2037{
2038}
2039
2040int lease_register_notifier(struct notifier_block *nb)
2041{
2042 return 0;
2043}
2044EXPORT_SYMBOL_GPL(lease_register_notifier);
2045
2046void lease_unregister_notifier(struct notifier_block *nb)
2047{
2048}
2049EXPORT_SYMBOL_GPL(lease_unregister_notifier);
2050
2051#endif /* IS_ENABLED(CONFIG_SRCU) */
2052
1994/** 2053/**
1995 * vfs_setlease - sets a lease on an open file 2054 * vfs_setlease - sets a lease on an open file
1996 * @filp: file pointer 2055 * @filp: file pointer
@@ -2011,6 +2070,8 @@ EXPORT_SYMBOL(generic_setlease);
2011int 2070int
2012vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) 2071vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
2013{ 2072{
2073 if (lease)
2074 setlease_notifier(arg, *lease);
2014 if (filp->f_op->setlease) 2075 if (filp->f_op->setlease)
2015 return filp->f_op->setlease(filp, arg, lease, priv); 2076 return filp->f_op->setlease(filp, arg, lease, priv);
2016 else 2077 else
@@ -2924,6 +2985,7 @@ static int __init filelock_init(void)
2924 INIT_HLIST_HEAD(&fll->hlist); 2985 INIT_HLIST_HEAD(&fll->hlist);
2925 } 2986 }
2926 2987
2988 lease_notifier_chain_init();
2927 return 0; 2989 return 0;
2928} 2990}
2929core_initcall(filelock_init); 2991core_initcall(filelock_init);