git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mcheha...
[safe/jmp/linux-2.6]
/
block
/
blk-map.c
diff --git
a/block/blk-map.c
b/block/blk-map.c
index
572140c
..
9083cf0
100644
(file)
--- a/
block/blk-map.c
+++ b/
block/blk-map.c
@@
-20,11
+20,10
@@
int blk_rq_append_bio(struct request_queue *q, struct request *rq,
rq->biotail->bi_next = bio;
rq->biotail = bio;
rq->biotail->bi_next = bio;
rq->biotail = bio;
- rq->data_len += bio->bi_size;
+ rq->
__
data_len += bio->bi_size;
}
return 0;
}
}
return 0;
}
-EXPORT_SYMBOL(blk_rq_append_bio);
static int __blk_rq_unmap_user(struct bio *bio)
{
static int __blk_rq_unmap_user(struct bio *bio)
{
@@
-63,6
+62,9
@@
static int __blk_rq_map_user(struct request_queue *q, struct request *rq,
if (IS_ERR(bio))
return PTR_ERR(bio);
if (IS_ERR(bio))
return PTR_ERR(bio);
+ if (map_data && map_data->null_mapped)
+ bio->bi_flags |= (1 << BIO_NULL_MAPPED);
+
orig_bio = bio;
blk_queue_bounce(q, &bio);
orig_bio = bio;
blk_queue_bounce(q, &bio);
@@
-113,9
+115,12
@@
int blk_rq_map_user(struct request_queue *q, struct request *rq,
struct bio *bio = NULL;
int ret;
struct bio *bio = NULL;
int ret;
- if (len > (q->max_hw_sectors << 9))
+ if (len > (queue_max_hw_sectors(q) << 9))
+ return -EINVAL;
+ if (!len)
return -EINVAL;
return -EINVAL;
- if (!len || !ubuf)
+
+ if (!ubuf && (!map_data || !map_data->null_mapped))
return -EINVAL;
while (bytes_read != len) {
return -EINVAL;
while (bytes_read != len) {
@@
-142,12
+147,15
@@
int blk_rq_map_user(struct request_queue *q, struct request *rq,
bio = rq->bio;
bytes_read += ret;
ubuf += ret;
bio = rq->bio;
bytes_read += ret;
ubuf += ret;
+
+ if (map_data)
+ map_data->offset += ret;
}
if (!bio_flagged(bio, BIO_USER_MAPPED))
rq->cmd_flags |= REQ_COPY_USER;
}
if (!bio_flagged(bio, BIO_USER_MAPPED))
rq->cmd_flags |= REQ_COPY_USER;
- rq->buffer =
rq->data =
NULL;
+ rq->buffer = NULL;
return 0;
unmap_rq:
blk_rq_unmap_user(bio);
return 0;
unmap_rq:
blk_rq_unmap_user(bio);
@@
-209,8
+217,14
@@
int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
return PTR_ERR(bio);
if (bio->bi_size != len) {
return PTR_ERR(bio);
if (bio->bi_size != len) {
+ /*
+ * Grab an extra reference to this bio, as bio_unmap_user()
+ * expects to be able to drop it twice as it happens on the
+ * normal IO completion path
+ */
+ bio_get(bio);
bio_endio(bio, 0);
bio_endio(bio, 0);
-
bio
_unmap_user(bio);
+
__blk_rq
_unmap_user(bio);
return -EINVAL;
}
return -EINVAL;
}
@@
-220,7
+234,7
@@
int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
blk_queue_bounce(q, &bio);
bio_get(bio);
blk_rq_bio_prep(q, rq, bio);
blk_queue_bounce(q, &bio);
bio_get(bio);
blk_rq_bio_prep(q, rq, bio);
- rq->buffer =
rq->data =
NULL;
+ rq->buffer = NULL;
return 0;
}
EXPORT_SYMBOL(blk_rq_map_user_iov);
return 0;
}
EXPORT_SYMBOL(blk_rq_map_user_iov);
@@
-267,7
+281,8
@@
EXPORT_SYMBOL(blk_rq_unmap_user);
*
* Description:
* Data will be mapped directly if possible. Otherwise a bounce
*
* Description:
* Data will be mapped directly if possible. Otherwise a bounce
- * buffer is used.
+ * buffer is used. Can be called multple times to append multple
+ * buffers.
*/
int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
unsigned int len, gfp_t gfp_mask)
*/
int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
unsigned int len, gfp_t gfp_mask)
@@
-275,8
+290,9
@@
int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
int reading = rq_data_dir(rq) == READ;
int do_copy = 0;
struct bio *bio;
int reading = rq_data_dir(rq) == READ;
int do_copy = 0;
struct bio *bio;
+ int ret;
- if (len > (q
->max_hw_sectors
<< 9))
+ if (len > (q
ueue_max_hw_sectors(q)
<< 9))
return -EINVAL;
if (!len || !kbuf)
return -EINVAL;
return -EINVAL;
if (!len || !kbuf)
return -EINVAL;
@@
-296,9
+312,15
@@
int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
if (do_copy)
rq->cmd_flags |= REQ_COPY_USER;
if (do_copy)
rq->cmd_flags |= REQ_COPY_USER;
- blk_rq_bio_prep(q, rq, bio);
+ ret = blk_rq_append_bio(q, rq, bio);
+ if (unlikely(ret)) {
+ /* request is too big */
+ bio_put(bio);
+ return ret;
+ }
+
blk_queue_bounce(q, &rq->bio);
blk_queue_bounce(q, &rq->bio);
- rq->buffer =
rq->data =
NULL;
+ rq->buffer = NULL;
return 0;
}
EXPORT_SYMBOL(blk_rq_map_kern);
return 0;
}
EXPORT_SYMBOL(blk_rq_map_kern);