root/fs/nfs_common/grace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. locks_start_grace
  2. locks_end_grace
  3. __state_in_grace
  4. locks_in_grace
  5. opens_in_grace
  6. grace_init_net
  7. grace_exit_net
  8. init_grace
  9. exit_grace

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

/* [<][>][^][v][top][bottom][index][help] */