0001
0002
0003
0004
0005
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
0018
0019
0020
0021
0022
0023
0024
0025
0026
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
0045
0046
0047
0048
0049
0050
0051
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
0084
0085
0086
0087
0088
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)