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

Commit 1691c63e authored by WANG Cong's avatar WANG Cong Committed by David S. Miller
Browse files

ipv6: refactor ipv6_dev_mc_inc()



Refactor out allocation and initialization and make
the refcount code more readable.

Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f7ed925c
Loading
Loading
Loading
Loading
+49 −33
Original line number Diff line number Diff line
@@ -641,14 +641,6 @@ bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
	return rv;
}

static void ma_put(struct ifmcaddr6 *mc)
{
	if (atomic_dec_and_test(&mc->mca_refcnt)) {
		in6_dev_put(mc->idev);
		kfree(mc);
	}
}

static void igmp6_group_added(struct ifmcaddr6 *mc)
{
	struct net_device *dev = mc->idev->dev;
@@ -814,6 +806,48 @@ static void mld_clear_delrec(struct inet6_dev *idev)
	read_unlock_bh(&idev->lock);
}

static void mca_get(struct ifmcaddr6 *mc)
{
	atomic_inc(&mc->mca_refcnt);
}

static void ma_put(struct ifmcaddr6 *mc)
{
	if (atomic_dec_and_test(&mc->mca_refcnt)) {
		in6_dev_put(mc->idev);
		kfree(mc);
	}
}

static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
				   const struct in6_addr *addr)
{
	struct ifmcaddr6 *mc;

	mc = kzalloc(sizeof(*mc), GFP_ATOMIC);
	if (mc == NULL)
		return NULL;

	setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc);

	mc->mca_addr = *addr;
	mc->idev = idev; /* reference taken by caller */
	mc->mca_users = 1;
	/* mca_stamp should be updated upon changes */
	mc->mca_cstamp = mc->mca_tstamp = jiffies;
	atomic_set(&mc->mca_refcnt, 1);
	spin_lock_init(&mc->mca_lock);

	/* initial mode is (EX, empty) */
	mc->mca_sfmode = MCAST_EXCLUDE;
	mc->mca_sfcount[MCAST_EXCLUDE] = 1;

	if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
	    IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
		mc->mca_flags |= MAF_NOREPORT;

	return mc;
}

/*
 *	device multicast group inc (add if not found)
@@ -849,38 +883,20 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
		}
	}

	/*
	 *	not found: create a new one.
	 */

	mc = kzalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);

	if (mc == NULL) {
	mc = mca_alloc(idev, addr);
	if (!mc) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc);

	mc->mca_addr = *addr;
	mc->idev = idev; /* (reference taken) */
	mc->mca_users = 1;
	/* mca_stamp should be updated upon changes */
	mc->mca_cstamp = mc->mca_tstamp = jiffies;
	atomic_set(&mc->mca_refcnt, 2);
	spin_lock_init(&mc->mca_lock);

	/* initial mode is (EX, empty) */
	mc->mca_sfmode = MCAST_EXCLUDE;
	mc->mca_sfcount[MCAST_EXCLUDE] = 1;

	if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
	    IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
		mc->mca_flags |= MAF_NOREPORT;

	mc->next = idev->mc_list;
	idev->mc_list = mc;

	/* Hold this for the code below before we unlock,
	 * it is already exposed via idev->mc_list.
	 */
	mca_get(mc);
	write_unlock_bh(&idev->lock);

	mld_del_delrec(idev, &mc->mca_addr);