Linux Audio

Check our new training course

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