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

Commit 69df9d59 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

ip_frag: dont touch device refcount



When sending fragmentation expiration ICMP V4/V6 messages,
we can avoid touching device refcount, thanks to RCU

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bd27a875
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -206,10 +206,11 @@ static void ip_expire(unsigned long arg)
		struct sk_buff *head = qp->q.fragments;

		/* Send an ICMP "Fragment Reassembly Timeout" message. */
		if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) {
		rcu_read_lock();
		head->dev = dev_get_by_index_rcu(net, qp->iif);
		if (head->dev)
			icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
			dev_put(head->dev);
		}
		rcu_read_unlock();
	}
out:
	spin_unlock(&qp->q.lock);
+6 −7
Original line number Diff line number Diff line
@@ -208,18 +208,17 @@ static void ip6_frag_expire(unsigned long data)
	fq_kill(fq);

	net = container_of(fq->q.net, struct net, ipv6.frags);
	dev = dev_get_by_index(net, fq->iif);
	rcu_read_lock();
	dev = dev_get_by_index_rcu(net, fq->iif);
	if (!dev)
		goto out;
		goto out_rcu_unlock;

	rcu_read_lock();
	IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
	IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
	rcu_read_unlock();

	/* Don't send error if the first segment did not arrive. */
	if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments)
		goto out;
		goto out_rcu_unlock;

	/*
	   But use as source device on which LAST ARRIVED
@@ -228,9 +227,9 @@ static void ip6_frag_expire(unsigned long data)
	 */
	fq->q.fragments->dev = dev;
	icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev);
out_rcu_unlock:
	rcu_read_unlock();
out:
	if (dev)
		dev_put(dev);
	spin_unlock(&fq->q.lock);
	fq_put(fq);
}