aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-02-22 11:48:42 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2015-02-27 14:20:47 -0500
commitd4c5dcacfaffb7493d161d5cd0fbb7b1190b7bd5 (patch)
tree096085d3b2a65238695479053ecc396e02315afa
parent6b9a44d0939ca6235c72b811bd55b462d6a0a553 (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.c100
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
436static unsigned char *
437fd_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
475static sense_reason_t 436static sense_reason_t
476fd_execute_write_same(struct se_cmd *cmd) 437fd_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