From: David W. <dw...@in...> - 2013-09-04 20:41:38
|
On Wed, 2013-09-04 at 14:30 -0400, David Miller wrote: > skb_realloc_headroom() should do everything you need. Great, thanks! Something like this then... ? Do I really need the truesize check? And if so, is there a better way to handle the ATM accounting? It just *happens* to be the case that the the br2684_pop() and pppoatm_pop() functions don't mind being bypassed in this fashion, and we should probably get away with tweaking the core ATM accounting directly like this. Doesn't make me happy though... diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 32784d1..4492c0f 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1145,19 +1145,19 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) return 0; } - if (!skb_clone_writable(skb, sizeof(*header))) { - int expand_by = 0; - int ret; - - if (skb_headroom(skb) < sizeof(*header)) - expand_by = sizeof(*header) - skb_headroom(skb); - - ret = pskb_expand_head(skb, expand_by, 0, GFP_ATOMIC); - if (ret) { - dev_warn(&card->dev->dev, "pskb_expand_head failed.\n"); - solos_pop(vcc, skb); - return ret; - } + if (skb_headroom(skb) < sizeof(*header)) { + struct sk_buff *nskb; + + nskb = skb_realloc_headroom(skb, sizeof(*header)); + if (!nskb) { + solos_pop(vcc, skb); + return -ENOMEM; + } + if (skb->truesize != nskb->truesize) + atm_force_charge(vcc, nskb->truesize - skb->truesize); + + dev_kfree_skb_any(skb); + skb = nskb; } header = (void *)skb_push(skb, sizeof(*header)); -- dwmw2 |