Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44abdc30 authored by Cong Wang's avatar Cong Wang Committed by Steffen Klassert
Browse files

xfrm: replace rwlock on xfrm_state_afinfo with rcu



Similar to commit 418a99ac
(Replace rwlock on xfrm_policy_afinfo with rcu), the rwlock
on xfrm_state_afinfo can be replaced by RCU too.

Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: default avatarCong Wang <amwang@redhat.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 0024dc53
Loading
Loading
Loading
Loading
+16 −17
Original line number Diff line number Diff line
@@ -158,8 +158,8 @@ static void xfrm_hash_resize(struct work_struct *work)
	mutex_unlock(&hash_resize_mutex);
}

static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
static DEFINE_SPINLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO];

static DEFINE_SPINLOCK(xfrm_state_gc_lock);

@@ -173,17 +173,16 @@ static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family)
	struct xfrm_state_afinfo *afinfo;
	if (unlikely(family >= NPROTO))
		return NULL;
	write_lock_bh(&xfrm_state_afinfo_lock);
	spin_lock_bh(&xfrm_state_afinfo_lock);
	afinfo = xfrm_state_afinfo[family];
	if (unlikely(!afinfo))
		write_unlock_bh(&xfrm_state_afinfo_lock);
		spin_unlock_bh(&xfrm_state_afinfo_lock);
	return afinfo;
}

static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
	__releases(xfrm_state_afinfo_lock)
{
	write_unlock_bh(&xfrm_state_afinfo_lock);
	spin_unlock_bh(&xfrm_state_afinfo_lock);
}

int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
@@ -1845,12 +1844,12 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
		return -EINVAL;
	if (unlikely(afinfo->family >= NPROTO))
		return -EAFNOSUPPORT;
	write_lock_bh(&xfrm_state_afinfo_lock);
	spin_lock_bh(&xfrm_state_afinfo_lock);
	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
		err = -ENOBUFS;
	else
		xfrm_state_afinfo[afinfo->family] = afinfo;
	write_unlock_bh(&xfrm_state_afinfo_lock);
		rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
	spin_unlock_bh(&xfrm_state_afinfo_lock);
	return err;
}
EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1862,14 +1861,15 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
		return -EINVAL;
	if (unlikely(afinfo->family >= NPROTO))
		return -EAFNOSUPPORT;
	write_lock_bh(&xfrm_state_afinfo_lock);
	spin_lock_bh(&xfrm_state_afinfo_lock);
	if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
		if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
			err = -EINVAL;
		else
			xfrm_state_afinfo[afinfo->family] = NULL;
			RCU_INIT_POINTER(xfrm_state_afinfo[afinfo->family], NULL);
	}
	write_unlock_bh(&xfrm_state_afinfo_lock);
	spin_unlock_bh(&xfrm_state_afinfo_lock);
	synchronize_rcu();
	return err;
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
@@ -1879,17 +1879,16 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
	struct xfrm_state_afinfo *afinfo;
	if (unlikely(family >= NPROTO))
		return NULL;
	read_lock(&xfrm_state_afinfo_lock);
	afinfo = xfrm_state_afinfo[family];
	rcu_read_lock();
	afinfo = rcu_dereference(xfrm_state_afinfo[family]);
	if (unlikely(!afinfo))
		read_unlock(&xfrm_state_afinfo_lock);
		rcu_read_unlock();
	return afinfo;
}

static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
	__releases(xfrm_state_afinfo_lock)
{
	read_unlock(&xfrm_state_afinfo_lock);
	rcu_read_unlock();
}

/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */