block layer: add partial mappings support to bio_map_user
Subsystems (3)
PATCH 2/6 block layer: add partial mappings support to bio_map_user
This is the updated patch for partial mappings support.
- bio_map_user_iov always allows partial mappings.
- The two users (blk_rq_map_user and blk_rq_map_user_iov) will fails if the bio is partially mapped.
- Added a length argument to blk_rq_map_user_iov in order to avoid including sg.h in ll_rw_blk.c for struct sg_iovec.
This is a resend:
http://marc.theaimsgroup.com/?l=linux-scsi&m=114086655400806&w=2
Signed-off-by FUJITA Tomonori <[email protected]>
Signed-off-by Mike Christie <[email protected]>
---
block/ll_rw_blk.c | 29 ++++++++++++++++++----------- block/scsi_ioctl.c | 3 ++- fs/bio.c | 14 +------------- include/linux/blkdev.h | 3 ++- 4 files changed, 23 insertions(+), 26 deletions(-)
bd5a6476b9a4fe5953527fd7c162a1e7754eea7c
block/ll_rw_blk.c +18 -11
@@ -2291,19 +2291,20 @@ int blk_rq_map_user(request_queue_t *q,else bio =bio_copy_user (q, uaddr, len, reading); -if (!IS_ERR (bio)) { - rq->bio = rq->biotail = bio; -blk_rq_bio_prep (q, rq, bio); +if (IS_ERR (bio)) +return PTR_ERR (bio); - rq->buffer = rq->data =NULL ; - rq->data_len = len; -return 0 ; +if (bio->bi_size != len) { +bio_endio (bio, bio->bi_size,0 ); +bio_unmap_user (bio); +return -EINVAL ; } -/* -* bio is the err-ptr -*/ -return PTR_ERR (bio); + rq->bio = rq->biotail = bio; +blk_rq_bio_prep (q, rq, bio); + rq->buffer = rq->data =NULL ; + rq->data_len = len; +return 0 ; }EXPORT_SYMBOL (blk_rq_map_user);
@@ -2329,7 +2330,7 @@ EXPORT_SYMBOL(blk_rq_map_user);* unmapping. */ int blk_rq_map_user_iov (request_queue_t *q,struct request *rq, -struct sg_iovec *iov,int iov_count) +struct sg_iovec *iov,int iov_count,unsigned int len) {struct bio *bio;
@@ -2343,6 +2344,12 @@ int blk_rq_map_user_iov(request_queue_tif (IS_ERR (bio))return PTR_ERR (bio); +if (bio->bi_size != len) { +bio_endio (bio, bio->bi_size,0 ); +bio_unmap_user (bio); +return -EINVAL ; + } + rq->bio = rq->biotail = bio;blk_rq_bio_prep (q, rq, bio); rq->buffer = rq->data =NULL ;
block/scsi_ioctl.c +2 -1
@@ -274,7 +274,8 @@ static int sg_io(struct file *file, requ goto out; } - ret =blk_rq_map_user_iov (q, rq, iov, hdr->iovec_count); + ret =blk_rq_map_user_iov (q, rq, iov, hdr->iovec_count, + hdr->dxfer_len);kfree (iov); }else if (hdr->dxfer_len) ret =blk_rq_map_user (q, rq, hdr->dxferp, hdr->dxfer_len);
fs/bio.c +1 -13
@@ -749,7 +749,6 @@ struct bio *bio_map_user_iov(request_que int write_to_vm) {struct bio *bio; -int len =0 , i; bio =__bio_map_user_iov (q, bdev, iov, iov_count, write_to_vm);
@@ -764,18 +763,7 @@ struct bio *bio_map_user_iov(request_que*/ bio_get (bio); -for (i =0 ; i < iov_count; i++) - len += iov[i].iov_len; - -if (bio->bi_size == len) -return bio; - -/* -* don't support partial mappings -*/ -bio_endio (bio, bio->bi_size,0 ); -bio_unmap_user (bio); -return ERR_PTR (-EINVAL ); +return bio; }static void __bio_unmap_user (struct bio *bio)
include/linux/blkdev.h +2 -1
@@ -611,7 +611,8 @@ extern void blk_queue_activity_fn(requesextern int blk_rq_map_user (request_queue_t *,struct request *,void __user *,unsigned int );extern int blk_rq_unmap_user (struct bio *,unsigned int );extern int blk_rq_map_kern (request_queue_t *,struct request *,void *,unsigned int ,gfp_t ); -extern int blk_rq_map_user_iov (request_queue_t *,struct request *,struct sg_iovec *,int ); +extern int blk_rq_map_user_iov (request_queue_t *,struct request *, +struct sg_iovec *,int ,unsigned int );extern int blk_execute_rq (request_queue_t *,struct gendisk *,struct request *,int ); extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
Signature · 1 line
1.1.5