diff options
| author | Kent Overstreet <kmo@daterainc.com> | 2013-11-23 21:21:01 -0500 |
|---|---|---|
| committer | Kent Overstreet <kmo@daterainc.com> | 2013-11-24 01:33:57 -0500 |
| commit | 20d0189b1012a37d2533a87fb451f7852f2418d1 (patch) | |
| tree | 5ceaa6cfc0e1f1cec423c6c9f5de72d49f2d63a1 /drivers/block | |
| parent | ee67891bf132612feb7b999ee1f3350b40867cb4 (diff) | |
block: Introduce new bio_split()
The new bio_split() can split arbitrary bios - it's not restricted to
single page bios, like the old bio_split() (previously renamed to
bio_pair_split()). It also has different semantics - it doesn't allocate
a struct bio_pair, leaving it up to the caller to handle completions.
Then convert the existing bio_pair_split() users to the new bio_split()
- and also nvme, which was open coding bio splitting.
(We have to take that BUG_ON() out of bio_integrity_trim() because this
bio_split() needs to use it, and there's no reason it has to be used on
bios marked as cloned; BIO_CLONED doesn't seem to have clearly
documented semantics anyways.)
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Keith Busch <keith.busch@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Neil Brown <neilb@suse.de>
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/nvme-core.c | 106 | ||||
| -rw-r--r-- | drivers/block/pktcdvd.c | 136 |
2 files changed, 83 insertions, 159 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 5539d2920872..1f14ac403945 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
| @@ -441,104 +441,19 @@ int nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, | |||
| 441 | return total_len; | 441 | return total_len; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | struct nvme_bio_pair { | ||
| 445 | struct bio b1, b2, *parent; | ||
| 446 | struct bio_vec *bv1, *bv2; | ||
| 447 | int err; | ||
| 448 | atomic_t cnt; | ||
| 449 | }; | ||
| 450 | |||
| 451 | static void nvme_bio_pair_endio(struct bio *bio, int err) | ||
| 452 | { | ||
| 453 | struct nvme_bio_pair *bp = bio->bi_private; | ||
| 454 | |||
| 455 | if (err) | ||
| 456 | bp->err = err; | ||
| 457 | |||
| 458 | if (atomic_dec_and_test(&bp->cnt)) { | ||
| 459 | bio_endio(bp->parent, bp->err); | ||
| 460 | kfree(bp->bv1); | ||
| 461 | kfree(bp->bv2); | ||
| 462 | kfree(bp); | ||
| 463 | } | ||
| 464 | } | ||
| 465 | |||
| 466 | static struct nvme_bio_pair *nvme_bio_split(struct bio *bio, int idx, | ||
| 467 | int len, int offset) | ||
| 468 | { | ||
| 469 | struct nvme_bio_pair *bp; | ||
| 470 | |||
| 471 | BUG_ON(len > bio->bi_iter.bi_size); | ||
| 472 | BUG_ON(idx > bio->bi_vcnt); | ||
| 473 | |||
| 474 | bp = kmalloc(sizeof(*bp), GFP_ATOMIC); | ||
| 475 | if (!bp) | ||
| 476 | return NULL; | ||
| 477 | bp->err = 0; | ||
| 478 | |||
| 479 | bp->b1 = *bio; | ||
| 480 | bp->b2 = *bio; | ||
| 481 | |||
| 482 | bp->b1.bi_iter.bi_size = len; | ||
| 483 | bp->b2.bi_iter.bi_size -= len; | ||
| 484 | bp->b1.bi_vcnt = idx; | ||
| 485 | bp->b2.bi_iter.bi_idx = idx; | ||
| 486 | bp->b2.bi_iter.bi_sector += len >> 9; | ||
| 487 | |||
| 488 | if (offset) { | ||
| 489 | bp->bv1 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec), | ||
| 490 | GFP_ATOMIC); | ||
| 491 | if (!bp->bv1) | ||
| 492 | goto split_fail_1; | ||
| 493 | |||
| 494 | bp->bv2 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec), | ||
| 495 | GFP_ATOMIC); | ||
| 496 | if (!bp->bv2) | ||
| 497 | goto split_fail_2; | ||
| 498 | |||
| 499 | memcpy(bp->bv1, bio->bi_io_vec, | ||
| 500 | bio->bi_max_vecs * sizeof(struct bio_vec)); | ||
| 501 | memcpy(bp->bv2, bio->bi_io_vec, | ||
| 502 | bio->bi_max_vecs * sizeof(struct bio_vec)); | ||
| 503 | |||
| 504 | bp->b1.bi_io_vec = bp->bv1; | ||
| 505 | bp->b2.bi_io_vec = bp->bv2; | ||
| 506 | bp->b2.bi_io_vec[idx].bv_offset += offset; | ||
| 507 | bp->b2.bi_io_vec[idx].bv_len -= offset; | ||
| 508 | bp->b1.bi_io_vec[idx].bv_len = offset; | ||
| 509 | bp->b1.bi_vcnt++; | ||
| 510 | } else | ||
| 511 | bp->bv1 = bp->bv2 = NULL; | ||
| 512 | |||
| 513 | bp->b1.bi_private = bp; | ||
| 514 | bp->b2.bi_private = bp; | ||
| 515 | |||
| 516 | bp->b1.bi_end_io = nvme_bio_pair_endio; | ||
| 517 | bp->b2.bi_end_io = nvme_bio_pair_endio; | ||
| 518 | |||
| 519 | bp->parent = bio; | ||
| 520 | atomic_set(&bp->cnt, 2); | ||
| 521 | |||
| 522 | return bp; | ||
| 523 | |||
| 524 | split_fail_2: | ||
| 525 | kfree(bp->bv1); | ||
| 526 | split_fail_1: | ||
| 527 | kfree(bp); | ||
| 528 | return NULL; | ||
| 529 | } | ||
| 530 | |||
| 531 | static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq, | 444 | static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq, |
| 532 | int idx, int len, int offset) | 445 | int len) |
| 533 | { | 446 | { |
| 534 | struct nvme_bio_pair *bp = nvme_bio_split(bio, idx, len, offset); | 447 | struct bio *split = bio_split(bio, len >> 9, GFP_ATOMIC, NULL); |
| 535 | if (!bp) | 448 | if (!split) |
| 536 | return -ENOMEM; | 449 | return -ENOMEM; |
| 537 | 450 | ||
| 451 | bio_chain(split, bio); | ||
| 452 | |||
| 538 | if (bio_list_empty(&nvmeq->sq_cong)) | 453 | if (bio_list_empty(&nvmeq->sq_cong)) |
| 539 | add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait); | 454 | add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait); |
| 540 | bio_list_add(&nvmeq->sq_cong, &bp->b1); | 455 | bio_list_add(&nvmeq->sq_cong, split); |
| 541 | bio_list_add(&nvmeq->sq_cong, &bp->b2); | 456 | bio_list_add(&nvmeq->sq_cong, bio); |
| 542 | 457 | ||
| 543 | return 0; | 458 | return 0; |
| 544 | } | 459 | } |
| @@ -568,8 +483,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, | |||
| 568 | } else { | 483 | } else { |
| 569 | if (!first && BIOVEC_NOT_VIRT_MERGEABLE(&bvprv, &bvec)) | 484 | if (!first && BIOVEC_NOT_VIRT_MERGEABLE(&bvprv, &bvec)) |
| 570 | return nvme_split_and_submit(bio, nvmeq, | 485 | return nvme_split_and_submit(bio, nvmeq, |
| 571 | iter.bi_idx, | 486 | length); |
| 572 | length, 0); | ||
| 573 | 487 | ||
| 574 | sg = sg ? sg + 1 : iod->sg; | 488 | sg = sg ? sg + 1 : iod->sg; |
| 575 | sg_set_page(sg, bvec.bv_page, | 489 | sg_set_page(sg, bvec.bv_page, |
| @@ -578,9 +492,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, | |||
| 578 | } | 492 | } |
| 579 | 493 | ||
| 580 | if (split_len - length < bvec.bv_len) | 494 | if (split_len - length < bvec.bv_len) |
| 581 | return nvme_split_and_submit(bio, nvmeq, iter.bi_idx, | 495 | return nvme_split_and_submit(bio, nvmeq, split_len); |
| 582 | split_len, | ||
| 583 | split_len - length); | ||
| 584 | length += bvec.bv_len; | 496 | length += bvec.bv_len; |
| 585 | bvprv = bvec; | 497 | bvprv = bvec; |
| 586 | first = 0; | 498 | first = 0; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 28789b82ae7d..3dda09a5ec41 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -2338,75 +2338,29 @@ static void pkt_end_io_read_cloned(struct bio *bio, int err) | |||
| 2338 | pkt_bio_finished(pd); | 2338 | pkt_bio_finished(pd); |
| 2339 | } | 2339 | } |
| 2340 | 2340 | ||
| 2341 | static void pkt_make_request(struct request_queue *q, struct bio *bio) | 2341 | static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio) |
| 2342 | { | 2342 | { |
| 2343 | struct pktcdvd_device *pd; | 2343 | struct bio *cloned_bio = bio_clone(bio, GFP_NOIO); |
| 2344 | char b[BDEVNAME_SIZE]; | 2344 | struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO); |
| 2345 | |||
| 2346 | psd->pd = pd; | ||
| 2347 | psd->bio = bio; | ||
| 2348 | cloned_bio->bi_bdev = pd->bdev; | ||
| 2349 | cloned_bio->bi_private = psd; | ||
| 2350 | cloned_bio->bi_end_io = pkt_end_io_read_cloned; | ||
| 2351 | pd->stats.secs_r += bio_sectors(bio); | ||
| 2352 | pkt_queue_bio(pd, cloned_bio); | ||
| 2353 | } | ||
| 2354 | |||
| 2355 | static void pkt_make_request_write(struct request_queue *q, struct bio *bio) | ||
| 2356 | { | ||
| 2357 | struct pktcdvd_device *pd = q->queuedata; | ||
| 2345 | sector_t zone; | 2358 | sector_t zone; |
| 2346 | struct packet_data *pkt; | 2359 | struct packet_data *pkt; |
| 2347 | int was_empty, blocked_bio; | 2360 | int was_empty, blocked_bio; |
| 2348 | struct pkt_rb_node *node; | 2361 | struct pkt_rb_node *node; |
| 2349 | 2362 | ||
| 2350 | pd = q->queuedata; | ||
| 2351 | if (!pd) { | ||
| 2352 | pr_err("%s incorrect request queue\n", | ||
| 2353 | bdevname(bio->bi_bdev, b)); | ||
| 2354 | goto end_io; | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | /* | ||
| 2358 | * Clone READ bios so we can have our own bi_end_io callback. | ||
| 2359 | */ | ||
| 2360 | if (bio_data_dir(bio) == READ) { | ||
| 2361 | struct bio *cloned_bio = bio_clone(bio, GFP_NOIO); | ||
| 2362 | struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO); | ||
| 2363 | |||
| 2364 | psd->pd = pd; | ||
| 2365 | psd->bio = bio; | ||
| 2366 | cloned_bio->bi_bdev = pd->bdev; | ||
| 2367 | cloned_bio->bi_private = psd; | ||
| 2368 | cloned_bio->bi_end_io = pkt_end_io_read_cloned; | ||
| 2369 | pd->stats.secs_r += bio_sectors(bio); | ||
| 2370 | pkt_queue_bio(pd, cloned_bio); | ||
| 2371 | return; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | if (!test_bit(PACKET_WRITABLE, &pd->flags)) { | ||
| 2375 | pkt_notice(pd, "WRITE for ro device (%llu)\n", | ||
| 2376 | (unsigned long long)bio->bi_iter.bi_sector); | ||
| 2377 | goto end_io; | ||
| 2378 | } | ||
| 2379 | |||
| 2380 | if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { | ||
| 2381 | pkt_err(pd, "wrong bio size\n"); | ||
| 2382 | goto end_io; | ||
| 2383 | } | ||
| 2384 | |||
| 2385 | blk_queue_bounce(q, &bio); | ||
| 2386 | |||
| 2387 | zone = get_zone(bio->bi_iter.bi_sector, pd); | 2363 | zone = get_zone(bio->bi_iter.bi_sector, pd); |
| 2388 | pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", | ||
| 2389 | (unsigned long long)bio->bi_iter.bi_sector, | ||
| 2390 | (unsigned long long)bio_end_sector(bio)); | ||
| 2391 | |||
| 2392 | /* Check if we have to split the bio */ | ||
| 2393 | { | ||
| 2394 | struct bio_pair *bp; | ||
| 2395 | sector_t last_zone; | ||
| 2396 | int first_sectors; | ||
| 2397 | |||
| 2398 | last_zone = get_zone(bio_end_sector(bio) - 1, pd); | ||
| 2399 | if (last_zone != zone) { | ||
| 2400 | BUG_ON(last_zone != zone + pd->settings.size); | ||
| 2401 | first_sectors = last_zone - bio->bi_iter.bi_sector; | ||
| 2402 | bp = bio_pair_split(bio, first_sectors); | ||
| 2403 | BUG_ON(!bp); | ||
| 2404 | pkt_make_request(q, &bp->bio1); | ||
| 2405 | pkt_make_request(q, &bp->bio2); | ||
| 2406 | bio_pair_release(bp); | ||
| 2407 | return; | ||
| 2408 | } | ||
| 2409 | } | ||
| 2410 | 2364 | ||
| 2411 | /* | 2365 | /* |
| 2412 | * If we find a matching packet in state WAITING or READ_WAIT, we can | 2366 | * If we find a matching packet in state WAITING or READ_WAIT, we can |
| @@ -2480,6 +2434,64 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) | |||
| 2480 | */ | 2434 | */ |
| 2481 | wake_up(&pd->wqueue); | 2435 | wake_up(&pd->wqueue); |
| 2482 | } | 2436 | } |
| 2437 | } | ||
| 2438 | |||
| 2439 | static void pkt_make_request(struct request_queue *q, struct bio *bio) | ||
| 2440 | { | ||
| 2441 | struct pktcdvd_device *pd; | ||
| 2442 | char b[BDEVNAME_SIZE]; | ||
| 2443 | struct bio *split; | ||
| 2444 | |||
| 2445 | pd = q->queuedata; | ||
| 2446 | if (!pd) { | ||
| 2447 | pr_err("%s incorrect request queue\n", | ||
| 2448 | bdevname(bio->bi_bdev, b)); | ||
| 2449 | goto end_io; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", | ||
| 2453 | (unsigned long long)bio->bi_iter.bi_sector, | ||
| 2454 | (unsigned long long)bio_end_sector(bio)); | ||
| 2455 | |||
| 2456 | /* | ||
| 2457 | * Clone READ bios so we can have our own bi_end_io callback. | ||
| 2458 | */ | ||
| 2459 | if (bio_data_dir(bio) == READ) { | ||
| 2460 | pkt_make_request_read(pd, bio); | ||
| 2461 | return; | ||
| 2462 | } | ||
| 2463 | |||
| 2464 | if (!test_bit(PACKET_WRITABLE, &pd->flags)) { | ||
| 2465 | pkt_notice(pd, "WRITE for ro device (%llu)\n", | ||
| 2466 | (unsigned long long)bio->bi_iter.bi_sector); | ||
| 2467 | goto end_io; | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { | ||
| 2471 | pkt_err(pd, "wrong bio size\n"); | ||
| 2472 | goto end_io; | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | blk_queue_bounce(q, &bio); | ||
| 2476 | |||
| 2477 | do { | ||
| 2478 | sector_t zone = get_zone(bio->bi_iter.bi_sector, pd); | ||
| 2479 | sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd); | ||
| 2480 | |||
| 2481 | if (last_zone != zone) { | ||
| 2482 | BUG_ON(last_zone != zone + pd->settings.size); | ||
| 2483 | |||
| 2484 | split = bio_split(bio, last_zone - | ||
| 2485 | bio->bi_iter.bi_sector, | ||
| 2486 | GFP_NOIO, fs_bio_set); | ||
| 2487 | bio_chain(split, bio); | ||
| 2488 | } else { | ||
| 2489 | split = bio; | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | pkt_make_request_write(q, split); | ||
| 2493 | } while (split != bio); | ||
| 2494 | |||
| 2483 | return; | 2495 | return; |
| 2484 | end_io: | 2496 | end_io: |
| 2485 | bio_io_error(bio); | 2497 | bio_io_error(bio); |
