]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/skbuff.c
[PATCH] cifs: character mapping of special characters (part 3 of 3)
[linux-2.6-omap-h63xx.git] / net / core / skbuff.c
index bf02ca9f80ac15bfaddf9ef0624e94c5623802e0..f65b3de590a96ff2ecc7df6b7a4b9020a641e549 100644 (file)
@@ -86,8 +86,10 @@ static kmem_cache_t *skbuff_head_cache;
  */
 void skb_over_panic(struct sk_buff *skb, int sz, void *here)
 {
-       printk(KERN_INFO "skput:over: %p:%d put:%d dev:%s",
-               here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+       printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p "
+                         "data:%p tail:%p end:%p dev:%s\n",
+              here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+              skb->dev ? skb->dev->name : "<NULL>");
        BUG();
 }
 
@@ -102,8 +104,10 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here)
 
 void skb_under_panic(struct sk_buff *skb, int sz, void *here)
 {
-       printk(KERN_INFO "skput:under: %p:%d put:%d dev:%s",
-               here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+       printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p "
+                         "data:%p tail:%p end:%p dev:%s\n",
+              here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+              skb->dev ? skb->dev->name : "<NULL>");
        BUG();
 }
 
@@ -276,20 +280,14 @@ void kfree_skbmem(struct sk_buff *skb)
 
 void __kfree_skb(struct sk_buff *skb)
 {
-       if (skb->list) {
-               printk(KERN_WARNING "Warning: kfree_skb passed an skb still "
-                      "on a list (from %p).\n", NET_CALLER(skb));
-               BUG();
-       }
+       BUG_ON(skb->list != NULL);
 
        dst_release(skb->dst);
 #ifdef CONFIG_XFRM
        secpath_put(skb->sp);
 #endif
-       if(skb->destructor) {
-               if (in_irq())
-                       printk(KERN_WARNING "Warning: kfree_skb on "
-                                           "hard IRQ %p\n", NET_CALLER(skb));
+       if (skb->destructor) {
+               WARN_ON(in_irq());
                skb->destructor(skb);
        }
 #ifdef CONFIG_NETFILTER
@@ -985,6 +983,94 @@ fault:
        return -EFAULT;
 }
 
+/**
+ *     skb_store_bits - store bits from kernel buffer to skb
+ *     @skb: destination buffer
+ *     @offset: offset in destination
+ *     @from: source buffer
+ *     @len: number of bytes to copy
+ *
+ *     Copy the specified number of bytes from the source buffer to the
+ *     destination skb.  This function handles all the messy bits of
+ *     traversing fragment lists and such.
+ */
+
+int skb_store_bits(const struct sk_buff *skb, int offset, void *from, int len)
+{
+       int i, copy;
+       int start = skb_headlen(skb);
+
+       if (offset > (int)skb->len - len)
+               goto fault;
+
+       if ((copy = start - offset) > 0) {
+               if (copy > len)
+                       copy = len;
+               memcpy(skb->data + offset, from, copy);
+               if ((len -= copy) == 0)
+                       return 0;
+               offset += copy;
+               from += copy;
+       }
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               int end;
+
+               BUG_TRAP(start <= offset + len);
+
+               end = start + frag->size;
+               if ((copy = end - offset) > 0) {
+                       u8 *vaddr;
+
+                       if (copy > len)
+                               copy = len;
+
+                       vaddr = kmap_skb_frag(frag);
+                       memcpy(vaddr + frag->page_offset + offset - start,
+                              from, copy);
+                       kunmap_skb_frag(vaddr);
+
+                       if ((len -= copy) == 0)
+                               return 0;
+                       offset += copy;
+                       from += copy;
+               }
+               start = end;
+       }
+
+       if (skb_shinfo(skb)->frag_list) {
+               struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+               for (; list; list = list->next) {
+                       int end;
+
+                       BUG_TRAP(start <= offset + len);
+
+                       end = start + list->len;
+                       if ((copy = end - offset) > 0) {
+                               if (copy > len)
+                                       copy = len;
+                               if (skb_store_bits(list, offset - start,
+                                                  from, copy))
+                                       goto fault;
+                               if ((len -= copy) == 0)
+                                       return 0;
+                               offset += copy;
+                               from += copy;
+                       }
+                       start = end;
+               }
+       }
+       if (!len)
+               return 0;
+
+fault:
+       return -EFAULT;
+}
+
+EXPORT_SYMBOL(skb_store_bits);
+
 /* Checksum skb data. */
 
 unsigned int skb_checksum(const struct sk_buff *skb, int offset,