From: Andrew Morton <akpm@zip.com.au>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: lkml <linux-kernel@vger.kernel.org>, Jens Axboe <axboe@suse.de>
Subject: [patch 4/18] fix loop driver for large BIOs
Date: Sun, 26 May 2002 13:39:36 -0700 [thread overview]
Message-ID: <3CF14808.B2CFA91A@zip.com.au> (raw)
Fix bug in the loop driver.
When presented with a multipage BIO, loop is overindexing the first
page in the BIO rather than advancing to the second page. It scribbles
on the backing file and/or on kernel memory.
This happens with multipage BIO-based pagecache I/O and presumably with
O_DIRECT also.
The fix is much-needed with the multipage-BIO patches - using that code
on loop-backed filesystems has rather messy results.
=====================================
--- 2.5.18/drivers/block/loop.c~loop-large-bio Sat May 25 23:26:45 2002
+++ 2.5.18-akpm/drivers/block/loop.c Sat May 25 23:26:45 2002
@@ -168,7 +168,8 @@ static void figure_loop_size(struct loop
}
-static int lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+static int
+do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
{
struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
@@ -178,12 +179,13 @@ static int lo_send(struct loop_device *l
unsigned long index;
unsigned size, offset;
int len;
+ int ret = 0;
down(&mapping->host->i_sem);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & (PAGE_CACHE_SIZE - 1);
- len = bio->bi_size;
- data = bio_data(bio);
+ data = kmap(bvec->bv_page) + bvec->bv_offset;
+ len = bvec->bv_len;
while (len > 0) {
int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize;
int transfer_result;
@@ -221,14 +223,34 @@ static int lo_send(struct loop_device *l
page_cache_release(page);
}
up(&mapping->host->i_sem);
- return 0;
+out:
+ kunmap(bvec->bv_page);
+ return ret;
unlock:
unlock_page(page);
page_cache_release(page);
fail:
up(&mapping->host->i_sem);
- return -1;
+ ret = -1;
+ goto out;
+}
+
+static int
+lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+{
+ unsigned vecnr;
+ int ret = 0;
+
+ for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) {
+ struct bio_vec *bvec = &bio->bi_io_vec[vecnr];
+
+ ret = do_lo_send(lo, bvec, bsize, pos);
+ if (ret < 0)
+ break;
+ pos += bvec->bv_len;
+ }
+ return ret;
}
struct lo_read_data {
@@ -262,26 +284,46 @@ static int lo_read_actor(read_descriptor
return size;
}
-static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+static int
+do_lo_receive(struct loop_device *lo,
+ struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
read_descriptor_t desc;
struct file *file;
cookie.lo = lo;
- cookie.data = bio_data(bio);
+ cookie.data = kmap(bvec->bv_page) + bvec->bv_offset;
cookie.bsize = bsize;
desc.written = 0;
- desc.count = bio->bi_size;
+ desc.count = bvec->bv_len;
desc.buf = (char*)&cookie;
desc.error = 0;
spin_lock_irq(&lo->lo_lock);
file = lo->lo_backing_file;
spin_unlock_irq(&lo->lo_lock);
do_generic_file_read(file, &pos, &desc, lo_read_actor);
+ kunmap(bvec->bv_page);
return desc.error;
}
+static int
+lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+{
+ unsigned vecnr;
+ int ret = 0;
+
+ for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) {
+ struct bio_vec *bvec = &bio->bi_io_vec[vecnr];
+
+ ret = do_lo_receive(lo, bvec, bsize, pos);
+ if (ret < 0)
+ break;
+ pos += bvec->bv_len;
+ }
+ return ret;
+}
+
static inline int loop_get_bs(struct loop_device *lo)
{
return block_size(lo->lo_device);
-
reply other threads:[~2002-05-26 20:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=3CF14808.B2CFA91A@zip.com.au \
--to=akpm@zip.com.au \
--cc=axboe@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.