Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Common code for control of lockd and nfsv4 grace periods.
  4 *
  5 * Transplanted from lockd code
  6 */
  7
  8#include <linux/module.h>
  9#include <net/net_namespace.h>
 10#include <net/netns/generic.h>
 11#include <linux/fs.h>
 12
 13static unsigned int grace_net_id;
 14static DEFINE_SPINLOCK(grace_lock);
 15
 16/**
 17 * locks_start_grace
 18 * @net: net namespace that this lock manager belongs to
 19 * @lm: who this grace period is for
 20 *
 21 * A grace period is a period during which locks should not be given
 22 * out.  Currently grace periods are only enforced by the two lock
 23 * managers (lockd and nfsd), using the locks_in_grace() function to
 24 * check when they are in a grace period.
 25 *
 26 * This function is called to start a grace period.
 27 */
 28void
 29locks_start_grace(struct net *net, struct lock_manager *lm)
 30{
 31	struct list_head *grace_list = net_generic(net, grace_net_id);
 32
 33	spin_lock(&grace_lock);
 34	if (list_empty(&lm->list))
 35		list_add(&lm->list, grace_list);
 36	else
 37		WARN(1, "double list_add attempt detected in net %x %s\n",
 38		     net->ns.inum, (net == &init_net) ? "(init_net)" : "");
 39	spin_unlock(&grace_lock);
 40}
 41EXPORT_SYMBOL_GPL(locks_start_grace);
 42
 43/**
 44 * locks_end_grace
 45 * @lm: who this grace period is for
 46 *
 47 * Call this function to state that the given lock manager is ready to
 48 * resume regular locking.  The grace period will not end until all lock
 49 * managers that called locks_start_grace() also call locks_end_grace().
 50 * Note that callers count on it being safe to call this more than once,
 51 * and the second call should be a no-op.
 52 */
 53void
 54locks_end_grace(struct lock_manager *lm)
 55{
 56	spin_lock(&grace_lock);
 57	list_del_init(&lm->list);
 58	spin_unlock(&grace_lock);
 59}
 60EXPORT_SYMBOL_GPL(locks_end_grace);
 61
 62static bool
 63__state_in_grace(struct net *net, bool open)
 64{
 65	struct list_head *grace_list = net_generic(net, grace_net_id);
 66	struct lock_manager *lm;
 67
 68	if (!open)
 69		return !list_empty(grace_list);
 70
 71	spin_lock(&grace_lock);
 72	list_for_each_entry(lm, grace_list, list) {
 73		if (lm->block_opens) {
 74			spin_unlock(&grace_lock);
 75			return true;
 76		}
 77	}
 78	spin_unlock(&grace_lock);
 79	return false;
 80}
 81
 82/**
 83 * locks_in_grace
 84 * @net: network namespace
 85 *
 86 * Lock managers call this function to determine when it is OK for them
 87 * to answer ordinary lock requests, and when they should accept only
 88 * lock reclaims.
 89 */
 90bool locks_in_grace(struct net *net)
 91{
 92	return __state_in_grace(net, false);
 93}
 94EXPORT_SYMBOL_GPL(locks_in_grace);
 95
 96bool opens_in_grace(struct net *net)
 97{
 98	return __state_in_grace(net, true);
 99}
100EXPORT_SYMBOL_GPL(opens_in_grace);
101
102static int __net_init
103grace_init_net(struct net *net)
104{
105	struct list_head *grace_list = net_generic(net, grace_net_id);
106
107	INIT_LIST_HEAD(grace_list);
108	return 0;
109}
110
111static void __net_exit
112grace_exit_net(struct net *net)
113{
114	struct list_head *grace_list = net_generic(net, grace_net_id);
115
116	WARN_ONCE(!list_empty(grace_list),
117		  "net %x %s: grace_list is not empty\n",
118		  net->ns.inum, __func__);
119}
120
121static struct pernet_operations grace_net_ops = {
122	.init = grace_init_net,
123	.exit = grace_exit_net,
124	.id   = &grace_net_id,
125	.size = sizeof(struct list_head),
126};
127
128static int __init
129init_grace(void)
130{
131	return register_pernet_subsys(&grace_net_ops);
132}
133
134static void __exit
135exit_grace(void)
136{
137	unregister_pernet_subsys(&grace_net_ops);
138}
139
140MODULE_AUTHOR("Jeff Layton <jlayton@primarydata.com>");
141MODULE_LICENSE("GPL");
142module_init(init_grace)
143module_exit(exit_grace)