Skip to content

Commit

Permalink
Revert "net: remove zap_completion_queue"
Browse files Browse the repository at this point in the history
This reverts commit 15e83ed.

As explained by Johannes Berg, the optimization made here is
invalid.  Or, at best, incomplete.

Not only destructor invocation, but conntract entry releasing
must be executed outside of hw IRQ context.

So just checking "skb->destructor" is insufficient.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 3, 2010
1 parent a427615 commit 3578b0c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
4 changes: 1 addition & 3 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1591,9 +1591,7 @@ EXPORT_SYMBOL(__netif_schedule);

void dev_kfree_skb_irq(struct sk_buff *skb)
{
if (!skb->destructor)
dev_kfree_skb(skb);
else if (atomic_dec_and_test(&skb->users)) {
if (atomic_dec_and_test(&skb->users)) {
struct softnet_data *sd;
unsigned long flags;

Expand Down
31 changes: 31 additions & 0 deletions net/core/netpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static atomic_t trapped;
(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
sizeof(struct iphdr) + sizeof(struct ethhdr))

static void zap_completion_queue(void);
static void arp_reply(struct sk_buff *skb);

static unsigned int carrier_timeout = 4;
Expand Down Expand Up @@ -196,6 +197,7 @@ void netpoll_poll_dev(struct net_device *dev)

service_arp_queue(dev->npinfo);

zap_completion_queue();
}
EXPORT_SYMBOL(netpoll_poll_dev);

Expand All @@ -221,11 +223,40 @@ static void refill_skbs(void)
spin_unlock_irqrestore(&skb_pool.lock, flags);
}

static void zap_completion_queue(void)
{
unsigned long flags;
struct softnet_data *sd = &get_cpu_var(softnet_data);

if (sd->completion_queue) {
struct sk_buff *clist;

local_irq_save(flags);
clist = sd->completion_queue;
sd->completion_queue = NULL;
local_irq_restore(flags);

while (clist != NULL) {
struct sk_buff *skb = clist;
clist = clist->next;
if (skb->destructor) {
atomic_inc(&skb->users);
dev_kfree_skb_any(skb); /* put this one back */
} else {
__kfree_skb(skb);
}
}
}

put_cpu_var(softnet_data);
}

static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
{
int count = 0;
struct sk_buff *skb;

zap_completion_queue();
refill_skbs();
repeat:

Expand Down

0 comments on commit 3578b0c

Please sign in to comment.