diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/locks.c b/fs/locks.c index 686eae21daf6..1913481bfbf7 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1990,6 +1990,64 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp, | |||
1990 | } | 1990 | } |
1991 | EXPORT_SYMBOL(generic_setlease); | 1991 | EXPORT_SYMBOL(generic_setlease); |
1992 | 1992 | ||
1993 | #if IS_ENABLED(CONFIG_SRCU) | ||
1994 | /* | ||
1995 | * Kernel subsystems can register to be notified on any attempt to set | ||
1996 | * a new lease with the lease_notifier_chain. This is used by (e.g.) nfsd | ||
1997 | * to close files that it may have cached when there is an attempt to set a | ||
1998 | * conflicting lease. | ||
1999 | */ | ||
2000 | static struct srcu_notifier_head lease_notifier_chain; | ||
2001 | |||
2002 | static inline void | ||
2003 | lease_notifier_chain_init(void) | ||
2004 | { | ||
2005 | srcu_init_notifier_head(&lease_notifier_chain); | ||
2006 | } | ||
2007 | |||
2008 | static inline void | ||
2009 | setlease_notifier(long arg, struct file_lock *lease) | ||
2010 | { | ||
2011 | if (arg != F_UNLCK) | ||
2012 | srcu_notifier_call_chain(&lease_notifier_chain, arg, lease); | ||
2013 | } | ||
2014 | |||
2015 | int lease_register_notifier(struct notifier_block *nb) | ||
2016 | { | ||
2017 | return srcu_notifier_chain_register(&lease_notifier_chain, nb); | ||
2018 | } | ||
2019 | EXPORT_SYMBOL_GPL(lease_register_notifier); | ||
2020 | |||
2021 | void lease_unregister_notifier(struct notifier_block *nb) | ||
2022 | { | ||
2023 | srcu_notifier_chain_unregister(&lease_notifier_chain, nb); | ||
2024 | } | ||
2025 | EXPORT_SYMBOL_GPL(lease_unregister_notifier); | ||
2026 | |||
2027 | #else /* !IS_ENABLED(CONFIG_SRCU) */ | ||
2028 | static inline void | ||
2029 | lease_notifier_chain_init(void) | ||
2030 | { | ||
2031 | } | ||
2032 | |||
2033 | static inline void | ||
2034 | setlease_notifier(long arg, struct file_lock *lease) | ||
2035 | { | ||
2036 | } | ||
2037 | |||
2038 | int lease_register_notifier(struct notifier_block *nb) | ||
2039 | { | ||
2040 | return 0; | ||
2041 | } | ||
2042 | EXPORT_SYMBOL_GPL(lease_register_notifier); | ||
2043 | |||
2044 | void lease_unregister_notifier(struct notifier_block *nb) | ||
2045 | { | ||
2046 | } | ||
2047 | EXPORT_SYMBOL_GPL(lease_unregister_notifier); | ||
2048 | |||
2049 | #endif /* IS_ENABLED(CONFIG_SRCU) */ | ||
2050 | |||
1993 | /** | 2051 | /** |
1994 | * vfs_setlease - sets a lease on an open file | 2052 | * vfs_setlease - sets a lease on an open file |
1995 | * @filp: file pointer | 2053 | * @filp: file pointer |
@@ -2010,6 +2068,8 @@ EXPORT_SYMBOL(generic_setlease); | |||
2010 | int | 2068 | int |
2011 | vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) | 2069 | vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) |
2012 | { | 2070 | { |
2071 | if (lease) | ||
2072 | setlease_notifier(arg, *lease); | ||
2013 | if (filp->f_op->setlease) | 2073 | if (filp->f_op->setlease) |
2014 | return filp->f_op->setlease(filp, arg, lease, priv); | 2074 | return filp->f_op->setlease(filp, arg, lease, priv); |
2015 | else | 2075 | else |
@@ -2923,6 +2983,7 @@ static int __init filelock_init(void) | |||
2923 | INIT_HLIST_HEAD(&fll->hlist); | 2983 | INIT_HLIST_HEAD(&fll->hlist); |
2924 | } | 2984 | } |
2925 | 2985 | ||
2986 | lease_notifier_chain_init(); | ||
2926 | return 0; | 2987 | return 0; |
2927 | } | 2988 | } |
2928 | core_initcall(filelock_init); | 2989 | core_initcall(filelock_init); |