cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

grace.c (3431B)


      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)