netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mike Christie <michaelc@cs.wisc.edu>
To: "Brandeburg, Jesse" <jesse.brandeburg@intel.com>
Cc: netdev@vger.kernel.org, olaf.kirch@oracle.com, tgraf@suug.ch,
	kkeil@suse.de, herbert@gondor.apana.org.au
Subject: Re: [PANIC] lro + iscsi or lro + skb text search causes panic
Date: Thu, 22 Jan 2009 22:22:42 -0600	[thread overview]
Message-ID: <49794612.9010204@cs.wisc.edu> (raw)
In-Reply-To: <4978F804.3060502@cs.wisc.edu>

[-- Attachment #1: Type: text/plain, Size: 726 bytes --]

Mike Christie wrote:
> Brandeburg, Jesse wrote:
>>
>> skb_copy_bits is an example of the code flow that does work.
>>
>> skb_seq_read appears to only be used by iSCSI and the skb text match 
>> support in tc/netfilter (aka skb_find_text)
>>
> 
> There is no reason iscsi needs to use skb_seq_read. It used to use 
> skb_copy_bits. I can convert iscsi to use skb_copy_bits again.
> 

Attached is a patch made against the scsi maintainer's tree (I think it 
should also apply to linus's) that converts iscsi to use skb_copy_bits. 
It is lightly tested. If there is no benefit in having skb_find_text use 
skb_seq_read maybe we can just kill it, so people do not have to 
maintain two helpers that provide similar functionality.

[-- Attachment #2: use-skb-copy-bits.patch --]
[-- Type: text/plain, Size: 4905 bytes --]

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 23808df..b052c57 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -74,7 +74,7 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
 			     unsigned int offset, size_t len)
 {
 	struct iscsi_conn *conn = rd_desc->arg.data;
-	unsigned int consumed, total_consumed = 0;
+	unsigned int consumed, total_consumed = 0, in = skb->len - offset;
 	int status;
 
 	debug_tcp("in %d bytes\n", skb->len - offset);
@@ -84,7 +84,8 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
 		consumed = iscsi_tcp_recv_skb(conn, skb, offset, 0, &status);
 		offset += consumed;
 		total_consumed += consumed;
-	} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE);
+	} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE &&
+		 consumed < in);
 
 	debug_tcp("read %d bytes status %d\n", skb->len - offset, status);
 	return total_consumed;
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index e7705d3..f91c79d 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -252,45 +252,6 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
 }
 EXPORT_SYMBOL_GPL(iscsi_tcp_segment_done);
 
-/**
- * iscsi_tcp_segment_recv - copy data to segment
- * @tcp_conn: the iSCSI TCP connection
- * @segment: the buffer to copy to
- * @ptr: data pointer
- * @len: amount of data available
- *
- * This function copies up to @len bytes to the
- * given buffer, and returns the number of bytes
- * consumed, which can actually be less than @len.
- *
- * If hash digest is enabled, the function will update the
- * hash while copying.
- * Combining these two operations doesn't buy us a lot (yet),
- * but in the future we could implement combined copy+crc,
- * just way we do for network layer checksums.
- */
-static int
-iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
-		       struct iscsi_segment *segment, const void *ptr,
-		       unsigned int len)
-{
-	unsigned int copy = 0, copied = 0;
-
-	while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
-		if (copied == len) {
-			debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
-				  len);
-			break;
-		}
-
-		copy = min(len - copied, segment->size - segment->copied);
-		debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
-		memcpy(segment->data + segment->copied, ptr + copied, copy);
-		copied += copy;
-	}
-	return copied;
-}
-
 inline void
 iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, size_t hdrlen,
 		      unsigned char digest[ISCSI_DIGEST_SIZE])
@@ -850,8 +811,7 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
 {
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct iscsi_segment *segment = &tcp_conn->in.segment;
-	struct skb_seq_state seq;
-	unsigned int consumed = 0;
+	unsigned int copy = 0, copied = 0, len = skb->len - offset;
 	int rc = 0;
 
 	debug_tcp("in %d bytes\n", skb->len - offset);
@@ -867,30 +827,31 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
 		goto segment_done;
 	}
 
