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 Original line Diff line number Diff line
@@ -158,8 +158,8 @@ out_unlock:
	mutex_unlock(&hash_resize_mutex);
	mutex_unlock(&hash_resize_mutex);
}
}


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


static DEFINE_SPINLOCK(xfrm_state_gc_lock);
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;
	struct xfrm_state_afinfo *afinfo;
	if (unlikely(family >= NPROTO))
	if (unlikely(family >= NPROTO))
		return NULL;
		return NULL;
	write_lock_bh(&xfrm_state_afinfo_lock);
	spin_lock_bh(&xfrm_state_afinfo_lock);
	afinfo = xfrm_state_afinfo[family];
	afinfo = xfrm_state_afinfo[family];
	if (unlikely(!afinfo))
	if (unlikely(!afinfo))
		write_unlock_bh(&xfrm_state_afinfo_lock);
		spin_unlock_bh(&xfrm_state_afinfo_lock);
	return afinfo;
	return afinfo;
}
}


static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *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)
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;
		return -EINVAL;
	if (unlikely(afinfo->family >= NPROTO))
	if (unlikely(afinfo->family >= NPROTO))
		return -EAFNOSUPPORT;
		return -EAFNOSUPPORT;
	write_lock_bh(&xfrm_state_afinfo_lock);
	spin_lock_bh(&xfrm_state_afinfo_lock);
	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
		err = -ENOBUFS;
		err = -ENOBUFS;
	else
	else
		xfrm_state_afinfo[afinfo->family] = afinfo;
		rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
	write_unlock_bh(&xfrm_state_afinfo_lock);
	spin_unlock_bh(&xfrm_state_afinfo_lock);
	return err;
	return err;
}
}
EXPORT_SYMBOL(xfrm_state_register_afinfo);
EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1862,14 +1861,15 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
		return -EINVAL;
		return -EINVAL;
	if (unlikely(afinfo->family >= NPROTO))
	if (unlikely(afinfo->family >= NPROTO))
		return -EAFNOSUPPORT;
		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 (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
		if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
		if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
			err = -EINVAL;
			err = -EINVAL;
		else
		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;
	return err;
}
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
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;
	struct xfrm_state_afinfo *afinfo;
	if (unlikely(family >= NPROTO))
	if (unlikely(family >= NPROTO))
		return NULL;
		return NULL;
	read_lock(&xfrm_state_afinfo_lock);
	rcu_read_lock();
	afinfo = xfrm_state_afinfo[family];
	afinfo = rcu_dereference(xfrm_state_afinfo[family]);
	if (unlikely(!afinfo))
	if (unlikely(!afinfo))
		read_unlock(&xfrm_state_afinfo_lock);
		rcu_read_unlock();
	return afinfo;
	return afinfo;
}
}


static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *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 */
/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */