target_core_xcopy.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*******************************************************************************
  3. * Filename: target_core_xcopy.c
  4. *
  5. * This file contains support for SPC-4 Extended-Copy offload with generic
  6. * TCM backends.
  7. *
  8. * Copyright (c) 2011-2013 Datera, Inc. All rights reserved.
  9. *
  10. * Author:
  11. * Nicholas A. Bellinger <nab@daterainc.com>
  12. *
  13. ******************************************************************************/
  14. #include <linux/slab.h>
  15. #include <linux/spinlock.h>
  16. #include <linux/list.h>
  17. #include <linux/rculist.h>
  18. #include <linux/configfs.h>
  19. #include <linux/ratelimit.h>
  20. #include <scsi/scsi_proto.h>
  21. #include <linux/unaligned.h>
  22. #include <target/target_core_base.h>
  23. #include <target/target_core_backend.h>
  24. #include <target/target_core_fabric.h>
  25. #include "target_core_internal.h"
  26. #include "target_core_pr.h"
  27. #include "target_core_ua.h"
  28. #include "target_core_xcopy.h"
  29. static struct workqueue_struct *xcopy_wq = NULL;
  30. static sense_reason_t target_parse_xcopy_cmd(struct xcopy_op *xop);
  31. /**
  32. * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
  33. *
  34. * @se_dev: device being considered for match
  35. * @dev_wwn: XCOPY requested NAA dev_wwn
  36. * @return: 1 on match, 0 on no-match
  37. */
  38. static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev,
  39. const unsigned char *dev_wwn)
  40. {
  41. unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
  42. int rc;
  43. if (!se_dev->dev_attrib.emulate_3pc) {
  44. pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev);
  45. return 0;
  46. }
  47. memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
  48. spc_gen_naa_6h_vendor_specific(se_dev, &tmp_dev_wwn[0]);
  49. rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
  50. if (rc != 0) {
  51. pr_debug("XCOPY: skip non-matching: %*ph\n",
  52. XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
  53. return 0;
  54. }
  55. pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
  56. return 1;
  57. }
  58. static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
  59. const unsigned char *dev_wwn,
  60. struct se_device **_found_dev,
  61. struct percpu_ref **_found_lun_ref)
  62. {
  63. struct se_dev_entry *deve;
  64. struct se_node_acl *nacl;
  65. struct se_lun *this_lun = NULL;
  66. struct se_device *found_dev = NULL;
  67. /* cmd with NULL sess indicates no associated $FABRIC_MOD */
  68. if (!sess)
  69. goto err_out;
  70. pr_debug("XCOPY 0xe4: searching for: %*ph\n",
  71. XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
  72. nacl = sess->se_node_acl;
  73. rcu_read_lock();
  74. hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
  75. struct se_device *this_dev;
  76. int rc;
  77. this_lun = deve->se_lun;
  78. this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
  79. rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn);
  80. if (rc) {
  81. if (percpu_ref_tryget_live(&this_lun->lun_ref))
  82. found_dev = this_dev;
  83. break;
  84. }
  85. }
  86. rcu_read_unlock();
  87. if (found_dev == NULL)
  88. goto err_out;
  89. pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n",
  90. found_dev, &found_dev->dev_group);
  91. *_found_dev = found_dev;
  92. *_found_lun_ref = &this_lun->lun_ref;
  93. return 0;
  94. err_out:
  95. pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
  96. return -EINVAL;
  97. }
  98. static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
  99. unsigned char *p, unsigned short cscd_index)
  100. {
  101. unsigned char *desc = p;
  102. unsigned short ript;
  103. u8 desig_len;
  104. /*
  105. * Extract RELATIVE INITIATOR PORT IDENTIFIER
  106. */
  107. ript = get_unaligned_be16(&desc[2]);
  108. pr_debug("XCOPY 0xe4: RELATIVE INITIATOR PORT IDENTIFIER: %hu\n", ript);
  109. /*
  110. * Check for supported code set, association, and designator type
  111. */
  112. if ((desc[4] & 0x0f) != 0x1) {
  113. pr_err("XCOPY 0xe4: code set of non binary type not supported\n");
  114. return -EINVAL;
  115. }
  116. if ((desc[5] & 0x30) != 0x00) {
  117. pr_err("XCOPY 0xe4: association other than LUN not supported\n");
  118. return -EINVAL;
  119. }
  120. if ((desc[5] & 0x0f) != 0x3) {
  121. pr_err("XCOPY 0xe4: designator type unsupported: 0x%02x\n",
  122. (desc[5] & 0x0f));
  123. return -EINVAL;
  124. }
  125. /*
  126. * Check for matching 16 byte length for NAA IEEE Registered Extended
  127. * Assigned designator
  128. */
  129. desig_len = desc[7];
  130. if (desig_len != XCOPY_NAA_IEEE_REGEX_LEN) {
  131. pr_err("XCOPY 0xe4: invalid desig_len: %d\n", (int)desig_len);
  132. return -EINVAL;
  133. }
  134. pr_debug("XCOPY 0xe4: desig_len: %d\n", (int)desig_len);
  135. /*
  136. * Check for NAA IEEE Registered Extended Assigned header..
  137. */
  138. if ((desc[8] & 0xf0) != 0x60) {
  139. pr_err("XCOPY 0xe4: Unsupported DESIGNATOR TYPE: 0x%02x\n",
  140. (desc[8] & 0xf0));
  141. return -EINVAL;
  142. }
  143. if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
  144. pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
  145. "dest\n", cscd_index);
  146. return 0;
  147. }
  148. if (cscd_index == xop->stdi) {
  149. memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
  150. /*
  151. * Determine if the source designator matches the local device
  152. */
  153. if (!memcmp(&xop->local_dev_wwn[0], &xop->src_tid_wwn[0],
  154. XCOPY_NAA_IEEE_REGEX_LEN)) {
  155. xop->op_origin = XCOL_SOURCE_RECV_OP;
  156. xop->src_dev = se_cmd->se_dev;
  157. pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
  158. " received xop\n", xop->src_dev);
  159. }
  160. }
  161. if (cscd_index == xop->dtdi) {
  162. memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
  163. /*
  164. * Determine if the destination designator matches the local
  165. * device. If @cscd_index corresponds to both source (stdi) and
  166. * destination (dtdi), or dtdi comes after stdi, then
  167. * XCOL_DEST_RECV_OP wins.
  168. */
  169. if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
  170. XCOPY_NAA_IEEE_REGEX_LEN)) {
  171. xop->op_origin = XCOL_DEST_RECV_OP;
  172. xop->dst_dev = se_cmd->se_dev;
  173. pr_debug("XCOPY 0xe4: Set xop->dst_dev: %p from destination"
  174. " received xop\n", xop->dst_dev);
  175. }
  176. }
  177. return 0;
  178. }
  179. static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
  180. struct xcopy_op *xop, unsigned char *p,
  181. unsigned short tdll, sense_reason_t *sense_ret)
  182. {
  183. struct se_device *local_dev = se_cmd->se_dev;
  184. unsigned char *desc = p;
  185. int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
  186. unsigned short cscd_index = 0;
  187. unsigned short start = 0;
  188. *sense_ret = TCM_INVALID_PARAMETER_LIST;
  189. if (offset != 0) {
  190. pr_err("XCOPY target descriptor list length is not"
  191. " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
  192. *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
  193. return -EINVAL;
  194. }
  195. if (tdll > RCR_OP_MAX_TARGET_DESC_COUNT * XCOPY_TARGET_DESC_LEN) {
  196. pr_err("XCOPY target descriptor supports a maximum"
  197. " two src/dest descriptors, tdll: %hu too large..\n", tdll);
  198. /* spc4r37 6.4.3.4 CSCD DESCRIPTOR LIST LENGTH field */
  199. *sense_ret = TCM_TOO_MANY_TARGET_DESCS;
  200. return -EINVAL;
  201. }
  202. /*
  203. * Generate an IEEE Registered Extended designator based upon the
  204. * se_device the XCOPY was received upon..
  205. */
  206. memset(&xop->local_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
  207. spc_gen_naa_6h_vendor_specific(local_dev, &xop->local_dev_wwn[0]);
  208. while (start < tdll) {
  209. /*
  210. * Check target descriptor identification with 0xE4 type, and
  211. * compare the current index with the CSCD descriptor IDs in
  212. * the segment descriptor. Use VPD 0x83 WWPN matching ..
  213. */
  214. switch (desc[0]) {
  215. case 0xe4:
  216. rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
  217. &desc[0], cscd_index);
  218. if (rc != 0)
  219. goto out;
  220. start += XCOPY_TARGET_DESC_LEN;
  221. desc += XCOPY_TARGET_DESC_LEN;
  222. cscd_index++;
  223. break;
  224. default:
  225. pr_err("XCOPY unsupported descriptor type code:"
  226. " 0x%02x\n", desc[0]);
  227. *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
  228. goto out;
  229. }
  230. }
  231. switch (xop->op_origin) {
  232. case XCOL_SOURCE_RECV_OP:
  233. rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
  234. xop->dst_tid_wwn,
  235. &xop->dst_dev,
  236. &xop->remote_lun_ref);
  237. break;
  238. case XCOL_DEST_RECV_OP:
  239. rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
  240. xop->src_tid_wwn,
  241. &xop->src_dev,
  242. &xop->remote_lun_ref);
  243. break;
  244. default:
  245. pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
  246. "stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
  247. rc = -EINVAL;
  248. break;
  249. }
  250. /*
  251. * If a matching IEEE NAA 0x83 descriptor for the requested device
  252. * is not located on this node, return COPY_ABORTED with ASQ/ASQC
  253. * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
  254. * initiator to fall back to normal copy method.
  255. */
  256. if (rc < 0) {
  257. *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
  258. goto out;
  259. }
  260. pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
  261. xop->src_dev, &xop->src_tid_wwn[0]);
  262. pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
  263. xop->dst_dev, &xop->dst_tid_wwn[0]);
  264. return cscd_index;
  265. out:
  266. return -EINVAL;
  267. }
  268. static int target_xcopy_parse_segdesc_02(struct xcopy_op *xop, unsigned char *p)
  269. {
  270. unsigned char *desc = p;
  271. int dc = (desc[1] & 0x02);
  272. unsigned short desc_len;
  273. desc_len = get_unaligned_be16(&desc[2]);
  274. if (desc_len != 0x18) {
  275. pr_err("XCOPY segment desc 0x02: Illegal desc_len:"
  276. " %hu\n", desc_len);
  277. return -EINVAL;
  278. }
  279. xop->stdi = get_unaligned_be16(&desc[4]);
  280. xop->dtdi = get_unaligned_be16(&desc[6]);
  281. if (xop->stdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX ||
  282. xop->dtdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX) {
  283. pr_err("XCOPY segment desc 0x02: unsupported CSCD ID > 0x%x; stdi: %hu dtdi: %hu\n",
  284. XCOPY_CSCD_DESC_ID_LIST_OFF_MAX, xop->stdi, xop->dtdi);
  285. return -EINVAL;
  286. }
  287. pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n",
  288. desc_len, xop->stdi, xop->dtdi, dc);
  289. xop->nolb = get_unaligned_be16(&desc[10]);
  290. xop->src_lba = get_unaligned_be64(&desc[12]);
  291. xop->dst_lba = get_unaligned_be64(&desc[20]);
  292. pr_debug("XCOPY seg desc 0x02: nolb: %hu src_lba: %llu dst_lba: %llu\n",
  293. xop->nolb, (unsigned long long)xop->src_lba,
  294. (unsigned long long)xop->dst_lba);
  295. return 0;
  296. }
  297. static int target_xcopy_parse_segment_descriptors(struct xcopy_op *xop,
  298. unsigned char *p, unsigned int sdll,
  299. sense_reason_t *sense_ret)
  300. {
  301. unsigned char *desc = p;
  302. unsigned int start = 0;
  303. int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
  304. *sense_ret = TCM_INVALID_PARAMETER_LIST;
  305. if (offset != 0) {
  306. pr_err("XCOPY segment descriptor list length is not"
  307. " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
  308. *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
  309. return -EINVAL;
  310. }
  311. if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
  312. pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
  313. " large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
  314. /* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
  315. *sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
  316. return -EINVAL;
  317. }
  318. while (start < sdll) {
  319. /*
  320. * Check segment descriptor type code for block -> block
  321. */
  322. switch (desc[0]) {
  323. case 0x02:
  324. rc = target_xcopy_parse_segdesc_02(xop, desc);
  325. if (rc < 0)
  326. goto out;
  327. ret++;
  328. start += XCOPY_SEGMENT_DESC_LEN;
  329. desc += XCOPY_SEGMENT_DESC_LEN;
  330. break;
  331. default:
  332. pr_err("XCOPY unsupported segment descriptor"
  333. "type: 0x%02x\n", desc[0]);
  334. *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
  335. goto out;
  336. }
  337. }
  338. return ret;
  339. out:
  340. return -EINVAL;
  341. }
  342. /*
  343. * Start xcopy_pt ops
  344. */
  345. struct xcopy_pt_cmd {
  346. struct se_cmd se_cmd;
  347. struct completion xpt_passthrough_sem;
  348. unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
  349. };
  350. struct se_portal_group xcopy_pt_tpg;
  351. static struct se_session xcopy_pt_sess;
  352. static struct se_node_acl xcopy_pt_nacl;
  353. static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
  354. {
  355. return 0;
  356. }
  357. static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
  358. {
  359. if (xop->op_origin == XCOL_SOURCE_RECV_OP)
  360. pr_debug("putting dst lun_ref for %p\n", xop->dst_dev);
  361. else
  362. pr_debug("putting src lun_ref for %p\n", xop->src_dev);
  363. percpu_ref_put(xop->remote_lun_ref);
  364. }
  365. static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
  366. {
  367. struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
  368. struct xcopy_pt_cmd, se_cmd);
  369. /* xpt_cmd is on the stack, nothing to free here */
  370. pr_debug("xpt_cmd done: %p\n", xpt_cmd);
  371. }
  372. static int xcopy_pt_check_stop_free(struct se_cmd *se_cmd)
  373. {
  374. struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
  375. struct xcopy_pt_cmd, se_cmd);
  376. complete(&xpt_cmd->xpt_passthrough_sem);
  377. return 0;
  378. }
  379. static int xcopy_pt_write_pending(struct se_cmd *se_cmd)
  380. {
  381. return 0;
  382. }
  383. static int xcopy_pt_queue_data_in(struct se_cmd *se_cmd)
  384. {
  385. return 0;
  386. }
  387. static int xcopy_pt_queue_status(struct se_cmd *se_cmd)
  388. {
  389. return 0;
  390. }
  391. static const struct target_core_fabric_ops xcopy_pt_tfo = {
  392. .fabric_name = "xcopy-pt",
  393. .get_cmd_state = xcopy_pt_get_cmd_state,
  394. .release_cmd = xcopy_pt_release_cmd,
  395. .check_stop_free = xcopy_pt_check_stop_free,
  396. .write_pending = xcopy_pt_write_pending,
  397. .queue_data_in = xcopy_pt_queue_data_in,
  398. .queue_status = xcopy_pt_queue_status,
  399. };
  400. /*
  401. * End xcopy_pt_ops
  402. */
  403. int target_xcopy_setup_pt(void)
  404. {
  405. xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
  406. if (!xcopy_wq) {
  407. pr_err("Unable to allocate xcopy_wq\n");
  408. return -ENOMEM;
  409. }
  410. memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group));
  411. INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list);
  412. INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list);
  413. xcopy_pt_tpg.se_tpg_tfo = &xcopy_pt_tfo;
  414. memset(&xcopy_pt_nacl, 0, sizeof(struct se_node_acl));
  415. INIT_LIST_HEAD(&xcopy_pt_nacl.acl_list);
  416. INIT_LIST_HEAD(&xcopy_pt_nacl.acl_sess_list);
  417. memset(&xcopy_pt_sess, 0, sizeof(struct se_session));
  418. transport_init_session(&xcopy_pt_sess);
  419. xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;
  420. xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;
  421. xcopy_pt_sess.se_tpg = &xcopy_pt_tpg;
  422. xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl;
  423. return 0;
  424. }
  425. void target_xcopy_release_pt(void)
  426. {
  427. if (xcopy_wq)
  428. destroy_workqueue(xcopy_wq);
  429. }
  430. /*
  431. * target_xcopy_setup_pt_cmd - set up a pass-through command
  432. * @xpt_cmd: Data structure to initialize.
  433. * @xop: Describes the XCOPY operation received from an initiator.
  434. * @se_dev: Backend device to associate with @xpt_cmd if
  435. * @remote_port == true.
  436. * @cdb: SCSI CDB to be copied into @xpt_cmd.
  437. * @remote_port: If false, use the LUN through which the XCOPY command has
  438. * been received. If true, use @se_dev->xcopy_lun.
  439. *
  440. * Set up a SCSI command (READ or WRITE) that will be used to execute an
  441. * XCOPY command.
  442. */
  443. static int target_xcopy_setup_pt_cmd(
  444. struct xcopy_pt_cmd *xpt_cmd,
  445. struct xcopy_op *xop,
  446. struct se_device *se_dev,
  447. unsigned char *cdb,
  448. bool remote_port)
  449. {
  450. struct se_cmd *cmd = &xpt_cmd->se_cmd;
  451. /*
  452. * Setup LUN+port to honor reservations based upon xop->op_origin for
  453. * X-COPY PUSH or X-COPY PULL based upon where the CDB was received.
  454. */
  455. if (remote_port) {
  456. cmd->se_lun = &se_dev->xcopy_lun;
  457. cmd->se_dev = se_dev;
  458. } else {
  459. cmd->se_lun = xop->xop_se_cmd->se_lun;
  460. cmd->se_dev = xop->xop_se_cmd->se_dev;
  461. }
  462. cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
  463. if (target_cmd_init_cdb(cmd, cdb, GFP_KERNEL))
  464. return -EINVAL;
  465. cmd->tag = 0;
  466. if (target_cmd_parse_cdb(cmd))
  467. return -EINVAL;
  468. if (transport_generic_map_mem_to_cmd(cmd, xop->xop_data_sg,
  469. xop->xop_data_nents, NULL, 0))
  470. return -EINVAL;
  471. pr_debug("Setup PASSTHROUGH_NOALLOC t_data_sg: %p t_data_nents:"
  472. " %u\n", cmd->t_data_sg, cmd->t_data_nents);
  473. return 0;
  474. }
  475. static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)
  476. {
  477. struct se_cmd *se_cmd = &xpt_cmd->se_cmd;
  478. sense_reason_t sense_rc;
  479. sense_rc = transport_generic_new_cmd(se_cmd);
  480. if (sense_rc)
  481. return -EINVAL;
  482. if (se_cmd->data_direction == DMA_TO_DEVICE)
  483. target_execute_cmd(se_cmd);
  484. wait_for_completion_interruptible(&xpt_cmd->xpt_passthrough_sem);
  485. pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",
  486. se_cmd->scsi_status);
  487. return (se_cmd->scsi_status) ? -EINVAL : 0;
  488. }
  489. static int target_xcopy_read_source(
  490. struct se_cmd *ec_cmd,
  491. struct xcopy_op *xop,
  492. struct se_device *src_dev,
  493. sector_t src_lba,
  494. u32 src_bytes)
  495. {
  496. struct xcopy_pt_cmd xpt_cmd;
  497. struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
  498. u32 transfer_length_block = src_bytes / src_dev->dev_attrib.block_size;
  499. int rc;
  500. unsigned char cdb[16];
  501. bool remote_port = (xop->op_origin == XCOL_DEST_RECV_OP);
  502. memset(&xpt_cmd, 0, sizeof(xpt_cmd));
  503. init_completion(&xpt_cmd.xpt_passthrough_sem);
  504. memset(&cdb[0], 0, 16);
  505. cdb[0] = READ_16;
  506. put_unaligned_be64(src_lba, &cdb[2]);
  507. put_unaligned_be32(transfer_length_block, &cdb[10]);
  508. pr_debug("XCOPY: Built READ_16: LBA: %llu Blocks: %u Length: %u\n",
  509. (unsigned long long)src_lba, transfer_length_block, src_bytes);
  510. __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, src_bytes,
  511. DMA_FROM_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0,
  512. NULL);
  513. rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, src_dev, &cdb[0],
  514. remote_port);
  515. if (rc < 0) {
  516. ec_cmd->scsi_status = se_cmd->scsi_status;
  517. goto out;
  518. }
  519. pr_debug("XCOPY-READ: Saved xop->xop_data_sg: %p, num: %u for READ"
  520. " memory\n", xop->xop_data_sg, xop->xop_data_nents);
  521. rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
  522. if (rc < 0)
  523. ec_cmd->scsi_status = se_cmd->scsi_status;
  524. out:
  525. transport_generic_free_cmd(se_cmd, 0);
  526. return rc;
  527. }
  528. static int target_xcopy_write_destination(
  529. struct se_cmd *ec_cmd,
  530. struct xcopy_op *xop,
  531. struct se_device *dst_dev,
  532. sector_t dst_lba,
  533. u32 dst_bytes)
  534. {
  535. struct xcopy_pt_cmd xpt_cmd;
  536. struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
  537. u32 transfer_length_block = dst_bytes / dst_dev->dev_attrib.block_size;
  538. int rc;
  539. unsigned char cdb[16];
  540. bool remote_port = (xop->op_origin == XCOL_SOURCE_RECV_OP);
  541. memset(&xpt_cmd, 0, sizeof(xpt_cmd));
  542. init_completion(&xpt_cmd.xpt_passthrough_sem);
  543. memset(&cdb[0], 0, 16);
  544. cdb[0] = WRITE_16;
  545. put_unaligned_be64(dst_lba, &cdb[2]);
  546. put_unaligned_be32(transfer_length_block, &cdb[10]);
  547. pr_debug("XCOPY: Built WRITE_16: LBA: %llu Blocks: %u Length: %u\n",
  548. (unsigned long long)dst_lba, transfer_length_block, dst_bytes);
  549. __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, dst_bytes,
  550. DMA_TO_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0,
  551. NULL);
  552. rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, dst_dev, &cdb[0],
  553. remote_port);
  554. if (rc < 0) {
  555. ec_cmd->scsi_status = se_cmd->scsi_status;
  556. goto out;
  557. }
  558. rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
  559. if (rc < 0)
  560. ec_cmd->scsi_status = se_cmd->scsi_status;
  561. out:
  562. transport_generic_free_cmd(se_cmd, 0);
  563. return rc;
  564. }
  565. static void target_xcopy_do_work(struct work_struct *work)
  566. {
  567. struct xcopy_op *xop = container_of(work, struct xcopy_op, xop_work);
  568. struct se_cmd *ec_cmd = xop->xop_se_cmd;
  569. struct se_device *src_dev, *dst_dev;
  570. sector_t src_lba, dst_lba, end_lba;
  571. unsigned long long max_bytes, max_bytes_src, max_bytes_dst, max_blocks;
  572. int rc = 0;
  573. unsigned short nolb;
  574. unsigned int copied_bytes = 0;
  575. sense_reason_t sense_rc;
  576. sense_rc = target_parse_xcopy_cmd(xop);
  577. if (sense_rc != TCM_NO_SENSE)
  578. goto err_free;
  579. if (WARN_ON_ONCE(!xop->src_dev) || WARN_ON_ONCE(!xop->dst_dev)) {
  580. sense_rc = TCM_INVALID_PARAMETER_LIST;
  581. goto err_free;
  582. }
  583. src_dev = xop->src_dev;
  584. dst_dev = xop->dst_dev;
  585. src_lba = xop->src_lba;
  586. dst_lba = xop->dst_lba;
  587. nolb = xop->nolb;
  588. end_lba = src_lba + nolb;
  589. /*
  590. * Break up XCOPY I/O into hw_max_sectors * hw_block_size sized
  591. * I/O based on the smallest max_bytes between src_dev + dst_dev
  592. */
  593. max_bytes_src = (unsigned long long) src_dev->dev_attrib.hw_max_sectors *
  594. src_dev->dev_attrib.hw_block_size;
  595. max_bytes_dst = (unsigned long long) dst_dev->dev_attrib.hw_max_sectors *
  596. dst_dev->dev_attrib.hw_block_size;
  597. max_bytes = min_t(u64, max_bytes_src, max_bytes_dst);
  598. max_bytes = min_t(u64, max_bytes, XCOPY_MAX_BYTES);
  599. /*
  600. * Using shift instead of the division because otherwise GCC
  601. * generates __udivdi3 that is missing on i386
  602. */
  603. max_blocks = max_bytes >> ilog2(src_dev->dev_attrib.block_size);
  604. pr_debug("%s: nolb: %u, max_blocks: %llu end_lba: %llu\n", __func__,
  605. nolb, max_blocks, (unsigned long long)end_lba);
  606. pr_debug("%s: Starting src_lba: %llu, dst_lba: %llu\n", __func__,
  607. (unsigned long long)src_lba, (unsigned long long)dst_lba);
  608. while (nolb) {
  609. u32 cur_bytes = min_t(u64, max_bytes, nolb * src_dev->dev_attrib.block_size);
  610. unsigned short cur_nolb = cur_bytes / src_dev->dev_attrib.block_size;
  611. if (cur_bytes != xop->xop_data_bytes) {
  612. /*
  613. * (Re)allocate a buffer large enough to hold the XCOPY
  614. * I/O size, which can be reused each read / write loop.
  615. */
  616. target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
  617. rc = target_alloc_sgl(&xop->xop_data_sg,
  618. &xop->xop_data_nents,
  619. cur_bytes,
  620. false, false);
  621. if (rc < 0)
  622. goto out;
  623. xop->xop_data_bytes = cur_bytes;
  624. }
  625. pr_debug("%s: Calling read src_dev: %p src_lba: %llu, cur_nolb: %hu\n",
  626. __func__, src_dev, (unsigned long long)src_lba, cur_nolb);
  627. rc = target_xcopy_read_source(ec_cmd, xop, src_dev, src_lba, cur_bytes);
  628. if (rc < 0)
  629. goto out;
  630. src_lba += cur_bytes / src_dev->dev_attrib.block_size;
  631. pr_debug("%s: Incremented READ src_lba to %llu\n", __func__,
  632. (unsigned long long)src_lba);
  633. pr_debug("%s: Calling write dst_dev: %p dst_lba: %llu, cur_nolb: %u\n",
  634. __func__, dst_dev, (unsigned long long)dst_lba, cur_nolb);
  635. rc = target_xcopy_write_destination(ec_cmd, xop, dst_dev,
  636. dst_lba, cur_bytes);
  637. if (rc < 0)
  638. goto out;
  639. dst_lba += cur_bytes / dst_dev->dev_attrib.block_size;
  640. pr_debug("%s: Incremented WRITE dst_lba to %llu\n", __func__,
  641. (unsigned long long)dst_lba);
  642. copied_bytes += cur_bytes;
  643. nolb -= cur_bytes / src_dev->dev_attrib.block_size;
  644. }
  645. xcopy_pt_undepend_remotedev(xop);
  646. target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
  647. kfree(xop);
  648. pr_debug("%s: Final src_lba: %llu, dst_lba: %llu\n", __func__,
  649. (unsigned long long)src_lba, (unsigned long long)dst_lba);
  650. pr_debug("%s: Blocks copied: %u, Bytes Copied: %u\n", __func__,
  651. copied_bytes / dst_dev->dev_attrib.block_size, copied_bytes);
  652. pr_debug("%s: Setting X-COPY GOOD status -> sending response\n", __func__);
  653. target_complete_cmd(ec_cmd, SAM_STAT_GOOD);
  654. return;
  655. out:
  656. /*
  657. * The XCOPY command was aborted after some data was transferred.
  658. * Terminate command with CHECK CONDITION status, with the sense key
  659. * set to COPY ABORTED.
  660. */
  661. sense_rc = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
  662. xcopy_pt_undepend_remotedev(xop);
  663. target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
  664. err_free:
  665. kfree(xop);
  666. pr_warn_ratelimited("%s: rc: %d, sense: %u, XCOPY operation failed\n",
  667. __func__, rc, sense_rc);
  668. target_complete_cmd_with_sense(ec_cmd, SAM_STAT_CHECK_CONDITION, sense_rc);
  669. }
  670. /*
  671. * Returns TCM_NO_SENSE upon success or a sense code != TCM_NO_SENSE if parsing
  672. * fails.
  673. */
  674. static sense_reason_t target_parse_xcopy_cmd(struct xcopy_op *xop)
  675. {
  676. struct se_cmd *se_cmd = xop->xop_se_cmd;
  677. unsigned char *p = NULL, *seg_desc;
  678. unsigned int list_id, list_id_usage, sdll, inline_dl;
  679. sense_reason_t ret = TCM_INVALID_PARAMETER_LIST;
  680. int rc;
  681. unsigned short tdll;
  682. p = transport_kmap_data_sg(se_cmd);
  683. if (!p) {
  684. pr_err("transport_kmap_data_sg() failed in target_do_xcopy\n");
  685. return TCM_OUT_OF_RESOURCES;
  686. }
  687. list_id = p[0];
  688. list_id_usage = (p[1] & 0x18) >> 3;
  689. /*
  690. * Determine TARGET DESCRIPTOR LIST LENGTH + SEGMENT DESCRIPTOR LIST LENGTH
  691. */
  692. tdll = get_unaligned_be16(&p[2]);
  693. sdll = get_unaligned_be32(&p[8]);
  694. if (tdll + sdll > RCR_OP_MAX_DESC_LIST_LEN) {
  695. pr_err("XCOPY descriptor list length %u exceeds maximum %u\n",
  696. tdll + sdll, RCR_OP_MAX_DESC_LIST_LEN);
  697. ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
  698. goto out;
  699. }
  700. inline_dl = get_unaligned_be32(&p[12]);
  701. if (inline_dl != 0) {
  702. pr_err("XCOPY with non zero inline data length\n");
  703. goto out;
  704. }
  705. if (se_cmd->data_length < (XCOPY_HDR_LEN + tdll + sdll + inline_dl)) {
  706. pr_err("XCOPY parameter truncation: data length %u too small "
  707. "for tdll: %hu sdll: %u inline_dl: %u\n",
  708. se_cmd->data_length, tdll, sdll, inline_dl);
  709. ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
  710. goto out;
  711. }
  712. pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
  713. " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
  714. tdll, sdll, inline_dl);
  715. /*
  716. * skip over the target descriptors until segment descriptors
  717. * have been passed - CSCD ids are needed to determine src and dest.
  718. */
  719. seg_desc = &p[16] + tdll;
  720. rc = target_xcopy_parse_segment_descriptors(xop, seg_desc, sdll, &ret);
  721. if (rc <= 0)
  722. goto out;
  723. pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
  724. rc * XCOPY_SEGMENT_DESC_LEN);
  725. rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
  726. if (rc <= 0)
  727. goto out;
  728. if (xop->src_dev->dev_attrib.block_size !=
  729. xop->dst_dev->dev_attrib.block_size) {
  730. pr_err("XCOPY: Non matching src_dev block_size: %u + dst_dev"
  731. " block_size: %u currently unsupported\n",
  732. xop->src_dev->dev_attrib.block_size,
  733. xop->dst_dev->dev_attrib.block_size);
  734. xcopy_pt_undepend_remotedev(xop);
  735. ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  736. goto out;
  737. }
  738. pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
  739. rc * XCOPY_TARGET_DESC_LEN);
  740. transport_kunmap_data_sg(se_cmd);
  741. return TCM_NO_SENSE;
  742. out:
  743. if (p)
  744. transport_kunmap_data_sg(se_cmd);
  745. return ret;
  746. }
  747. sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
  748. {
  749. struct se_device *dev = se_cmd->se_dev;
  750. struct xcopy_op *xop;
  751. unsigned int sa;
  752. if (!dev->dev_attrib.emulate_3pc) {
  753. pr_err("EXTENDED_COPY operation explicitly disabled\n");
  754. return TCM_UNSUPPORTED_SCSI_OPCODE;
  755. }
  756. sa = se_cmd->t_task_cdb[1] & 0x1f;
  757. if (sa != 0x00) {
  758. pr_err("EXTENDED_COPY(LID4) not supported\n");
  759. return TCM_UNSUPPORTED_SCSI_OPCODE;
  760. }
  761. if (se_cmd->data_length == 0) {
  762. target_complete_cmd(se_cmd, SAM_STAT_GOOD);
  763. return TCM_NO_SENSE;
  764. }
  765. if (se_cmd->data_length < XCOPY_HDR_LEN) {
  766. pr_err("XCOPY parameter truncation: length %u < hdr_len %u\n",
  767. se_cmd->data_length, XCOPY_HDR_LEN);
  768. return TCM_PARAMETER_LIST_LENGTH_ERROR;
  769. }
  770. xop = kzalloc_obj(struct xcopy_op);
  771. if (!xop)
  772. goto err;
  773. xop->xop_se_cmd = se_cmd;
  774. INIT_WORK(&xop->xop_work, target_xcopy_do_work);
  775. if (WARN_ON_ONCE(!queue_work(xcopy_wq, &xop->xop_work)))
  776. goto free;
  777. return TCM_NO_SENSE;
  778. free:
  779. kfree(xop);
  780. err:
  781. return TCM_OUT_OF_RESOURCES;
  782. }
  783. static sense_reason_t target_rcr_operating_parameters(struct se_cmd *se_cmd)
  784. {
  785. unsigned char *p;
  786. p = transport_kmap_data_sg(se_cmd);
  787. if (!p) {
  788. pr_err("transport_kmap_data_sg failed in"
  789. " target_rcr_operating_parameters\n");
  790. return TCM_OUT_OF_RESOURCES;
  791. }
  792. if (se_cmd->data_length < 54) {
  793. pr_err("Receive Copy Results Op Parameters length"
  794. " too small: %u\n", se_cmd->data_length);
  795. transport_kunmap_data_sg(se_cmd);
  796. return TCM_INVALID_CDB_FIELD;
  797. }
  798. /*
  799. * Set SNLID=1 (Supports no List ID)
  800. */
  801. p[4] = 0x1;
  802. /*
  803. * MAXIMUM TARGET DESCRIPTOR COUNT
  804. */
  805. put_unaligned_be16(RCR_OP_MAX_TARGET_DESC_COUNT, &p[8]);
  806. /*
  807. * MAXIMUM SEGMENT DESCRIPTOR COUNT
  808. */
  809. put_unaligned_be16(RCR_OP_MAX_SG_DESC_COUNT, &p[10]);
  810. /*
  811. * MAXIMUM DESCRIPTOR LIST LENGTH
  812. */
  813. put_unaligned_be32(RCR_OP_MAX_DESC_LIST_LEN, &p[12]);
  814. /*
  815. * MAXIMUM SEGMENT LENGTH
  816. */
  817. put_unaligned_be32(RCR_OP_MAX_SEGMENT_LEN, &p[16]);
  818. /*
  819. * MAXIMUM INLINE DATA LENGTH for SA 0x04 (NOT SUPPORTED)
  820. */
  821. put_unaligned_be32(0x0, &p[20]);
  822. /*
  823. * HELD DATA LIMIT
  824. */
  825. put_unaligned_be32(0x0, &p[24]);
  826. /*
  827. * MAXIMUM STREAM DEVICE TRANSFER SIZE
  828. */
  829. put_unaligned_be32(0x0, &p[28]);
  830. /*
  831. * TOTAL CONCURRENT COPIES
  832. */
  833. put_unaligned_be16(RCR_OP_TOTAL_CONCURR_COPIES, &p[34]);
  834. /*
  835. * MAXIMUM CONCURRENT COPIES
  836. */
  837. p[36] = RCR_OP_MAX_CONCURR_COPIES;
  838. /*
  839. * DATA SEGMENT GRANULARITY (log 2)
  840. */
  841. p[37] = RCR_OP_DATA_SEG_GRAN_LOG2;
  842. /*
  843. * INLINE DATA GRANULARITY log 2)
  844. */
  845. p[38] = RCR_OP_INLINE_DATA_GRAN_LOG2;
  846. /*
  847. * HELD DATA GRANULARITY
  848. */
  849. p[39] = RCR_OP_HELD_DATA_GRAN_LOG2;
  850. /*
  851. * IMPLEMENTED DESCRIPTOR LIST LENGTH
  852. */
  853. p[43] = 0x2;
  854. /*
  855. * List of implemented descriptor type codes (ordered)
  856. */
  857. p[44] = 0x02; /* Copy Block to Block device */
  858. p[45] = 0xe4; /* Identification descriptor target descriptor */
  859. /*
  860. * AVAILABLE DATA (n-3)
  861. */
  862. put_unaligned_be32(42, &p[0]);
  863. transport_kunmap_data_sg(se_cmd);
  864. target_complete_cmd(se_cmd, SAM_STAT_GOOD);
  865. return TCM_NO_SENSE;
  866. }
  867. sense_reason_t target_do_receive_copy_results(struct se_cmd *se_cmd)
  868. {
  869. unsigned char *cdb = &se_cmd->t_task_cdb[0];
  870. int sa = (cdb[1] & 0x1f), list_id = cdb[2];
  871. struct se_device *dev = se_cmd->se_dev;
  872. sense_reason_t rc = TCM_NO_SENSE;
  873. if (!dev->dev_attrib.emulate_3pc) {
  874. pr_debug("Third-party copy operations explicitly disabled\n");
  875. return TCM_UNSUPPORTED_SCSI_OPCODE;
  876. }
  877. pr_debug("Entering target_do_receive_copy_results: SA: 0x%02x, List ID:"
  878. " 0x%02x, AL: %u\n", sa, list_id, se_cmd->data_length);
  879. if (list_id != 0) {
  880. pr_err("Receive Copy Results with non zero list identifier"
  881. " not supported\n");
  882. return TCM_INVALID_CDB_FIELD;
  883. }
  884. switch (sa) {
  885. case RCR_SA_OPERATING_PARAMETERS:
  886. rc = target_rcr_operating_parameters(se_cmd);
  887. break;
  888. case RCR_SA_COPY_STATUS:
  889. case RCR_SA_RECEIVE_DATA:
  890. case RCR_SA_FAILED_SEGMENT_DETAILS:
  891. default:
  892. pr_err("Unsupported SA for receive copy results: 0x%02x\n", sa);
  893. return TCM_INVALID_CDB_FIELD;
  894. }
  895. return rc;
  896. }