diff options
| -rw-r--r-- | drivers/target/target_core_iblock.c | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 53f4501819f9..664604616576 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
| @@ -151,6 +151,11 @@ static int iblock_configure_device(struct se_device *dev) | |||
| 151 | pr_debug("IBLOCK: BLOCK Discard support available," | 151 | pr_debug("IBLOCK: BLOCK Discard support available," |
| 152 | " disabled by default\n"); | 152 | " disabled by default\n"); |
| 153 | } | 153 | } |
| 154 | /* | ||
| 155 | * Enable write same emulation for IBLOCK and use 0xFFFF as | ||
| 156 | * the smaller WRITE_SAME(10) only has a two-byte block count. | ||
| 157 | */ | ||
| 158 | dev->dev_attrib.max_write_same_len = 0xFFFF; | ||
| 154 | 159 | ||
| 155 | if (blk_queue_nonrot(q)) | 160 | if (blk_queue_nonrot(q)) |
| 156 | dev->dev_attrib.is_nonrot = 1; | 161 | dev->dev_attrib.is_nonrot = 1; |
| @@ -375,17 +380,20 @@ err: | |||
| 375 | return ret; | 380 | return ret; |
| 376 | } | 381 | } |
| 377 | 382 | ||
| 383 | static struct bio *iblock_get_bio(struct se_cmd *, sector_t, u32); | ||
| 384 | static void iblock_submit_bios(struct bio_list *, int); | ||
| 385 | static void iblock_complete_cmd(struct se_cmd *); | ||
| 386 | |||
| 378 | static sense_reason_t | 387 | static sense_reason_t |
| 379 | iblock_execute_write_same(struct se_cmd *cmd) | 388 | iblock_execute_write_same_unmap(struct se_cmd *cmd) |
| 380 | { | 389 | { |
| 381 | struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); | 390 | struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); |
| 382 | int ret; | 391 | int rc; |
| 383 | 392 | ||
| 384 | ret = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, | 393 | rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba, |
| 385 | spc_get_write_same_sectors(cmd), GFP_KERNEL, | 394 | spc_get_write_same_sectors(cmd), GFP_KERNEL, 0); |
| 386 | 0); | 395 | if (rc < 0) { |
| 387 | if (ret < 0) { | 396 | pr_warn("blkdev_issue_discard() failed: %d\n", rc); |
| 388 | pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); | ||
| 389 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 397 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 390 | } | 398 | } |
| 391 | 399 | ||
| @@ -393,6 +401,69 @@ iblock_execute_write_same(struct se_cmd *cmd) | |||
| 393 | return 0; | 401 | return 0; |
| 394 | } | 402 | } |
| 395 | 403 | ||
| 404 | static sense_reason_t | ||
| 405 | iblock_execute_write_same(struct se_cmd *cmd) | ||
| 406 | { | ||
| 407 | struct iblock_req *ibr; | ||
| 408 | struct scatterlist *sg; | ||
| 409 | struct bio *bio; | ||
| 410 | struct bio_list list; | ||
| 411 | sector_t block_lba = cmd->t_task_lba; | ||
| 412 | unsigned int sectors = spc_get_write_same_sectors(cmd); | ||
| 413 | |||
| 414 | sg = &cmd->t_data_sg[0]; | ||
| 415 | |||
| 416 | if (cmd->t_data_nents > 1 || | ||
| 417 | sg->length != cmd->se_dev->dev_attrib.block_size) { | ||
| 418 | pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u" | ||
| 419 | " block_size: %u\n", cmd->t_data_nents, sg->length, | ||
| 420 | cmd->se_dev->dev_attrib.block_size); | ||
| 421 | return TCM_INVALID_CDB_FIELD; | ||
| 422 | } | ||
| 423 | |||
| 424 | ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); | ||
| 425 | if (!ibr) | ||
| 426 | goto fail; | ||
| 427 | cmd->priv = ibr; | ||
| 428 | |||
| 429 | bio = iblock_get_bio(cmd, block_lba, 1); | ||
| 430 | if (!bio) | ||
| 431 | goto fail_free_ibr; | ||
| 432 | |||
| 433 | bio_list_init(&list); | ||
| 434 | bio_list_add(&list, bio); | ||
| 435 | |||
| 436 | atomic_set(&ibr->pending, 1); | ||
| 437 | |||
| 438 | while (sectors) { | ||
| 439 | while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) | ||
| 440 | != sg->length) { | ||
| 441 | |||
| 442 | bio = iblock_get_bio(cmd, block_lba, 1); | ||
| 443 | if (!bio) | ||
| 444 | goto fail_put_bios; | ||
| 445 | |||
| 446 | atomic_inc(&ibr->pending); | ||
| 447 | bio_list_add(&list, bio); | ||
| 448 | } | ||
| 449 | |||
| 450 | /* Always in 512 byte units for Linux/Block */ | ||
| 451 | block_lba += sg->length >> IBLOCK_LBA_SHIFT; | ||
| 452 | sectors -= 1; | ||
| 453 | } | ||
| 454 | |||
| 455 | iblock_submit_bios(&list, WRITE); | ||
| 456 | return 0; | ||
| 457 | |||
| 458 | fail_put_bios: | ||
| 459 | while ((bio = bio_list_pop(&list))) | ||
| 460 | bio_put(bio); | ||
| 461 | fail_free_ibr: | ||
| 462 | kfree(ibr); | ||
| 463 | fail: | ||
| 464 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 465 | } | ||
| 466 | |||
| 396 | enum { | 467 | enum { |
| 397 | Opt_udev_path, Opt_readonly, Opt_force, Opt_err | 468 | Opt_udev_path, Opt_readonly, Opt_force, Opt_err |
| 398 | }; | 469 | }; |
| @@ -701,6 +772,7 @@ static struct sbc_ops iblock_sbc_ops = { | |||
| 701 | .execute_rw = iblock_execute_rw, | 772 | .execute_rw = iblock_execute_rw, |
| 702 | .execute_sync_cache = iblock_execute_sync_cache, | 773 | .execute_sync_cache = iblock_execute_sync_cache, |
| 703 | .execute_write_same = iblock_execute_write_same, | 774 | .execute_write_same = iblock_execute_write_same, |
| 775 | .execute_write_same_unmap = iblock_execute_write_same_unmap, | ||
| 704 | .execute_unmap = iblock_execute_unmap, | 776 | .execute_unmap = iblock_execute_unmap, |
| 705 | }; | 777 | }; |
| 706 | 778 | ||
