aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/locks.c61
-rw-r--r--include/linux/fs.h5
2 files changed, 66 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}
1991EXPORT_SYMBOL(generic_setlease); 1991EXPORT_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 */
2000static struct srcu_notifier_head lease_notifier_chain;
2001
2002static inline void
2003lease_notifier_chain_init(void)
2004{
2005 srcu_init_notifier_head(&lease_notifier_chain);
2006}
2007
2008static inline void
2009setlease_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
2015int lease_register_notifier(struct notifier_block *nb)
2016{
2017 return srcu_notifier_chain_register(&lease_notifier_chain, nb);
2018}
2019EXPORT_SYMBOL_GPL(lease_register_notifier);
2020
2021void lease_unregister_notifier(struct notifier_block *nb)
2022{
2023 srcu_notifier_chain_unregister(&lease_notifier_chain, nb);
2024}
2025EXPORT_SYMBOL_GPL(lease_unregister_notifier);
2026
2027#else /* !IS_ENABLED(CONFIG_SRCU) */
2028static inline void
2029lease_notifier_chain_init(void)
2030{
2031}
2032
2033static inline void
2034setlease_notifier(long arg, struct file_lock *lease)
2035{
2036}
2037
2038int lease_register_notifier(struct notifier_block *nb)
2039{
2040 return 0;
2041}
2042EXPORT_SYMBOL_GPL(lease_register_notifier);
2043
2044void lease_unregister_notifier(struct notifier_block *nb)
2045{
2046}
2047EXPORT_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);
2010int 2068int
2011vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) 2069vfs_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}
2928core_initcall(filelock_init); 2989core_initcall(filelock_init);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 56b8e358af5c..0f106c7f4bb9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1155,6 +1155,11 @@ extern void lease_get_mtime(struct inode *, struct timespec64 *time);
1155extern int generic_setlease(struct file *, long, struct file_lock **, void **priv); 1155extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
1156extern int vfs_setlease(struct file *, long, struct file_lock **, void **); 1156extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
1157extern int lease_modify(struct file_lock *, int, struct list_head *); 1157extern int lease_modify(struct file_lock *, int, struct list_head *);
1158
1159struct notifier_block;
1160extern int lease_register_notifier(struct notifier_block *);
1161extern void lease_unregister_notifier(struct notifier_block *);
1162
1158struct files_struct; 1163struct files_struct;
1159extern void show_fd_locks(struct seq_file *f, 1164extern void show_fd_locks(struct seq_file *f,
1160 struct file *filp, struct files_struct *files); 1165 struct file *filp, struct files_struct *files);