diff options
author | Christoph Hellwig <hch@lst.de> | 2015-02-22 11:48:42 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-02-27 14:20:47 -0500 |
commit | d4c5dcacfaffb7493d161d5cd0fbb7b1190b7bd5 (patch) | |
tree | 096085d3b2a65238695479053ecc396e02315afa | |
parent | 6b9a44d0939ca6235c72b811bd55b462d6a0a553 (diff) |
target: rewrite fd_execute_write_same
With the new bio_vec backed iov_iter helpers we can simply set up
on bio_vec per LBA, all pointing to the same initiator-supplied
buffer.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_file.c | 100 |
1 files changed, 22 insertions, 78 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index ea6e14e3ac5a..8800d54f743b 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -433,59 +433,17 @@ fd_execute_sync_cache(struct se_cmd *cmd) | |||
433 | return 0; | 433 | return 0; |
434 | } | 434 | } |
435 | 435 | ||
436 | static unsigned char * | ||
437 | fd_setup_write_same_buf(struct se_cmd *cmd, struct scatterlist *sg, | ||
438 | unsigned int len) | ||
439 | { | ||
440 | struct se_device *se_dev = cmd->se_dev; | ||
441 | unsigned int block_size = se_dev->dev_attrib.block_size; | ||
442 | unsigned int i = 0, end; | ||
443 | unsigned char *buf, *p, *kmap_buf; | ||
444 | |||
445 | buf = kzalloc(min_t(unsigned int, len, PAGE_SIZE), GFP_KERNEL); | ||
446 | if (!buf) { | ||
447 | pr_err("Unable to allocate fd_execute_write_same buf\n"); | ||
448 | return NULL; | ||
449 | } | ||
450 | |||
451 | kmap_buf = kmap(sg_page(sg)) + sg->offset; | ||
452 | if (!kmap_buf) { | ||
453 | pr_err("kmap() failed in fd_setup_write_same\n"); | ||
454 | kfree(buf); | ||
455 | return NULL; | ||
456 | } | ||
457 | /* | ||
458 | * Fill local *buf to contain multiple WRITE_SAME blocks up to | ||
459 | * min(len, PAGE_SIZE) | ||
460 | */ | ||
461 | p = buf; | ||
462 | end = min_t(unsigned int, len, PAGE_SIZE); | ||
463 | |||
464 | while (i < end) { | ||
465 | memcpy(p, kmap_buf, block_size); | ||
466 | |||
467 | i += block_size; | ||
468 | p += block_size; | ||
469 | } | ||
470 | kunmap(sg_page(sg)); | ||
471 | |||
472 | return buf; | ||
473 | } | ||
474 | |||
475 | static sense_reason_t | 436 | static sense_reason_t |
476 | fd_execute_write_same(struct se_cmd *cmd) | 437 | fd_execute_write_same(struct se_cmd *cmd) |
477 | { | 438 | { |
478 | struct se_device *se_dev = cmd->se_dev; | 439 | struct se_device *se_dev = cmd->se_dev; |
479 | struct fd_dev *fd_dev = FD_DEV(se_dev); | 440 | struct fd_dev *fd_dev = FD_DEV(se_dev); |
480 | struct file *f = fd_dev->fd_file; | ||
481 | struct scatterlist *sg; | ||
482 | struct iovec *iov; | ||
483 | mm_segment_t old_fs; | ||
484 | sector_t nolb = sbc_get_write_same_sectors(cmd); | ||
485 | loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size; | 441 | loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size; |
486 | unsigned int len, len_tmp, iov_num; | 442 | sector_t nolb = sbc_get_write_same_sectors(cmd); |
487 | int i, rc; | 443 | struct iov_iter iter; |
488 | unsigned char *buf; | 444 | struct bio_vec *bvec; |
445 | unsigned int len = 0, i; | ||
446 | ssize_t ret; | ||
489 | 447 | ||
490 | if (!nolb) { | 448 | if (!nolb) { |
491 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 449 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
@@ -496,49 +454,35 @@ fd_execute_write_same(struct se_cmd *cmd) | |||
496 | " backends not supported\n"); | 454 | " backends not supported\n"); |
497 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 455 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
498 | } | 456 | } |
499 | sg = &cmd->t_data_sg[0]; | ||
500 | 457 | ||
501 | if (cmd->t_data_nents > 1 || | 458 | if (cmd->t_data_nents > 1 || |
502 | sg->length != cmd->se_dev->dev_attrib.block_size) { | 459 | cmd->t_data_sg[0].length != cmd->se_dev->dev_attrib.block_size) { |
503 | pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u" | 460 | pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u" |
504 | " block_size: %u\n", cmd->t_data_nents, sg->length, | 461 | " block_size: %u\n", |
462 | cmd->t_data_nents, | ||
463 | cmd->t_data_sg[0].length, | ||
505 | cmd->se_dev->dev_attrib.block_size); | 464 | cmd->se_dev->dev_attrib.block_size); |
506 | return TCM_INVALID_CDB_FIELD; | 465 | return TCM_INVALID_CDB_FIELD; |
507 | } | 466 | } |
508 | 467 | ||
509 | len = len_tmp = nolb * se_dev->dev_attrib.block_size; | 468 | bvec = kcalloc(nolb, sizeof(struct bio_vec), GFP_KERNEL); |
510 | iov_num = DIV_ROUND_UP(len, PAGE_SIZE); | 469 | if (!bvec) |
511 | |||
512 | buf = fd_setup_write_same_buf(cmd, sg, len); | ||
513 | if (!buf) | ||
514 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 470 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
515 | 471 | ||
516 | iov = vzalloc(sizeof(struct iovec) * iov_num); | 472 | for (i = 0; i < nolb; i++) { |
517 | if (!iov) { | 473 | bvec[i].bv_page = sg_page(&cmd->t_data_sg[0]); |
518 | pr_err("Unable to allocate fd_execute_write_same iovecs\n"); | 474 | bvec[i].bv_len = cmd->t_data_sg[0].length; |
519 | kfree(buf); | 475 | bvec[i].bv_offset = cmd->t_data_sg[0].offset; |
520 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
521 | } | ||
522 | /* | ||
523 | * Map the single fabric received scatterlist block now populated | ||
524 | * in *buf into each iovec for I/O submission. | ||
525 | */ | ||
526 | for (i = 0; i < iov_num; i++) { | ||
527 | iov[i].iov_base = buf; | ||
528 | iov[i].iov_len = min_t(unsigned int, len_tmp, PAGE_SIZE); | ||
529 | len_tmp -= iov[i].iov_len; | ||
530 | } | ||
531 | 476 | ||
532 | old_fs = get_fs(); | 477 | len += se_dev->dev_attrib.block_size; |
533 | set_fs(get_ds()); | 478 | } |
534 | rc = vfs_writev(f, &iov[0], iov_num, &pos); | ||
535 | set_fs(old_fs); | ||
536 | 479 | ||
537 | vfree(iov); | 480 | iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len); |
538 | kfree(buf); | 481 | ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos); |
539 | 482 | ||
540 | if (rc < 0 || rc != len) { | 483 | kfree(bvec); |
541 | pr_err("vfs_writev() returned %d for write same\n", rc); | 484 | if (ret < 0 || ret != len) { |
485 | pr_err("vfs_iter_write() returned %zd for write same\n", ret); | ||
542 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 486 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
543 | } | 487 | } |
544 | 488 | ||