Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Common code for control of lockd and nfsv4 grace periods.
0004  *
0005  * Transplanted from lockd code
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <net/net_namespace.h>
0010 #include <net/netns/generic.h>
0011 #include <linux/fs.h>
0012 
0013 static unsigned int grace_net_id;
0014 static DEFINE_SPINLOCK(grace_lock);
0015 
0016 /**
0017  * locks_start_grace
0018  * @net: net namespace that this lock manager belongs to
0019  * @lm: who this grace period is for
0020  *
0021  * A grace period is a period during which locks should not be given
0022  * out.  Currently grace periods are only enforced by the two lock
0023  * managers (lockd and nfsd), using the locks_in_grace() function to
0024  * check when they are in a grace period.
0025  *
0026  * This function is called to start a grace period.
0027  */
0028 void
0029 locks_start_grace(struct net *net, struct lock_manager *lm)
0030 {
0031     struct list_head *grace_list = net_generic(net, grace_net_id);
0032 
0033     spin_lock(&grace_lock);
0034     if (list_empty(&lm->list))
0035         list_add(&lm->list, grace_list);
0036     else
0037         WARN(1, "double list_add attempt detected in net %x %s\n",
0038              net->ns.inum, (net == &init_net) ? "(init_net)" : "");
0039     spin_unlock(&grace_lock);
0040 }
0041 EXPORT_SYMBOL_GPL(locks_start_grace);
0042 
0043 /**
0044  * locks_end_grace
0045  * @lm: who this grace period is for
0046  *
0047  * Call this function to state that the given lock manager is ready to
0048  * resume regular locking.  The grace period will not end until all lock
0049  * managers that called locks_start_grace() also call locks_end_grace().
0050  * Note that callers count on it being safe to call this more than once,
0051  * and the second call should be a no-op.
0052  */
0053 void
0054 locks_end_grace(struct lock_manager *lm)
0055 {
0056     spin_lock(&grace_lock);
0057     list_del_init(&lm->list);
0058     spin_unlock(&grace_lock);
0059 }
0060 EXPORT_SYMBOL_GPL(locks_end_grace);
0061 
0062 static bool
0063 __state_in_grace(struct net *net, bool open)
0064 {
0065     struct list_head *grace_list = net_generic(net, grace_net_id);
0066     struct lock_manager *lm;
0067 
0068     if (!open)
0069         return !list_empty(grace_list);
0070 
0071     spin_lock(&grace_lock);
0072     list_for_each_entry(lm, grace_list, list) {
0073         if (lm->block_opens) {
0074             spin_unlock(&grace_lock);
0075             return true;
0076         }
0077     }
0078     spin_unlock(&grace_lock);
0079     return false;
0080 }
0081 
0082 /**
0083  * locks_in_grace
0084  * @net: network namespace
0085  *
0086  * Lock managers call this function to determine when it is OK for them
0087  * to answer ordinary lock requests, and when they should accept only
0088  * lock reclaims.
0089  */
0090 bool locks_in_grace(struct net *net)
0091 {
0092     return __state_in_grace(net, false);
0093 }
0094 EXPORT_SYMBOL_GPL(locks_in_grace);
0095 
0096 bool opens_in_grace(struct net *net)
0097 {
0098     return __state_in_grace(net, true);
0099 }
0100 EXPORT_SYMBOL_GPL(opens_in_grace);
0101 
0102 static int __net_init
0103 grace_init_net(struct net *net)
0104 {
0105     struct list_head *grace_list = net_generic(net, grace_net_id);
0106 
0107     INIT_LIST_HEAD(grace_list);
0108     return 0;
0109 }
0110 
0111 static void __net_exit
0112 grace_exit_net(struct net *net)
0113 {
0114     struct list_head *grace_list = net_generic(net, grace_net_id);
0115 
0116     WARN_ONCE(!list_empty(grace_list),
0117           "net %x %s: grace_list is not empty\n",
0118           net->ns.inum, __func__);
0119 }
0120 
0121 static struct pernet_operations grace_net_ops = {
0122     .init = grace_init_net,
0123     .exit = grace_exit_net,
0124     .id   = &grace_net_id,
0125     .size = sizeof(struct list_head),
0126 };
0127 
0128 static int __init
0129 init_grace(void)
0130 {
0131     return register_pernet_subsys(&grace_net_ops);
0132 }
0133 
0134 static void __exit
0135 exit_grace(void)
0136 {
0137     unregister_pernet_subsys(&grace_net_ops);
0138 }
0139 
0140 MODULE_AUTHOR("Jeff Layton <jlayton@primarydata.com>");
0141 MODULE_LICENSE("GPL");
0142 module_init(init_grace)
0143 module_exit(exit_grace)