block: add dma alignment and padding support to blk_rq_map_kern
Subsystems (3)
PATCH 1/1 block: add dma alignment and padding support to blk_rq_map_kern
blk_rq_map_kern ignores dma alignment and padding. Is it problematic to libata?
This is against Jens' for-2.6.26 branch.
==
From: FUJITA Tomonori <[email protected]>
Subject: [PATCH] block: add dma alignment and padding support to blk_rq_map_kern
This patch adds bio_copy_kern similar to bio_copy_user. blk_rq_map_kern uses bio_copy_kern instead of bio_map_kern if necessary.
bio_copy_kern uses temporary pages and the bi_end_io callback frees these pages. bio_copy_kern saves the original kernel buffer at bio->bi_private it doesn't use something like struct bio_map_data to store the information about the caller.
--- block/blk-map.c | 21 +++++++++++- fs/bio.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/bio.h | 2 + 3 files changed, 112 insertions(+), 1 deletions(-)
block/blk-map.c +20 -1
@@ -255,10 +255,18 @@ EXPORT_SYMBOL(blk_rq_unmap_user);* @kbuf: the kernel buffer * @len: length of user data * @gfp_mask: memory allocation flags +* +* Description: +* Data will be mapped directly if possible. Otherwise a bounce +* buffer is used. */ int blk_rq_map_kern (struct request_queue *q,struct request *rq,void *kbuf,unsigned int len,gfp_t gfp_mask) { +unsigned long kaddr; +unsigned int alignment; +int reading =rq_data_dir (rq) ==READ ; +int do_copy =0 ;struct bio *bio;if (len > (q->max_hw_sectors <<9 ))
@@ -266,13 +274,24 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,if (!len || !kbuf)return -EINVAL ; - bio =bio_map_kern (q, kbuf, len, gfp_mask); + kaddr = (unsigned long )kbuf; + alignment =queue_dma_alignment (q) | q->dma_pad_mask; + do_copy = ((kaddr & alignment) || (len & alignment)); + +if (do_copy) + bio =bio_copy_kern (q, kbuf, len, gfp_mask, reading); +else + bio =bio_map_kern (q, kbuf, len, gfp_mask); +if (IS_ERR (bio))return PTR_ERR (bio);if (rq_data_dir (rq) ==WRITE ) bio->bi_rw |= (1 <<BIO_RW ); +if (do_copy) + rq->cmd_flags |=REQ_COPY_USER ; +blk_rq_bio_prep (q, rq, bio);blk_queue_bounce (q, &rq->bio); rq->buffer = rq->data =NULL ;
fs/bio.c +90 -0
102 lines not on this page · raw message
include/linux/bio.h +2 -0
@@ -324,6 +324,8 @@ extern struct bio *bio_map_user_iov(struct request_queue *,extern void bio_unmap_user (struct bio *);extern struct bio *bio_map_kern (struct request_queue *,void *,unsigned int ,gfp_t ); +extern struct bio *bio_copy_kern (struct request_queue *,void *,unsigned int , +gfp_t ,int );extern void bio_set_pages_dirty (struct bio *bio);extern void bio_check_pages_dirty (struct bio *bio);extern struct bio *bio_copy_user (struct request_queue *,unsigned long ,unsigned int ,int );
Signature · 1 line
1.5.3.4
Quoted 2 lines · FUJITA Tomonori
blk_rq_map_kernignores dma alignment and padding. Is it problematic to libata?
Till now we've been depending for the issuer to get this right but it's definitely worth fixing. Thanks.
Signature · 1 line
tejun
Quoted 6 lines · On Wed, 23 Apr 2008 15:32:25 +0900 Tejun Heo <[email protected]> wrote:
Quoted 2 lines · FUJITA Tomonori
blk_rq_map_kernignores dma alignment and padding. Is it problematic to libata?Till now we've been depending for the issuer to get this right but it's definitely worth fixing. Thanks.
Surely, some callers don't give 512-byte aligned buffer, which libata wants.