diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 38 |
1 files changed, 30 insertions, 8 deletions
@@ -313,7 +313,8 @@ int bio_get_nr_vecs(struct block_device *bdev) | |||
313 | } | 313 | } |
314 | 314 | ||
315 | static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page | 315 | static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page |
316 | *page, unsigned int len, unsigned int offset) | 316 | *page, unsigned int len, unsigned int offset, |
317 | unsigned short max_sectors) | ||
317 | { | 318 | { |
318 | int retried_segments = 0; | 319 | int retried_segments = 0; |
319 | struct bio_vec *bvec; | 320 | struct bio_vec *bvec; |
@@ -327,7 +328,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page | |||
327 | if (bio->bi_vcnt >= bio->bi_max_vecs) | 328 | if (bio->bi_vcnt >= bio->bi_max_vecs) |
328 | return 0; | 329 | return 0; |
329 | 330 | ||
330 | if (((bio->bi_size + len) >> 9) > q->max_sectors) | 331 | if (((bio->bi_size + len) >> 9) > max_sectors) |
331 | return 0; | 332 | return 0; |
332 | 333 | ||
333 | /* | 334 | /* |
@@ -386,6 +387,25 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page | |||
386 | } | 387 | } |
387 | 388 | ||
388 | /** | 389 | /** |
390 | * bio_add_pc_page - attempt to add page to bio | ||
391 | * @bio: destination bio | ||
392 | * @page: page to add | ||
393 | * @len: vec entry length | ||
394 | * @offset: vec entry offset | ||
395 | * | ||
396 | * Attempt to add a page to the bio_vec maplist. This can fail for a | ||
397 | * number of reasons, such as the bio being full or target block | ||
398 | * device limitations. The target block device must allow bio's | ||
399 | * smaller than PAGE_SIZE, so it is always possible to add a single | ||
400 | * page to an empty bio. This should only be used by REQ_PC bios. | ||
401 | */ | ||
402 | int bio_add_pc_page(request_queue_t *q, struct bio *bio, struct page *page, | ||
403 | unsigned int len, unsigned int offset) | ||
404 | { | ||
405 | return __bio_add_page(q, bio, page, len, offset, q->max_hw_sectors); | ||
406 | } | ||
407 | |||
408 | /** | ||
389 | * bio_add_page - attempt to add page to bio | 409 | * bio_add_page - attempt to add page to bio |
390 | * @bio: destination bio | 410 | * @bio: destination bio |
391 | * @page: page to add | 411 | * @page: page to add |
@@ -401,8 +421,8 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page | |||
401 | int bio_add_page(struct bio *bio, struct page *page, unsigned int len, | 421 | int bio_add_page(struct bio *bio, struct page *page, unsigned int len, |
402 | unsigned int offset) | 422 | unsigned int offset) |
403 | { | 423 | { |
404 | return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page, | 424 | struct request_queue *q = bdev_get_queue(bio->bi_bdev); |
405 | len, offset); | 425 | return __bio_add_page(q, bio, page, len, offset, q->max_sectors); |
406 | } | 426 | } |
407 | 427 | ||
408 | struct bio_map_data { | 428 | struct bio_map_data { |
@@ -514,7 +534,7 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr, | |||
514 | break; | 534 | break; |
515 | } | 535 | } |
516 | 536 | ||
517 | if (__bio_add_page(q, bio, page, bytes, 0) < bytes) { | 537 | if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) { |
518 | ret = -EINVAL; | 538 | ret = -EINVAL; |
519 | break; | 539 | break; |
520 | } | 540 | } |
@@ -628,7 +648,8 @@ static struct bio *__bio_map_user_iov(request_queue_t *q, | |||
628 | /* | 648 | /* |
629 | * sorry... | 649 | * sorry... |
630 | */ | 650 | */ |
631 | if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes) | 651 | if (bio_add_pc_page(q, bio, pages[j], bytes, offset) < |
652 | bytes) | ||
632 | break; | 653 | break; |
633 | 654 | ||
634 | len -= bytes; | 655 | len -= bytes; |
@@ -801,8 +822,8 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data, | |||
801 | if (bytes > len) | 822 | if (bytes > len) |
802 | bytes = len; | 823 | bytes = len; |
803 | 824 | ||
804 | if (__bio_add_page(q, bio, virt_to_page(data), bytes, | 825 | if (bio_add_pc_page(q, bio, virt_to_page(data), bytes, |
805 | offset) < bytes) | 826 | offset) < bytes) |
806 | break; | 827 | break; |
807 | 828 | ||
808 | data += bytes; | 829 | data += bytes; |
@@ -1228,6 +1249,7 @@ EXPORT_SYMBOL(bio_clone); | |||
1228 | EXPORT_SYMBOL(bio_phys_segments); | 1249 | EXPORT_SYMBOL(bio_phys_segments); |
1229 | EXPORT_SYMBOL(bio_hw_segments); | 1250 | EXPORT_SYMBOL(bio_hw_segments); |
1230 | EXPORT_SYMBOL(bio_add_page); | 1251 | EXPORT_SYMBOL(bio_add_page); |
1252 | EXPORT_SYMBOL(bio_add_pc_page); | ||
1231 | EXPORT_SYMBOL(bio_get_nr_vecs); | 1253 | EXPORT_SYMBOL(bio_get_nr_vecs); |
1232 | EXPORT_SYMBOL(bio_map_user); | 1254 | EXPORT_SYMBOL(bio_map_user); |
1233 | EXPORT_SYMBOL(bio_unmap_user); | 1255 | EXPORT_SYMBOL(bio_unmap_user); |