diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 28029a342892c9ec9a30b1be5b9f8f15785d7d08..b570f39faa3a61b2046c4d5c21e57e465e9c9c5f 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1267,10 +1267,11 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, */ static inline int fcoe_start_io(struct sk_buff *skb) { + struct sk_buff *nskb; int rc; - skb_get(skb); - rc = dev_queue_xmit(skb); + nskb = skb_clone(skb, GFP_ATOMIC); + rc = dev_queue_xmit(nskb); if (rc != 0) return rc; kfree_skb(skb); diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index db252e2722d04247b8e0b570543e76a932e172be..c4b58d042f6f81b6a49b20b83eeb18b8fdd0ad80 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -530,11 +530,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, struct scatterlist *sg; struct fc_frame *fp = NULL; struct fc_lport *lport = fsp->lp; + struct page *page; size_t remaining; size_t t_blen; size_t tlen; size_t sg_bytes; size_t frame_offset, fh_parm_offset; + size_t off; int error; void *data = NULL; void *page_addr; @@ -605,28 +607,26 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, fh_parm_offset = frame_offset; fr_max_payload(fp) = fsp->max_payload; } + + off = offset + sg->offset; sg_bytes = min(tlen, sg->length - offset); + sg_bytes = min(sg_bytes, + (size_t) (PAGE_SIZE - (off & ~PAGE_MASK))); + page = sg_page(sg) + (off >> PAGE_SHIFT); if (using_sg) { - get_page(sg_page(sg)); + get_page(page); skb_fill_page_desc(fp_skb(fp), skb_shinfo(fp_skb(fp))->nr_frags, - sg_page(sg), sg->offset + offset, - sg_bytes); + page, off & ~PAGE_MASK, sg_bytes); fp_skb(fp)->data_len += sg_bytes; fr_len(fp) += sg_bytes; fp_skb(fp)->truesize += PAGE_SIZE; } else { - size_t off = offset + sg->offset; - /* * The scatterlist item may be bigger than PAGE_SIZE, * but we must not cross pages inside the kmap. */ - sg_bytes = min(sg_bytes, (size_t) (PAGE_SIZE - - (off & ~PAGE_MASK))); - page_addr = kmap_atomic(sg_page(sg) + - (off >> PAGE_SHIFT), - KM_SOFTIRQ0); + page_addr = kmap_atomic(page, KM_SOFTIRQ0); memcpy(data, (char *)page_addr + (off & ~PAGE_MASK), sg_bytes); kunmap_atomic(page_addr, KM_SOFTIRQ0); diff --git a/drivers/scsi/libfc/fc_frame.c b/drivers/scsi/libfc/fc_frame.c index 79c956501bd9f1bed0cdb83383cd940135b42256..6da01c6169641ee882df5f56359b474485abef30 100644 --- a/drivers/scsi/libfc/fc_frame.c +++ b/drivers/scsi/libfc/fc_frame.c @@ -58,12 +58,13 @@ struct fc_frame *_fc_frame_alloc(size_t len) WARN_ON((len % sizeof(u32)) != 0); len += sizeof(struct fc_frame_header); - skb = dev_alloc_skb(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM); + skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM + + NET_SKB_PAD, GFP_ATOMIC); if (!skb) return NULL; + skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM); fp = (struct fc_frame *) skb; fc_frame_init(fp); - skb_reserve(skb, FC_FRAME_HEADROOM); skb_put(skb, len); return fp; }