From: Boaz Harrosh <bharrosh@panasas.com>
To: linux-scsi@vger.kernel.org,
James Bottomley <James.Bottomley@SteelEye.com>,
Jens Axboe <jens.axboe@oracle.com>
Cc: Benny Halevy <bhalevy@panasas.com>
Subject: Possible bug in scsi_lib.c:scsi_req_map_sg()
Date: Mon, 27 Nov 2006 19:44:54 +0200 [thread overview]
Message-ID: <456B2416.7000101@panasas.com> (raw)
Playing with some tests which I admit are not 100% orthodox I have stumbled upon a bug that raises a serious question:
In the call to scsi_execute_async() in the use_sg case, must the scatterlist* (pointed to by buffer) map a buffer that's contiguous in virtual memory or is it allowed to map disjoint segments of memory?
In scsi_req_map_sg() nr_pages is calculated like this:
int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
this calculation assumes that only the first page can have a non zero offset so disjoint memory segments pointed by sgl will fail mapping in some case when we do not allocate enough nr_pages for them.
Please consider below patch for a fix for such cases. With this patch my tests pass, including booting from a SATA drive (with a 2.6.18 code base).
Without the patch the kernel fails really badly. What happens is that bio_add_pc_page(..) fails and then inside bio_put() and later bio_free() at the call to mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]), bio->bi_io_vec == NULL and the kernel panics.
bio->bi_io_vec is set to NULL in bio_alloc_bioset() when nr_iovecs == 0. As this seems like a valid use case bio_free() should free bio->bi_io_vec only if bio->bi_io_vec != NULL (see second patch).
Both patches are based off of scsi-misc-2.6.
<First Patch>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
==== //depot/local/scsi-misc-2.6-dev/linux/drivers/scsi/scsi_lib.c#1 - /home/bharrosh/p4.local/local/scsi-misc-2.6-dev/linux/drivers/scsi/scsi_lib.c ====
diff -Npu /tmp/tmp.20230.0 /home/bharrosh/p4.local/local/scsi-misc-2.6-dev/linux/drivers/scsi/scsi_lib.c -L a/drivers/scsi/scsi_lib.c -L b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -299,16 +299,20 @@ static int scsi_bi_endio(struct bio *bio
* sent to use, as some ULDs use that struct to only organize the pages.
*/
static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
- int nsegs, unsigned bufflen, gfp_t gfp)
+ int nsegs, gfp_t gfp)
{
struct request_queue *q = rq->q;
- int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ int nr_pages = 0;
unsigned int data_len = 0, len, bytes, off;
struct page *page;
struct bio *bio = NULL;
int i, err, nr_vecs = 0;
for (i = 0; i < nsegs; i++) {
+ nr_pages += (sgl[i].length + sgl[i].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ }
+
+ for (i = 0; i < nsegs; i++) {
page = sgl[i].page;
off = sgl[i].offset;
len = sgl[i].length;
@@ -402,7 +406,7 @@ int scsi_execute_async(struct scsi_devic
req->cmd_flags |= REQ_QUIET;
if (use_sg)
- err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
+ err = scsi_req_map_sg(req, buffer, use_sg, gfp);
else if (bufflen)
err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp);
</First Patch>
<Second Patch>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
diff --git a/fs/bio.c b/fs/bio.c
index f95c874..199b929 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -113,7 +113,8 @@ void bio_free(struct bio *bio, struct bi
BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
- mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
+ if (likely(bio->bi_io_vec))
+ mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
mempool_free(bio, bio_set->bio_pool);
}
</Second Patch>
next reply other threads:[~2006-11-27 17:45 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-27 17:44 Boaz Harrosh [this message]
2006-11-27 19:13 ` Possible bug in scsi_lib.c:scsi_req_map_sg() Mike Christie
2006-11-27 19:27 ` Mike Christie
2006-11-27 21:52 ` Kai Makisara
2006-11-28 18:57 ` Jens Axboe
2006-11-29 9:30 ` Benny Halevy
2007-03-02 16:45 ` Dachepalli, Sudhir
2007-03-02 21:19 ` Mike Christie
2007-03-02 21:59 ` Mike Christie
2007-03-02 23:45 ` Dachepalli, Sudhir
2007-03-04 0:04 ` Mike Christie
2007-03-04 7:36 ` Dachepalli, Sudhir
2007-03-04 14:31 ` James Bottomley
2007-03-04 15:43 ` Mike Christie
2007-03-04 15:57 ` James Bottomley
2007-03-04 16:21 ` Mike Christie
2007-03-04 16:51 ` James Bottomley
2007-03-04 17:04 ` Mike Christie
2007-03-04 17:07 ` Mike Christie
2007-03-04 18:00 ` Dachepalli, Sudhir
2007-03-04 18:14 ` James Bottomley
2007-03-04 19:06 ` Dachepalli, Sudhir
2007-03-05 13:00 ` Christoph Hellwig
2007-03-05 13:02 ` Christoph Hellwig
2006-11-27 23:33 ` James Bottomley
2006-11-28 15:44 ` Boaz Harrosh
2006-11-28 17:30 ` 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=456B2416.7000101@panasas.com \
--to=bharrosh@panasas.com \
--cc=James.Bottomley@SteelEye.com \
--cc=bhalevy@panasas.com \
--cc=jens.axboe@oracle.com \
--cc=linux-scsi@vger.kernel.org \
/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