From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tejun Heo Subject: [PATCH 2/7] block: update bio according to DMA alignment padding Date: Sat, 9 Feb 2008 10:40:21 +0900 Message-ID: <12025212271469-git-send-email-htejun@gmail.com> References: <12025212262892-git-send-email-htejun@gmail.com> Return-path: Received: from rv-out-0910.google.com ([209.85.198.184]:56720 "EHLO rv-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754228AbYBIBke (ORCPT ); Fri, 8 Feb 2008 20:40:34 -0500 Received: by rv-out-0910.google.com with SMTP id k20so2705686rvb.1 for ; Fri, 08 Feb 2008 17:40:33 -0800 (PST) In-Reply-To: <12025212262892-git-send-email-htejun@gmail.com> Sender: linux-ide-owner@vger.kernel.org List-Id: linux-ide@vger.kernel.org To: jeff@garzik.org, linux-ide@vger.kernel.org, jens.axboe@oracle.com, linux-scsi@vger.kernel.org, fujita.tomonori@lab.ntt.co.jp, akpm@linux-foundation.org Cc: Tejun Heo , James Bottomley DMA start address and transfer size alignment for PC requests are achieved using bio_copy_user() instead of bio_map_user(). This works because bio_copy_user() always uses full pages and block DMA alignment isn't allowed to go over PAGE_SIZE. However, the implementation didn't update the last bio of the request to make this padding visible to lower layers. This patch makes blk_rq_map_user() extend the last bio such that it includes the padding area and the size of area pointed to by the request is properly aligned. Signed-off-by: Tejun Heo Cc: James Bottomley --- block/blk-map.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index 955d75c..103b1df 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -139,6 +139,23 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, ubuf += ret; } + /* + * __blk_rq_map_user() copies the buffers if starting address + * or length isn't aligned. As the copied buffer is always + * page aligned, we know that there's enough room for padding. + * Extend the last bio and update rq->data_len accordingly. + * + * On unmap, bio_uncopy_user() will use unmodified + * bio_map_data pointed to by bio->bi_private. + */ + if (len & queue_dma_alignment(q)) { + unsigned int pad_len = (queue_dma_alignment(q) & ~len) + 1; + struct bio *bio = rq->biotail; + + bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len; + bio->bi_size += pad_len; + } + rq->buffer = rq->data = NULL; return 0; unmap_rq: -- 1.5.2.4