From: Tejun Heo <tj@kernel.org>
To: axboe@kernel.dk, bharrosh@panasas.com,
linux-kernel@vger.kernel.org, fujita.tomonori@lab.ntt.co.jp
Cc: Tejun Heo <tj@kernel.org>
Subject: [PATCH 10/17] bio: use bio_create_from_sgl() in bio_map_user_iov()
Date: Wed, 1 Apr 2009 22:44:25 +0900 [thread overview]
Message-ID: <1238593472-30360-11-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1238593472-30360-1-git-send-email-tj@kernel.org>
Impact: cleanup
As bio_map_user_iov() is unique in the way it acquires pages to map
from all other three operations (user-copy, kern-map, kern-copy), the
function still needs to get the pages itself but the bio creation can
use bio_create_from_sgl(). Create sgl of mapped pages and use it to
create bio from it. The code will be further simplified with future
changes to bio_create_from_sgl().
Signed-off-by: Tejun Heo <tj@kernel.org>
---
fs/bio.c | 79 ++++++++++++++++++++++++++------------------------------------
1 files changed, 33 insertions(+), 46 deletions(-)
diff --git a/fs/bio.c b/fs/bio.c
index 4540afc..1ca8b16 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1059,13 +1059,13 @@ struct bio *bio_copy_user(struct request_queue *q, struct rq_map_data *md,
struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev,
struct iovec *iov, int count, int rw, gfp_t gfp)
{
- int i, j;
size_t tot_len = 0;
int nr_pages = 0;
+ int nents = 0;
+ struct scatterlist *sgl;
struct page **pages;
struct bio *bio;
- int cur_page = 0;
- int ret, offset;
+ int i, ret;
for (i = 0; i < count; i++) {
unsigned long uaddr = (unsigned long)iov[i].iov_base;
@@ -1088,70 +1088,57 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev,
if (!nr_pages || tot_len & q->dma_pad_mask)
return ERR_PTR(-EINVAL);
- bio = bio_kmalloc(gfp, nr_pages);
- if (!bio)
+ sgl = kmalloc(nr_pages * sizeof(sgl[0]), gfp);
+ if (!sgl)
return ERR_PTR(-ENOMEM);
+ sg_init_table(sgl, nr_pages);
ret = -ENOMEM;
- pages = kcalloc(nr_pages, sizeof(struct page *), gfp);
+ pages = kcalloc(nr_pages, sizeof(pages[0]), gfp);
if (!pages)
- goto out;
+ goto err_sgl;
for (i = 0; i < count; i++) {
unsigned long uaddr = (unsigned long)iov[i].iov_base;
unsigned long len = iov[i].iov_len;
- unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- unsigned long start = uaddr >> PAGE_SHIFT;
- const int local_nr_pages = end - start;
- const int page_limit = cur_page + local_nr_pages;
-
+ unsigned long offset = offset_in_page(uaddr);
+ int local_nr_pages = PFN_UP(uaddr + len) - PFN_DOWN(uaddr);
+
ret = get_user_pages_fast(uaddr, local_nr_pages, rw == READ,
- &pages[cur_page]);
+ &pages[nents]);
if (ret < local_nr_pages) {
ret = -EFAULT;
- goto out_unmap;
+ goto err_pages;
}
- offset = uaddr & ~PAGE_MASK;
- for (j = cur_page; j < page_limit; j++) {
- unsigned int bytes = PAGE_SIZE - offset;
+ while (len) {
+ unsigned int bytes = min(PAGE_SIZE - offset, len);
- if (len <= 0)
- break;
-
- if (bytes > len)
- bytes = len;
-
- /*
- * sorry...
- */
- if (bio_add_pc_page(q, bio, pages[j], bytes, offset) <
- bytes)
- break;
+ sg_set_page(&sgl[nents], pages[nents], bytes, offset);
+ nents++;
len -= bytes;
offset = 0;
}
-
- cur_page = j;
- /*
- * release the pages we didn't map into the bio, if any
- */
- while (j < page_limit)
- page_cache_release(pages[j++]);
}
+ BUG_ON(nents != nr_pages);
- kfree(pages);
+ bio = bio_create_from_sgl(q, sgl, nents, nr_pages, rw, gfp);
+ if (IS_ERR(bio)) {
+ ret = PTR_ERR(bio);
+ goto err_pages;
+ }
- /*
- * set data direction, and check if mapped pages need bouncing
- */
- if (rw == WRITE)
- bio->bi_rw |= (1 << BIO_RW);
+ /* release the pages we didn't map into the bio, if any */
+ for (i = bio->bi_vcnt; i < nr_pages; i++)
+ page_cache_release(pages[i]);
bio->bi_bdev = bdev;
bio->bi_flags |= (1 << BIO_USER_MAPPED);
+ kfree(sgl);
+ kfree(pages);
+
/*
* subtle -- if __bio_map_user() ended up bouncing a bio,
* it would normally disappear when its bi_end_io is run.
@@ -1162,15 +1149,15 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev,
return bio;
- out_unmap:
+err_pages:
for (i = 0; i < nr_pages; i++) {
- if(!pages[i])
+ if (!pages[i])
break;
page_cache_release(pages[i]);
}
- out:
kfree(pages);
- bio_put(bio);
+err_sgl:
+ kfree(sgl);
return ERR_PTR(ret);
}
--
1.6.0.2
next prev parent reply other threads:[~2009-04-01 13:52 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-01 13:44 [RFC PATCHSET block] block: blk-map updates and API cleanup Tejun Heo
2009-04-01 13:44 ` [PATCH 01/17] blk-map: move blk_rq_map_user() below blk_rq_map_user_iov() Tejun Heo
2009-04-01 13:44 ` [PATCH 02/17] scatterlist: improve atomic mapping handling in mapping iterator Tejun Heo
2009-04-01 13:44 ` [PATCH 03/17] blk-map: improve alignment checking for blk_rq_map_user_iov() Tejun Heo
2009-04-01 13:44 ` [PATCH 04/17] bio: bio.h cleanup Tejun Heo
2009-04-01 13:44 ` [PATCH 05/17] bio: cleanup rw usage Tejun Heo
2009-04-02 8:36 ` Boaz Harrosh
2009-04-02 9:02 ` Tejun Heo
2009-04-02 9:07 ` Boaz Harrosh
2009-04-02 9:13 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 06/17] blk-map/bio: use struct iovec instead of sg_iovec Tejun Heo
2009-04-01 14:50 ` Boaz Harrosh
2009-04-01 15:32 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 07/17] blk-map/bio: rename stuff Tejun Heo
2009-04-01 13:44 ` [PATCH 08/17] bio: reimplement bio_copy_user_iov() Tejun Heo
2009-04-01 15:50 ` Boaz Harrosh
2009-04-01 23:57 ` Tejun Heo
2009-04-02 8:24 ` Boaz Harrosh
2009-04-02 8:59 ` Tejun Heo
2009-04-02 9:54 ` Boaz Harrosh
2009-04-02 1:38 ` Tejun Heo
2009-04-02 7:34 ` Boaz Harrosh
2009-04-02 7:51 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 09/17] bio: collapse __bio_map_user_iov(), __bio_unmap_user() and __bio_map_kern() Tejun Heo
2009-04-01 13:44 ` Tejun Heo [this message]
2009-04-01 16:33 ` [PATCH 10/17] bio: use bio_create_from_sgl() in bio_map_user_iov() Boaz Harrosh
2009-04-01 22:20 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 11/17] bio: add sgl source support to bci and implement bio_memcpy_sgl_sgl() Tejun Heo
2009-04-01 13:44 ` [PATCH 12/17] bio: implement bio_{map|copy}_kern_sgl() Tejun Heo
2009-04-01 13:44 ` [PATCH 13/17] blk-map: implement blk_rq_map_kern_sgl() Tejun Heo
2009-04-01 16:50 ` Boaz Harrosh
2009-04-01 22:25 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 14/17] scsi: replace custom rq mapping with blk_rq_map_kern_sgl() Tejun Heo
2009-04-01 17:00 ` Boaz Harrosh
2009-04-01 17:05 ` James Bottomley
2009-04-01 17:17 ` Boaz Harrosh
2009-04-13 7:42 ` FUJITA Tomonori
2009-04-13 9:38 ` Tejun Heo
2009-04-13 10:07 ` FUJITA Tomonori
2009-04-13 12:59 ` Borislav Petkov
2009-04-14 0:44 ` FUJITA Tomonori
2009-04-14 10:01 ` Borislav Petkov
2009-04-14 23:44 ` FUJITA Tomonori
2009-04-15 4:25 ` Tejun Heo
2009-04-15 7:26 ` Borislav Petkov
2009-04-15 7:48 ` FUJITA Tomonori
2009-04-15 8:13 ` Borislav Petkov
2009-04-16 3:06 ` Tejun Heo
2009-04-16 3:06 ` Tejun Heo
2009-04-16 5:44 ` Borislav Petkov
2009-04-16 6:07 ` Tejun Heo
2009-04-16 6:07 ` Tejun Heo
2009-04-16 6:29 ` Borislav Petkov
2009-04-16 6:30 ` Tejun Heo
2009-04-16 6:30 ` Tejun Heo
2009-04-16 5:53 ` [PATCH 1/3] ide: add helpers for preparing sense requests Borislav Petkov
2009-04-16 5:53 ` [PATCH 2/3] ide-cd: convert to using generic sense request Borislav Petkov
2009-04-16 5:54 ` [PATCH 3/3] ide-atapi: convert ide-{floppy,tape} to using preallocated sense buffer Borislav Petkov
2009-04-01 13:44 ` [PATCH 15/17] bio/blk-map: kill unused stuff and un-export internal functions Tejun Heo
2009-04-01 13:54 ` Boaz Harrosh
2009-04-01 14:06 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 16/17] blk-map/bio: remove superflous @len parameter from blk_rq_map_user_iov() Tejun Heo
2009-04-01 17:12 ` Boaz Harrosh
2009-04-01 22:17 ` Tejun Heo
2009-04-01 13:44 ` [PATCH 17/17] blk-map/bio: remove superflous @q from blk_rq_map_{user|kern}*() Tejun Heo
2009-04-01 17:05 ` Boaz Harrosh
2009-04-01 14:08 ` [RFC PATCHSET block] block: blk-map updates and API cleanup Tejun Heo
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=1238593472-30360-11-git-send-email-tj@kernel.org \
--to=tj@kernel.org \
--cc=axboe@kernel.dk \
--cc=bharrosh@panasas.com \
--cc=fujita.tomonori@lab.ntt.co.jp \
--cc=linux-kernel@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 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.