sr: use bdev_check_media_change
[linux-2.6-microblaze.git] / include / linux / virtio_net.h
index 6f6ade6..e8a924e 100644 (file)
@@ -31,6 +31,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 {
        unsigned int gso_type = 0;
        unsigned int thlen = 0;
+       unsigned int p_off = 0;
        unsigned int ip_proto;
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
@@ -68,7 +69,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
                if (!skb_partial_csum_set(skb, start, off))
                        return -EINVAL;
 
-               if (skb_transport_offset(skb) + thlen > skb_headlen(skb))
+               p_off = skb_transport_offset(skb) + thlen;
+               if (p_off > skb_headlen(skb))
                        return -EINVAL;
        } else {
                /* gso packets without NEEDS_CSUM do not set transport_offset.
@@ -92,23 +94,32 @@ retry:
                                return -EINVAL;
                        }
 
-                       if (keys.control.thoff + thlen > skb_headlen(skb) ||
+                       p_off = keys.control.thoff + thlen;
+                       if (p_off > skb_headlen(skb) ||
                            keys.basic.ip_proto != ip_proto)
                                return -EINVAL;
 
                        skb_set_transport_header(skb, keys.control.thoff);
+               } else if (gso_type) {
+                       p_off = thlen;
+                       if (p_off > skb_headlen(skb))
+                               return -EINVAL;
                }
        }
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size);
+               struct skb_shared_info *shinfo = skb_shinfo(skb);
 
-               skb_shinfo(skb)->gso_size = gso_size;
-               skb_shinfo(skb)->gso_type = gso_type;
+               /* Too small packets are not really GSO ones. */
+               if (skb->len - p_off > gso_size) {
+                       shinfo->gso_size = gso_size;
+                       shinfo->gso_type = gso_type;
 
-               /* Header must be checked, and gso_segs computed. */
-               skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
-               skb_shinfo(skb)->gso_segs = 0;
+                       /* Header must be checked, and gso_segs computed. */
+                       shinfo->gso_type |= SKB_GSO_DODGY;
+                       shinfo->gso_segs = 0;
+               }
        }
 
        return 0;