linux/fs/nfs_common/grace.c
<<
>>
Prefs
   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 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        list_add(&lm->list, grace_list);
  34        spin_unlock(&grace_lock);
  35}
  36EXPORT_SYMBOL_GPL(locks_start_grace);
  37
  38/**
  39 * locks_end_grace
  40 * @net: net namespace that this lock manager belongs to
  41 * @lm: who this grace period is for
  42 *
  43 * Call this function to state that the given lock manager is ready to
  44 * resume regular locking.  The grace period will not end until all lock
  45 * managers that called locks_start_grace() also call locks_end_grace().
  46 * Note that callers count on it being safe to call this more than once,
  47 * and the second call should be a no-op.
  48 */
  49void
  50locks_end_grace(struct lock_manager *lm)
  51{
  52        spin_lock(&grace_lock);
  53        list_del_init(&lm->list);
  54        spin_unlock(&grace_lock);
  55}
  56EXPORT_SYMBOL_GPL(locks_end_grace);
  57
  58/**
  59 * locks_in_grace
  60 *
  61 * Lock managers call this function to determine when it is OK for them
  62 * to answer ordinary lock requests, and when they should accept only
  63 * lock reclaims.
  64 */
  65int
  66__state_in_grace(struct net *net, bool open)
  67{
  68        struct list_head *grace_list = net_generic(net, grace_net_id);
  69        struct lock_manager *lm;
  70
  71        if (!open)
  72                return !list_empty(grace_list);
  73
  74        list_for_each_entry(lm, grace_list, list) {
  75                if (lm->block_opens)
  76                        return true;
  77        }
  78        return false;
  79}
  80
  81int locks_in_grace(struct net *net)
  82{
  83        return __state_in_grace(net, 0);
  84}
  85EXPORT_SYMBOL_GPL(locks_in_grace);
  86
  87int opens_in_grace(struct net *net)
  88{
  89        return __state_in_grace(net, 1);
  90}
  91EXPORT_SYMBOL_GPL(opens_in_grace);
  92
  93static int __net_init
  94grace_init_net(struct net *net)
  95{
  96        struct list_head *grace_list = net_generic(net, grace_net_id);
  97
  98        INIT_LIST_HEAD(grace_list);
  99        return 0;
 100}
 101
 102static void __net_exit
 103grace_exit_net(struct net *net)
 104{
 105        struct list_head *grace_list = net_generic(net, grace_net_id);
 106
 107        BUG_ON(!list_empty(grace_list));
 108}
 109
 110static struct pernet_operations grace_net_ops = {
 111        .init = grace_init_net,
 112        .exit = grace_exit_net,
 113        .id   = &grace_net_id,
 114        .size = sizeof(struct list_head),
 115};
 116
 117static int __init
 118init_grace(void)
 119{
 120        return register_pernet_subsys(&grace_net_ops);
 121}
 122
 123static void __exit
 124exit_grace(void)
 125{
 126        unregister_pernet_subsys(&grace_net_ops);
 127}
 128
 129MODULE_AUTHOR("Jeff Layton <jlayton@primarydata.com>");
 130MODULE_LICENSE("GPL");
 131module_init(init_grace)
 132module_exit(exit_grace)
 133