|
@@ -716,9 +716,23 @@ int bio_get_nr_vecs(struct block_device *bdev)
|
|
|
}
|
|
|
EXPORT_SYMBOL(bio_get_nr_vecs);
|
|
|
|
|
|
-static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
- *page, unsigned int len, unsigned int offset,
|
|
|
- unsigned int max_sectors)
|
|
|
+/**
|
|
|
+ * bio_add_pc_page - attempt to add page to bio
|
|
|
+ * @q: the target queue
|
|
|
+ * @bio: destination bio
|
|
|
+ * @page: page to add
|
|
|
+ * @len: vec entry length
|
|
|
+ * @offset: vec entry offset
|
|
|
+ *
|
|
|
+ * Attempt to add a page to the bio_vec maplist. This can fail for a
|
|
|
+ * number of reasons, such as the bio being full or target block device
|
|
|
+ * limitations. The target block device must allow bio's up to PAGE_SIZE,
|
|
|
+ * so it is always possible to add a single page to an empty bio.
|
|
|
+ *
|
|
|
+ * This should only be used by REQ_PC bios.
|
|
|
+ */
|
|
|
+int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
+ *page, unsigned int len, unsigned int offset)
|
|
|
{
|
|
|
int retried_segments = 0;
|
|
|
struct bio_vec *bvec;
|
|
@@ -729,7 +743,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
if (unlikely(bio_flagged(bio, BIO_CLONED)))
|
|
|
return 0;
|
|
|
|
|
|
- if (((bio->bi_iter.bi_size + len) >> 9) > max_sectors)
|
|
|
+ if (((bio->bi_iter.bi_size + len) >> 9) > queue_max_hw_sectors(q))
|
|
|
return 0;
|
|
|
|
|
|
/*
|
|
@@ -742,28 +756,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
|
|
|
if (page == prev->bv_page &&
|
|
|
offset == prev->bv_offset + prev->bv_len) {
|
|
|
- unsigned int prev_bv_len = prev->bv_len;
|
|
|
prev->bv_len += len;
|
|
|
-
|
|
|
- if (q->merge_bvec_fn) {
|
|
|
- struct bvec_merge_data bvm = {
|
|
|
- /* prev_bvec is already charged in
|
|
|
- bi_size, discharge it in order to
|
|
|
- simulate merging updated prev_bvec
|
|
|
- as new bvec. */
|
|
|
- .bi_bdev = bio->bi_bdev,
|
|
|
- .bi_sector = bio->bi_iter.bi_sector,
|
|
|
- .bi_size = bio->bi_iter.bi_size -
|
|
|
- prev_bv_len,
|
|
|
- .bi_rw = bio->bi_rw,
|
|
|
- };
|
|
|
-
|
|
|
- if (q->merge_bvec_fn(q, &bvm, prev) < prev->bv_len) {
|
|
|
- prev->bv_len -= len;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
bio->bi_iter.bi_size += len;
|
|
|
goto done;
|
|
|
}
|
|
@@ -806,27 +799,6 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
blk_recount_segments(q, bio);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * if queue has other restrictions (eg varying max sector size
|
|
|
- * depending on offset), it can specify a merge_bvec_fn in the
|
|
|
- * queue to get further control
|
|
|
- */
|
|
|
- if (q->merge_bvec_fn) {
|
|
|
- struct bvec_merge_data bvm = {
|
|
|
- .bi_bdev = bio->bi_bdev,
|
|
|
- .bi_sector = bio->bi_iter.bi_sector,
|
|
|
- .bi_size = bio->bi_iter.bi_size - len,
|
|
|
- .bi_rw = bio->bi_rw,
|
|
|
- };
|
|
|
-
|
|
|
- /*
|
|
|
- * merge_bvec_fn() returns number of bytes it can accept
|
|
|
- * at this offset
|
|
|
- */
|
|
|
- if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len)
|
|
|
- goto failed;
|
|
|
- }
|
|
|
-
|
|
|
/* If we may be able to merge these biovecs, force a recount */
|
|
|
if (bio->bi_vcnt > 1 && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
|
|
|
bio_clear_flag(bio, BIO_SEG_VALID);
|
|
@@ -843,28 +815,6 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
|
|
|
blk_recount_segments(q, bio);
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
-/**
|
|
|
- * bio_add_pc_page - attempt to add page to bio
|
|
|
- * @q: the target queue
|
|
|
- * @bio: destination bio
|
|
|
- * @page: page to add
|
|
|
- * @len: vec entry length
|
|
|
- * @offset: vec entry offset
|
|
|
- *
|
|
|
- * Attempt to add a page to the bio_vec maplist. This can fail for a
|
|
|
- * number of reasons, such as the bio being full or target block device
|
|
|
- * limitations. The target block device must allow bio's up to PAGE_SIZE,
|
|
|
- * so it is always possible to add a single page to an empty bio.
|
|
|
- *
|
|
|
- * This should only be used by REQ_PC bios.
|
|
|
- */
|
|
|
-int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page,
|
|
|
- unsigned int len, unsigned int offset)
|
|
|
-{
|
|
|
- return __bio_add_page(q, bio, page, len, offset,
|
|
|
- queue_max_hw_sectors(q));
|
|
|
-}
|
|
|
EXPORT_SYMBOL(bio_add_pc_page);
|
|
|
|
|
|
/**
|
|
@@ -874,22 +824,47 @@ EXPORT_SYMBOL(bio_add_pc_page);
|
|
|
* @len: vec entry length
|
|
|
* @offset: vec entry offset
|
|
|
*
|
|
|
- * Attempt to add a page to the bio_vec maplist. This can fail for a
|
|
|
- * number of reasons, such as the bio being full or target block device
|
|
|
- * limitations. The target block device must allow bio's up to PAGE_SIZE,
|
|
|
- * so it is always possible to add a single page to an empty bio.
|
|
|
+ * Attempt to add a page to the bio_vec maplist. This will only fail
|
|
|
+ * if either bio->bi_vcnt == bio->bi_max_vecs or it's a cloned bio.
|
|
|
*/
|
|
|
-int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
|
|
|
- unsigned int offset)
|
|
|
+int bio_add_page(struct bio *bio, struct page *page,
|
|
|
+ unsigned int len, unsigned int offset)
|
|
|
{
|
|
|
- struct request_queue *q = bdev_get_queue(bio->bi_bdev);
|
|
|
- unsigned int max_sectors;
|
|
|
+ struct bio_vec *bv;
|
|
|
|
|
|
- max_sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
|
|
|
- if ((max_sectors < (len >> 9)) && !bio->bi_iter.bi_size)
|
|
|
- max_sectors = len >> 9;
|
|
|
+ /*
|
|
|
+ * cloned bio must not modify vec list
|
|
|
+ */
|
|
|
+ if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
|
|
|
+ return 0;
|
|
|
|
|
|
- return __bio_add_page(q, bio, page, len, offset, max_sectors);
|
|
|
+ /*
|
|
|
+ * For filesystems with a blocksize smaller than the pagesize
|
|
|
+ * we will often be called with the same page as last time and
|
|
|
+ * a consecutive offset. Optimize this special case.
|
|
|
+ */
|
|
|
+ if (bio->bi_vcnt > 0) {
|
|
|
+ bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
|
|
|
+
|
|
|
+ if (page == bv->bv_page &&
|
|
|
+ offset == bv->bv_offset + bv->bv_len) {
|
|
|
+ bv->bv_len += len;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bio->bi_vcnt >= bio->bi_max_vecs)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bv = &bio->bi_io_vec[bio->bi_vcnt];
|
|
|
+ bv->bv_page = page;
|
|
|
+ bv->bv_len = len;
|
|
|
+ bv->bv_offset = offset;
|
|
|
+
|
|
|
+ bio->bi_vcnt++;
|
|
|
+done:
|
|
|
+ bio->bi_iter.bi_size += len;
|
|
|
+ return len;
|
|
|
}
|
|
|
EXPORT_SYMBOL(bio_add_page);
|
|
|
|