static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
			    struct inet6_dev *idev)
{
	struct ip6_sf_socklist *psl;
	int err;

	psl = sock_dereference(iml->sflist, sk);

	if (idev)
		mutex_lock(&idev->mc_lock);

	if (!psl) {
		/* any-source empty exclude case */
		err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0);
	} else {
		err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode,
				     psl->sl_count, psl->sl_addr, 0);
		RCU_INIT_POINTER(iml->sflist, NULL);
		atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
			   &sk->sk_omem_alloc);
		kfree_rcu(psl, rcu);
	}

	if (idev)
		mutex_unlock(&idev->mc_lock);

	return err;
}
static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
			    struct inet6_dev *idev)
{
	struct ip6_sf_socklist *psl;
	int err;

	psl = sock_dereference(iml->sflist, sk);

	if (idev)
		mutex_lock(&idev->mc_lock);

	if (!psl) {
		 
		err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0);
	} else {
		err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode,
				     psl->sl_count, psl->sl_addr, 0);
		RCU_INIT_POINTER(iml->sflist, NULL);
		atomic_sub(struct_size(psl, sl_addr, psl->sl_max),
			   &sk->sk_omem_alloc);
		kfree_rcu(psl, rcu);
	}

	if (idev)
		mutex_unlock(&idev->mc_lock);

	return err;
}