hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/target/target_core_xcopy.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*******************************************************************************
23 * Filename: target_core_xcopy.c
34 *
....@@ -8,16 +9,6 @@
89 *
910 * Author:
1011 * Nicholas A. Bellinger <nab@daterainc.com>
11
- *
12
- * This program is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version.
16
- *
17
- * This program is distributed in the hope that it will be useful,
18
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- * GNU General Public License for more details.
2112 *
2213 ******************************************************************************/
2314
....@@ -166,7 +157,7 @@
166157 * Assigned designator
167158 */
168159 desig_len = desc[7];
169
- if (desig_len != 16) {
160
+ if (desig_len != XCOPY_NAA_IEEE_REGEX_LEN) {
170161 pr_err("XCOPY 0xe4: invalid desig_len: %d\n", (int)desig_len);
171162 return -EINVAL;
172163 }
....@@ -351,11 +342,6 @@
351342 xop->nolb, (unsigned long long)xop->src_lba,
352343 (unsigned long long)xop->dst_lba);
353344
354
- if (dc != 0) {
355
- xop->dbl = get_unaligned_be24(&desc[29]);
356
-
357
- pr_debug("XCOPY seg desc 0x02: DC=1 w/ dbl: %u\n", xop->dbl);
358
- }
359345 return 0;
360346 }
361347
....@@ -416,9 +402,7 @@
416402 */
417403
418404 struct xcopy_pt_cmd {
419
- bool remote_port;
420405 struct se_cmd se_cmd;
421
- struct xcopy_op *xcopy_op;
422406 struct completion xpt_passthrough_sem;
423407 unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
424408 };
....@@ -426,11 +410,6 @@
426410 struct se_portal_group xcopy_pt_tpg;
427411 static struct se_session xcopy_pt_sess;
428412 static struct se_node_acl xcopy_pt_nacl;
429
-
430
-static char *xcopy_pt_get_fabric_name(void)
431
-{
432
- return "xcopy-pt";
433
-}
434413
435414 static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
436415 {
....@@ -452,7 +431,8 @@
452431 struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
453432 struct xcopy_pt_cmd, se_cmd);
454433
455
- kfree(xpt_cmd);
434
+ /* xpt_cmd is on the stack, nothing to free here */
435
+ pr_debug("xpt_cmd done: %p\n", xpt_cmd);
456436 }
457437
458438 static int xcopy_pt_check_stop_free(struct se_cmd *se_cmd)
....@@ -469,11 +449,6 @@
469449 return 0;
470450 }
471451
472
-static int xcopy_pt_write_pending_status(struct se_cmd *se_cmd)
473
-{
474
- return 0;
475
-}
476
-
477452 static int xcopy_pt_queue_data_in(struct se_cmd *se_cmd)
478453 {
479454 return 0;
....@@ -485,12 +460,11 @@
485460 }
486461
487462 static const struct target_core_fabric_ops xcopy_pt_tfo = {
488
- .get_fabric_name = xcopy_pt_get_fabric_name,
463
+ .fabric_name = "xcopy-pt",
489464 .get_cmd_state = xcopy_pt_get_cmd_state,
490465 .release_cmd = xcopy_pt_release_cmd,
491466 .check_stop_free = xcopy_pt_check_stop_free,
492467 .write_pending = xcopy_pt_write_pending,
493
- .write_pending_status = xcopy_pt_write_pending_status,
494468 .queue_data_in = xcopy_pt_queue_data_in,
495469 .queue_status = xcopy_pt_queue_status,
496470 };
....@@ -510,7 +484,6 @@
510484 }
511485
512486 memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group));
513
- INIT_LIST_HEAD(&xcopy_pt_tpg.se_tpg_node);
514487 INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list);
515488 INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list);
516489
....@@ -522,7 +495,7 @@
522495 memset(&xcopy_pt_sess, 0, sizeof(struct se_session));
523496 ret = transport_init_session(&xcopy_pt_sess);
524497 if (ret < 0)
525
- return ret;
498
+ goto destroy_wq;
526499
527500 xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;
528501 xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;
....@@ -531,141 +504,71 @@
531504 xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl;
532505
533506 return 0;
507
+
508
+destroy_wq:
509
+ destroy_workqueue(xcopy_wq);
510
+ xcopy_wq = NULL;
511
+ return ret;
534512 }
535513
536514 void target_xcopy_release_pt(void)
537515 {
538
- if (xcopy_wq)
516
+ if (xcopy_wq) {
539517 destroy_workqueue(xcopy_wq);
540
-}
541
-
542
-static void target_xcopy_setup_pt_port(
543
- struct xcopy_pt_cmd *xpt_cmd,
544
- struct xcopy_op *xop,
545
- bool remote_port)
546
-{
547
- struct se_cmd *ec_cmd = xop->xop_se_cmd;
548
- struct se_cmd *pt_cmd = &xpt_cmd->se_cmd;
549
-
550
- if (xop->op_origin == XCOL_SOURCE_RECV_OP) {
551
- /*
552
- * Honor destination port reservations for X-COPY PUSH emulation
553
- * when CDB is received on local source port, and READs blocks to
554
- * WRITE on remote destination port.
555
- */
556
- if (remote_port) {
557
- xpt_cmd->remote_port = remote_port;
558
- } else {
559
- pt_cmd->se_lun = ec_cmd->se_lun;
560
- pt_cmd->se_dev = ec_cmd->se_dev;
561
-
562
- pr_debug("Honoring local SRC port from ec_cmd->se_dev:"
563
- " %p\n", pt_cmd->se_dev);
564
- pt_cmd->se_lun = ec_cmd->se_lun;
565
- pr_debug("Honoring local SRC port from ec_cmd->se_lun: %p\n",
566
- pt_cmd->se_lun);
567
- }
568
- } else {
569
- /*
570
- * Honor source port reservation for X-COPY PULL emulation
571
- * when CDB is received on local desintation port, and READs
572
- * blocks from the remote source port to WRITE on local
573
- * destination port.
574
- */
575
- if (remote_port) {
576
- xpt_cmd->remote_port = remote_port;
577
- } else {
578
- pt_cmd->se_lun = ec_cmd->se_lun;
579
- pt_cmd->se_dev = ec_cmd->se_dev;
580
-
581
- pr_debug("Honoring local DST port from ec_cmd->se_dev:"
582
- " %p\n", pt_cmd->se_dev);
583
- pt_cmd->se_lun = ec_cmd->se_lun;
584
- pr_debug("Honoring local DST port from ec_cmd->se_lun: %p\n",
585
- pt_cmd->se_lun);
586
- }
518
+ transport_uninit_session(&xcopy_pt_sess);
587519 }
588520 }
589521
590
-static void target_xcopy_init_pt_lun(struct se_device *se_dev,
591
- struct se_cmd *pt_cmd, bool remote_port)
592
-{
593
- /*
594
- * Don't allocate + init an pt_cmd->se_lun if honoring local port for
595
- * reservations. The pt_cmd->se_lun pointer will be setup from within
596
- * target_xcopy_setup_pt_port()
597
- */
598
- if (remote_port) {
599
- pr_debug("Setup emulated se_dev: %p from se_dev\n",
600
- pt_cmd->se_dev);
601
- pt_cmd->se_lun = &se_dev->xcopy_lun;
602
- pt_cmd->se_dev = se_dev;
603
- }
604
-
605
- pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
606
-}
607
-
522
+/*
523
+ * target_xcopy_setup_pt_cmd - set up a pass-through command
524
+ * @xpt_cmd: Data structure to initialize.
525
+ * @xop: Describes the XCOPY operation received from an initiator.
526
+ * @se_dev: Backend device to associate with @xpt_cmd if
527
+ * @remote_port == true.
528
+ * @cdb: SCSI CDB to be copied into @xpt_cmd.
529
+ * @remote_port: If false, use the LUN through which the XCOPY command has
530
+ * been received. If true, use @se_dev->xcopy_lun.
531
+ *
532
+ * Set up a SCSI command (READ or WRITE) that will be used to execute an
533
+ * XCOPY command.
534
+ */
608535 static int target_xcopy_setup_pt_cmd(
609536 struct xcopy_pt_cmd *xpt_cmd,
610537 struct xcopy_op *xop,
611538 struct se_device *se_dev,
612539 unsigned char *cdb,
613
- bool remote_port,
614
- bool alloc_mem)
540
+ bool remote_port)
615541 {
616542 struct se_cmd *cmd = &xpt_cmd->se_cmd;
617
- sense_reason_t sense_rc;
618
- int ret = 0, rc;
543
+
619544 /*
620545 * Setup LUN+port to honor reservations based upon xop->op_origin for
621546 * X-COPY PUSH or X-COPY PULL based upon where the CDB was received.
622547 */
623
- target_xcopy_init_pt_lun(se_dev, cmd, remote_port);
548
+ if (remote_port) {
549
+ cmd->se_lun = &se_dev->xcopy_lun;
550
+ cmd->se_dev = se_dev;
551
+ } else {
552
+ cmd->se_lun = xop->xop_se_cmd->se_lun;
553
+ cmd->se_dev = xop->xop_se_cmd->se_dev;
554
+ }
555
+ cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
624556
625
- xpt_cmd->xcopy_op = xop;
626
- target_xcopy_setup_pt_port(xpt_cmd, xop, remote_port);
557
+ if (target_cmd_init_cdb(cmd, cdb))
558
+ return -EINVAL;
627559
628560 cmd->tag = 0;
629
- sense_rc = target_setup_cmd_from_cdb(cmd, cdb);
630
- if (sense_rc) {
631
- ret = -EINVAL;
632
- goto out;
633
- }
561
+ if (target_cmd_parse_cdb(cmd))
562
+ return -EINVAL;
634563
635
- if (alloc_mem) {
636
- rc = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
637
- cmd->data_length, false, false);
638
- if (rc < 0) {
639
- ret = rc;
640
- goto out;
641
- }
642
- /*
643
- * Set this bit so that transport_free_pages() allows the
644
- * caller to release SGLs + physical memory allocated by
645
- * transport_generic_get_mem()..
646
- */
647
- cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
648
- } else {
649
- /*
650
- * Here the previously allocated SGLs for the internal READ
651
- * are mapped zero-copy to the internal WRITE.
652
- */
653
- sense_rc = transport_generic_map_mem_to_cmd(cmd,
654
- xop->xop_data_sg, xop->xop_data_nents,
655
- NULL, 0);
656
- if (sense_rc) {
657
- ret = -EINVAL;
658
- goto out;
659
- }
564
+ if (transport_generic_map_mem_to_cmd(cmd, xop->xop_data_sg,
565
+ xop->xop_data_nents, NULL, 0))
566
+ return -EINVAL;
660567
661
- pr_debug("Setup PASSTHROUGH_NOALLOC t_data_sg: %p t_data_nents:"
662
- " %u\n", cmd->t_data_sg, cmd->t_data_nents);
663
- }
568
+ pr_debug("Setup PASSTHROUGH_NOALLOC t_data_sg: %p t_data_nents:"
569
+ " %u\n", cmd->t_data_sg, cmd->t_data_nents);
664570
665571 return 0;
666
-
667
-out:
668
- return ret;
669572 }
670573
671574 static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)
....@@ -695,20 +598,15 @@
695598 sector_t src_lba,
696599 u32 src_sectors)
697600 {
698
- struct xcopy_pt_cmd *xpt_cmd;
699
- struct se_cmd *se_cmd;
601
+ struct xcopy_pt_cmd xpt_cmd;
602
+ struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
700603 u32 length = (src_sectors * src_dev->dev_attrib.block_size);
701604 int rc;
702605 unsigned char cdb[16];
703606 bool remote_port = (xop->op_origin == XCOL_DEST_RECV_OP);
704607
705
- xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
706
- if (!xpt_cmd) {
707
- pr_err("Unable to allocate xcopy_pt_cmd\n");
708
- return -ENOMEM;
709
- }
710
- init_completion(&xpt_cmd->xpt_passthrough_sem);
711
- se_cmd = &xpt_cmd->se_cmd;
608
+ memset(&xpt_cmd, 0, sizeof(xpt_cmd));
609
+ init_completion(&xpt_cmd.xpt_passthrough_sem);
712610
713611 memset(&cdb[0], 0, 16);
714612 cdb[0] = READ_16;
....@@ -718,36 +616,24 @@
718616 (unsigned long long)src_lba, src_sectors, length);
719617
720618 transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
721
- DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
722
- xop->src_pt_cmd = xpt_cmd;
619
+ DMA_FROM_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0);
723620
724
- rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
725
- remote_port, true);
621
+ rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, src_dev, &cdb[0],
622
+ remote_port);
726623 if (rc < 0) {
727
- ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
728
- transport_generic_free_cmd(se_cmd, 0);
729
- return rc;
624
+ ec_cmd->scsi_status = se_cmd->scsi_status;
625
+ goto out;
730626 }
731627
732
- xop->xop_data_sg = se_cmd->t_data_sg;
733
- xop->xop_data_nents = se_cmd->t_data_nents;
734628 pr_debug("XCOPY-READ: Saved xop->xop_data_sg: %p, num: %u for READ"
735629 " memory\n", xop->xop_data_sg, xop->xop_data_nents);
736630
737
- rc = target_xcopy_issue_pt_cmd(xpt_cmd);
738
- if (rc < 0) {
739
- ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
740
- transport_generic_free_cmd(se_cmd, 0);
741
- return rc;
742
- }
743
- /*
744
- * Clear off the allocated t_data_sg, that has been saved for
745
- * zero-copy WRITE submission reuse in struct xcopy_op..
746
- */
747
- se_cmd->t_data_sg = NULL;
748
- se_cmd->t_data_nents = 0;
749
-
750
- return 0;
631
+ rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
632
+ if (rc < 0)
633
+ ec_cmd->scsi_status = se_cmd->scsi_status;
634
+out:
635
+ transport_generic_free_cmd(se_cmd, 0);
636
+ return rc;
751637 }
752638
753639 static int target_xcopy_write_destination(
....@@ -757,20 +643,15 @@
757643 sector_t dst_lba,
758644 u32 dst_sectors)
759645 {
760
- struct xcopy_pt_cmd *xpt_cmd;
761
- struct se_cmd *se_cmd;
646
+ struct xcopy_pt_cmd xpt_cmd;
647
+ struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
762648 u32 length = (dst_sectors * dst_dev->dev_attrib.block_size);
763649 int rc;
764650 unsigned char cdb[16];
765651 bool remote_port = (xop->op_origin == XCOL_SOURCE_RECV_OP);
766652
767
- xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
768
- if (!xpt_cmd) {
769
- pr_err("Unable to allocate xcopy_pt_cmd\n");
770
- return -ENOMEM;
771
- }
772
- init_completion(&xpt_cmd->xpt_passthrough_sem);
773
- se_cmd = &xpt_cmd->se_cmd;
653
+ memset(&xpt_cmd, 0, sizeof(xpt_cmd));
654
+ init_completion(&xpt_cmd.xpt_passthrough_sem);
774655
775656 memset(&cdb[0], 0, 16);
776657 cdb[0] = WRITE_16;
....@@ -780,36 +661,21 @@
780661 (unsigned long long)dst_lba, dst_sectors, length);
781662
782663 transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
783
- DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
784
- xop->dst_pt_cmd = xpt_cmd;
664
+ DMA_TO_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0);
785665
786
- rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
787
- remote_port, false);
666
+ rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, dst_dev, &cdb[0],
667
+ remote_port);
788668 if (rc < 0) {
789
- struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
790
- ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
791
- /*
792
- * If the failure happened before the t_mem_list hand-off in
793
- * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
794
- * core releases this memory on error during X-COPY WRITE I/O.
795
- */
796
- src_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
797
- src_cmd->t_data_sg = xop->xop_data_sg;
798
- src_cmd->t_data_nents = xop->xop_data_nents;
799
-
800
- transport_generic_free_cmd(se_cmd, 0);
801
- return rc;
669
+ ec_cmd->scsi_status = se_cmd->scsi_status;
670
+ goto out;
802671 }
803672
804
- rc = target_xcopy_issue_pt_cmd(xpt_cmd);
805
- if (rc < 0) {
806
- ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
807
- se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
808
- transport_generic_free_cmd(se_cmd, 0);
809
- return rc;
810
- }
811
-
812
- return 0;
673
+ rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
674
+ if (rc < 0)
675
+ ec_cmd->scsi_status = se_cmd->scsi_status;
676
+out:
677
+ transport_generic_free_cmd(se_cmd, 0);
678
+ return rc;
813679 }
814680
815681 static void target_xcopy_do_work(struct work_struct *work)
....@@ -820,7 +686,7 @@
820686 sector_t src_lba, dst_lba, end_lba;
821687 unsigned int max_sectors;
822688 int rc = 0;
823
- unsigned short nolb, cur_nolb, max_nolb, copied_nolb = 0;
689
+ unsigned short nolb, max_nolb, copied_nolb = 0;
824690
825691 if (target_parse_xcopy_cmd(xop) != TCM_NO_SENSE)
826692 goto err_free;
....@@ -850,7 +716,23 @@
850716 (unsigned long long)src_lba, (unsigned long long)dst_lba);
851717
852718 while (src_lba < end_lba) {
853
- cur_nolb = min(nolb, max_nolb);
719
+ unsigned short cur_nolb = min(nolb, max_nolb);
720
+ u32 cur_bytes = cur_nolb * src_dev->dev_attrib.block_size;
721
+
722
+ if (cur_bytes != xop->xop_data_bytes) {
723
+ /*
724
+ * (Re)allocate a buffer large enough to hold the XCOPY
725
+ * I/O size, which can be reused each read / write loop.
726
+ */
727
+ target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
728
+ rc = target_alloc_sgl(&xop->xop_data_sg,
729
+ &xop->xop_data_nents,
730
+ cur_bytes,
731
+ false, false);
732
+ if (rc < 0)
733
+ goto out;
734
+ xop->xop_data_bytes = cur_bytes;
735
+ }
854736
855737 pr_debug("target_xcopy_do_work: Calling read src_dev: %p src_lba: %llu,"
856738 " cur_nolb: %hu\n", src_dev, (unsigned long long)src_lba, cur_nolb);
....@@ -868,10 +750,8 @@
868750
869751 rc = target_xcopy_write_destination(ec_cmd, xop, dst_dev,
870752 dst_lba, cur_nolb);
871
- if (rc < 0) {
872
- transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
753
+ if (rc < 0)
873754 goto out;
874
- }
875755
876756 dst_lba += cur_nolb;
877757 pr_debug("target_xcopy_do_work: Incremented WRITE dst_lba to %llu\n",
....@@ -879,14 +759,10 @@
879759
880760 copied_nolb += cur_nolb;
881761 nolb -= cur_nolb;
882
-
883
- transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
884
- xop->dst_pt_cmd->se_cmd.se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
885
-
886
- transport_generic_free_cmd(&xop->dst_pt_cmd->se_cmd, 0);
887762 }
888763
889764 xcopy_pt_undepend_remotedev(xop);
765
+ target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
890766 kfree(xop);
891767
892768 pr_debug("target_xcopy_do_work: Final src_lba: %llu, dst_lba: %llu\n",
....@@ -900,6 +776,7 @@
900776
901777 out:
902778 xcopy_pt_undepend_remotedev(xop);
779
+ target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
903780
904781 err_free:
905782 kfree(xop);