-	skb_prepare_seq_read(skb, offset, skb->len, &seq);
-	while (1) {
-		unsigned int avail;
-		const u8 *ptr;
-
-		avail = skb_seq_read(consumed, &ptr, &seq);
-		if (avail == 0) {
-			debug_tcp("no more data avail. Consumed %d\n",
-				  consumed);
+	while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
+		if (copied == len) {
+			debug_tcp("iscsi_tcp_recv_skb finished skb "
+				  "copied %d bytes\n", len);
 			*status = ISCSI_TCP_SKB_DONE;
-			skb_abort_seq_read(&seq);
 			goto skb_done;
 		}
-		BUG_ON(segment->copied >= segment->size);
 
-		debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
-		rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
-		BUG_ON(rc == 0);
-		consumed += rc;
+		copy = min(len - copied, segment->size - segment->copied);
+		debug_tcp("iscsi_tcp_recv_skb copying %d (len %u copied %u "
+			  "segment size %u segment copied %u\n", copy,
+			  copied, segment->size, segment->copied);
 
-		if (segment->total_copied >= segment->total_size) {
-			skb_abort_seq_read(&seq);
-			goto segment_done;
+		rc = skb_copy_bits(skb, copied + offset,
+				   segment->data + segment->copied, copy);
+		if (rc) {
+			printk(KERN_ERR "iscsi_tcp_recv_skb bug. Could not "
+			       "copy skb data to command buffer. (len %u "
+			       "copied %u segment size %u segment copied %u)\n",
+				copy, copied, segment->size, segment->copied);
+			*status = ISCSI_TCP_CONN_ERR;
+			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+			return 0;
 		}
+		copied += copy;
 	}
 
 segment_done:
@@ -906,8 +867,8 @@ segment_done:
 	/* The done() functions sets up the next segment. */
 
 skb_done:
-	conn->rxdata_octets += consumed;
-	return consumed;
+	conn->rxdata_octets += copied;
+	return copied;
 }
 EXPORT_SYMBOL_GPL(iscsi_tcp_recv_skb);
 

  reply	other threads:[~2009-01-23  4:24 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-22 20:55 [PANIC] lro + iscsi or lro + skb text search causes panic Brandeburg, Jesse
2009-01-22 22:49 ` Mike Christie
2009-01-23  4:22   ` Mike Christie [this message]
2009-01-23  4:29     ` Mike Christie
2009-01-26  5:34     ` David Miller
2009-01-22 23:21 ` Herbert Xu
2009-01-22 23:45   ` Brandeburg, Jesse
2009-01-23  0:04   ` Mike Christie
2009-01-26  5:32     ` David Miller
2009-01-26 22:30       ` Herbert Xu
2009-01-27  1:40         ` Brandeburg, Jesse
2009-01-27  3:01           ` Herbert Xu
2009-01-27  5:52         ` David Miller
2009-01-27  6:12         ` Mike Christie
     [not found]           ` <46A00B48CC54E4468EF6911F877AC4CA01EF2BC9@blrx3m10.blr.amer.dell.com>
2009-01-28 21:25             ` Herbert Xu
2009-01-30  0:13               ` David Miller
2009-01-26 20:54     ` Mike Christie
  -- strict thread matches above, loose matches on Subject: below --
2009-01-28 12:36 Shyam_Iyer
2009-01-28 18:22 ` Mike Christie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49794612.9010204@cs.wisc.edu \
    --to=michaelc@cs.wisc.edu \
    --cc=herbert@gondor.apana.org.au \
    --cc=jesse.brandeburg@intel.com \
    --cc=kkeil@suse.de \
    --cc=netdev@vger.kernel.org \
    --cc=olaf.kirch@oracle.com \
    --cc=tgraf@suug.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).