iscsi_target_datain_values.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*******************************************************************************
  3. * This file contains the iSCSI Target DataIN value generation functions.
  4. *
  5. * (c) Copyright 2007-2013 Datera, Inc.
  6. *
  7. * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
  8. *
  9. ******************************************************************************/
  10. #include <linux/slab.h>
  11. #include <scsi/iscsi_proto.h>
  12. #include <target/iscsi/iscsi_target_core.h>
  13. #include "iscsi_target_seq_pdu_list.h"
  14. #include "iscsi_target_erl1.h"
  15. #include "iscsi_target_util.h"
  16. #include "iscsi_target.h"
  17. #include "iscsi_target_datain_values.h"
  18. struct iscsi_datain_req *iscsit_allocate_datain_req(void)
  19. {
  20. struct iscsi_datain_req *dr;
  21. dr = kmem_cache_zalloc(lio_dr_cache, GFP_ATOMIC);
  22. if (!dr) {
  23. pr_err("Unable to allocate memory for"
  24. " struct iscsi_datain_req\n");
  25. return NULL;
  26. }
  27. INIT_LIST_HEAD(&dr->cmd_datain_node);
  28. return dr;
  29. }
  30. void iscsit_attach_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
  31. {
  32. spin_lock(&cmd->datain_lock);
  33. list_add_tail(&dr->cmd_datain_node, &cmd->datain_list);
  34. spin_unlock(&cmd->datain_lock);
  35. }
  36. void iscsit_free_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
  37. {
  38. spin_lock(&cmd->datain_lock);
  39. list_del(&dr->cmd_datain_node);
  40. spin_unlock(&cmd->datain_lock);
  41. kmem_cache_free(lio_dr_cache, dr);
  42. }
  43. void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
  44. {
  45. struct iscsi_datain_req *dr, *dr_tmp;
  46. spin_lock(&cmd->datain_lock);
  47. list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, cmd_datain_node) {
  48. list_del(&dr->cmd_datain_node);
  49. kmem_cache_free(lio_dr_cache, dr);
  50. }
  51. spin_unlock(&cmd->datain_lock);
  52. }
  53. struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *cmd)
  54. {
  55. if (list_empty(&cmd->datain_list)) {
  56. pr_err("cmd->datain_list is empty for ITT:"
  57. " 0x%08x\n", cmd->init_task_tag);
  58. return NULL;
  59. }
  60. return list_first_entry(&cmd->datain_list, struct iscsi_datain_req,
  61. cmd_datain_node);
  62. }
  63. /*
  64. * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
  65. */
  66. static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
  67. struct iscsi_cmd *cmd,
  68. struct iscsi_datain *datain)
  69. {
  70. u32 next_burst_len, read_data_done, read_data_left;
  71. struct iscsi_conn *conn = cmd->conn;
  72. struct iscsi_datain_req *dr;
  73. dr = iscsit_get_datain_req(cmd);
  74. if (!dr)
  75. return NULL;
  76. if (dr->recovery && dr->generate_recovery_values) {
  77. if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
  78. cmd, dr) < 0)
  79. return NULL;
  80. dr->generate_recovery_values = 0;
  81. }
  82. next_burst_len = (!dr->recovery) ?
  83. cmd->next_burst_len : dr->next_burst_len;
  84. read_data_done = (!dr->recovery) ?
  85. cmd->read_data_done : dr->read_data_done;
  86. read_data_left = (cmd->se_cmd.data_length - read_data_done);
  87. if (!read_data_left) {
  88. pr_err("ITT: 0x%08x read_data_left is zero!\n",
  89. cmd->init_task_tag);
  90. return NULL;
  91. }
  92. if ((read_data_left <= conn->conn_ops->MaxRecvDataSegmentLength) &&
  93. (read_data_left <= (conn->sess->sess_ops->MaxBurstLength -
  94. next_burst_len))) {
  95. datain->length = read_data_left;
  96. datain->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
  97. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  98. datain->flags |= ISCSI_FLAG_DATA_ACK;
  99. } else {
  100. if ((next_burst_len +
  101. conn->conn_ops->MaxRecvDataSegmentLength) <
  102. conn->sess->sess_ops->MaxBurstLength) {
  103. datain->length =
  104. conn->conn_ops->MaxRecvDataSegmentLength;
  105. next_burst_len += datain->length;
  106. } else {
  107. datain->length = (conn->sess->sess_ops->MaxBurstLength -
  108. next_burst_len);
  109. next_burst_len = 0;
  110. datain->flags |= ISCSI_FLAG_CMD_FINAL;
  111. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  112. datain->flags |= ISCSI_FLAG_DATA_ACK;
  113. }
  114. }
  115. datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
  116. datain->offset = read_data_done;
  117. if (!dr->recovery) {
  118. cmd->next_burst_len = next_burst_len;
  119. cmd->read_data_done += datain->length;
  120. } else {
  121. dr->next_burst_len = next_burst_len;
  122. dr->read_data_done += datain->length;
  123. }
  124. if (!dr->recovery) {
  125. if (datain->flags & ISCSI_FLAG_DATA_STATUS)
  126. dr->dr_complete = DATAIN_COMPLETE_NORMAL;
  127. return dr;
  128. }
  129. if (!dr->runlength) {
  130. if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
  131. dr->dr_complete =
  132. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  133. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  134. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  135. }
  136. } else {
  137. if ((dr->begrun + dr->runlength) == dr->data_sn) {
  138. dr->dr_complete =
  139. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  140. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  141. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  142. }
  143. }
  144. return dr;
  145. }
  146. /*
  147. * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
  148. */
  149. static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
  150. struct iscsi_cmd *cmd,
  151. struct iscsi_datain *datain)
  152. {
  153. u32 offset, read_data_done, read_data_left, seq_send_order;
  154. struct iscsi_conn *conn = cmd->conn;
  155. struct iscsi_datain_req *dr;
  156. struct iscsi_seq *seq;
  157. dr = iscsit_get_datain_req(cmd);
  158. if (!dr)
  159. return NULL;
  160. if (dr->recovery && dr->generate_recovery_values) {
  161. if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
  162. cmd, dr) < 0)
  163. return NULL;
  164. dr->generate_recovery_values = 0;
  165. }
  166. read_data_done = (!dr->recovery) ?
  167. cmd->read_data_done : dr->read_data_done;
  168. seq_send_order = (!dr->recovery) ?
  169. cmd->seq_send_order : dr->seq_send_order;
  170. read_data_left = (cmd->se_cmd.data_length - read_data_done);
  171. if (!read_data_left) {
  172. pr_err("ITT: 0x%08x read_data_left is zero!\n",
  173. cmd->init_task_tag);
  174. return NULL;
  175. }
  176. seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
  177. if (!seq)
  178. return NULL;
  179. seq->sent = 1;
  180. if (!dr->recovery && !seq->next_burst_len)
  181. seq->first_datasn = cmd->data_sn;
  182. offset = (seq->offset + seq->next_burst_len);
  183. if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
  184. cmd->se_cmd.data_length) {
  185. datain->length = (cmd->se_cmd.data_length - offset);
  186. datain->offset = offset;
  187. datain->flags |= ISCSI_FLAG_CMD_FINAL;
  188. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  189. datain->flags |= ISCSI_FLAG_DATA_ACK;
  190. seq->next_burst_len = 0;
  191. seq_send_order++;
  192. } else {
  193. if ((seq->next_burst_len +
  194. conn->conn_ops->MaxRecvDataSegmentLength) <
  195. conn->sess->sess_ops->MaxBurstLength) {
  196. datain->length =
  197. conn->conn_ops->MaxRecvDataSegmentLength;
  198. datain->offset = (seq->offset + seq->next_burst_len);
  199. seq->next_burst_len += datain->length;
  200. } else {
  201. datain->length = (conn->sess->sess_ops->MaxBurstLength -
  202. seq->next_burst_len);
  203. datain->offset = (seq->offset + seq->next_burst_len);
  204. datain->flags |= ISCSI_FLAG_CMD_FINAL;
  205. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  206. datain->flags |= ISCSI_FLAG_DATA_ACK;
  207. seq->next_burst_len = 0;
  208. seq_send_order++;
  209. }
  210. }
  211. if ((read_data_done + datain->length) == cmd->se_cmd.data_length)
  212. datain->flags |= ISCSI_FLAG_DATA_STATUS;
  213. datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
  214. if (!dr->recovery) {
  215. cmd->seq_send_order = seq_send_order;
  216. cmd->read_data_done += datain->length;
  217. } else {
  218. dr->seq_send_order = seq_send_order;
  219. dr->read_data_done += datain->length;
  220. }
  221. if (!dr->recovery) {
  222. if (datain->flags & ISCSI_FLAG_CMD_FINAL)
  223. seq->last_datasn = datain->data_sn;
  224. if (datain->flags & ISCSI_FLAG_DATA_STATUS)
  225. dr->dr_complete = DATAIN_COMPLETE_NORMAL;
  226. return dr;
  227. }
  228. if (!dr->runlength) {
  229. if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
  230. dr->dr_complete =
  231. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  232. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  233. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  234. }
  235. } else {
  236. if ((dr->begrun + dr->runlength) == dr->data_sn) {
  237. dr->dr_complete =
  238. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  239. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  240. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  241. }
  242. }
  243. return dr;
  244. }
  245. /*
  246. * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
  247. */
  248. static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
  249. struct iscsi_cmd *cmd,
  250. struct iscsi_datain *datain)
  251. {
  252. u32 next_burst_len, read_data_done, read_data_left;
  253. struct iscsi_conn *conn = cmd->conn;
  254. struct iscsi_datain_req *dr;
  255. struct iscsi_pdu *pdu;
  256. dr = iscsit_get_datain_req(cmd);
  257. if (!dr)
  258. return NULL;
  259. if (dr->recovery && dr->generate_recovery_values) {
  260. if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
  261. cmd, dr) < 0)
  262. return NULL;
  263. dr->generate_recovery_values = 0;
  264. }
  265. next_burst_len = (!dr->recovery) ?
  266. cmd->next_burst_len : dr->next_burst_len;
  267. read_data_done = (!dr->recovery) ?
  268. cmd->read_data_done : dr->read_data_done;
  269. read_data_left = (cmd->se_cmd.data_length - read_data_done);
  270. if (!read_data_left) {
  271. pr_err("ITT: 0x%08x read_data_left is zero!\n",
  272. cmd->init_task_tag);
  273. return dr;
  274. }
  275. pdu = iscsit_get_pdu_holder_for_seq(cmd, NULL);
  276. if (!pdu)
  277. return dr;
  278. if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) {
  279. pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
  280. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  281. pdu->flags |= ISCSI_FLAG_DATA_ACK;
  282. next_burst_len = 0;
  283. } else {
  284. if ((next_burst_len + conn->conn_ops->MaxRecvDataSegmentLength) <
  285. conn->sess->sess_ops->MaxBurstLength)
  286. next_burst_len += pdu->length;
  287. else {
  288. pdu->flags |= ISCSI_FLAG_CMD_FINAL;
  289. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  290. pdu->flags |= ISCSI_FLAG_DATA_ACK;
  291. next_burst_len = 0;
  292. }
  293. }
  294. pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
  295. if (!dr->recovery) {
  296. cmd->next_burst_len = next_burst_len;
  297. cmd->read_data_done += pdu->length;
  298. } else {
  299. dr->next_burst_len = next_burst_len;
  300. dr->read_data_done += pdu->length;
  301. }
  302. datain->flags = pdu->flags;
  303. datain->length = pdu->length;
  304. datain->offset = pdu->offset;
  305. datain->data_sn = pdu->data_sn;
  306. if (!dr->recovery) {
  307. if (datain->flags & ISCSI_FLAG_DATA_STATUS)
  308. dr->dr_complete = DATAIN_COMPLETE_NORMAL;
  309. return dr;
  310. }
  311. if (!dr->runlength) {
  312. if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
  313. dr->dr_complete =
  314. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  315. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  316. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  317. }
  318. } else {
  319. if ((dr->begrun + dr->runlength) == dr->data_sn) {
  320. dr->dr_complete =
  321. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  322. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  323. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  324. }
  325. }
  326. return dr;
  327. }
  328. /*
  329. * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
  330. */
  331. static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
  332. struct iscsi_cmd *cmd,
  333. struct iscsi_datain *datain)
  334. {
  335. u32 read_data_done, read_data_left, seq_send_order;
  336. struct iscsi_conn *conn = cmd->conn;
  337. struct iscsi_datain_req *dr;
  338. struct iscsi_pdu *pdu;
  339. struct iscsi_seq *seq = NULL;
  340. dr = iscsit_get_datain_req(cmd);
  341. if (!dr)
  342. return NULL;
  343. if (dr->recovery && dr->generate_recovery_values) {
  344. if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
  345. cmd, dr) < 0)
  346. return NULL;
  347. dr->generate_recovery_values = 0;
  348. }
  349. read_data_done = (!dr->recovery) ?
  350. cmd->read_data_done : dr->read_data_done;
  351. seq_send_order = (!dr->recovery) ?
  352. cmd->seq_send_order : dr->seq_send_order;
  353. read_data_left = (cmd->se_cmd.data_length - read_data_done);
  354. if (!read_data_left) {
  355. pr_err("ITT: 0x%08x read_data_left is zero!\n",
  356. cmd->init_task_tag);
  357. return NULL;
  358. }
  359. seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
  360. if (!seq)
  361. return NULL;
  362. seq->sent = 1;
  363. if (!dr->recovery && !seq->next_burst_len)
  364. seq->first_datasn = cmd->data_sn;
  365. pdu = iscsit_get_pdu_holder_for_seq(cmd, seq);
  366. if (!pdu)
  367. return NULL;
  368. if (seq->pdu_send_order == seq->pdu_count) {
  369. pdu->flags |= ISCSI_FLAG_CMD_FINAL;
  370. if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
  371. pdu->flags |= ISCSI_FLAG_DATA_ACK;
  372. seq->next_burst_len = 0;
  373. seq_send_order++;
  374. } else
  375. seq->next_burst_len += pdu->length;
  376. if ((read_data_done + pdu->length) == cmd->se_cmd.data_length)
  377. pdu->flags |= ISCSI_FLAG_DATA_STATUS;
  378. pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
  379. if (!dr->recovery) {
  380. cmd->seq_send_order = seq_send_order;
  381. cmd->read_data_done += pdu->length;
  382. } else {
  383. dr->seq_send_order = seq_send_order;
  384. dr->read_data_done += pdu->length;
  385. }
  386. datain->flags = pdu->flags;
  387. datain->length = pdu->length;
  388. datain->offset = pdu->offset;
  389. datain->data_sn = pdu->data_sn;
  390. if (!dr->recovery) {
  391. if (datain->flags & ISCSI_FLAG_CMD_FINAL)
  392. seq->last_datasn = datain->data_sn;
  393. if (datain->flags & ISCSI_FLAG_DATA_STATUS)
  394. dr->dr_complete = DATAIN_COMPLETE_NORMAL;
  395. return dr;
  396. }
  397. if (!dr->runlength) {
  398. if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
  399. dr->dr_complete =
  400. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  401. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  402. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  403. }
  404. } else {
  405. if ((dr->begrun + dr->runlength) == dr->data_sn) {
  406. dr->dr_complete =
  407. (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
  408. DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
  409. DATAIN_COMPLETE_CONNECTION_RECOVERY;
  410. }
  411. }
  412. return dr;
  413. }
  414. struct iscsi_datain_req *iscsit_get_datain_values(
  415. struct iscsi_cmd *cmd,
  416. struct iscsi_datain *datain)
  417. {
  418. struct iscsi_conn *conn = cmd->conn;
  419. if (conn->sess->sess_ops->DataSequenceInOrder &&
  420. conn->sess->sess_ops->DataPDUInOrder)
  421. return iscsit_set_datain_values_yes_and_yes(cmd, datain);
  422. else if (!conn->sess->sess_ops->DataSequenceInOrder &&
  423. conn->sess->sess_ops->DataPDUInOrder)
  424. return iscsit_set_datain_values_no_and_yes(cmd, datain);
  425. else if (conn->sess->sess_ops->DataSequenceInOrder &&
  426. !conn->sess->sess_ops->DataPDUInOrder)
  427. return iscsit_set_datain_values_yes_and_no(cmd, datain);
  428. else if (!conn->sess->sess_ops->DataSequenceInOrder &&
  429. !conn->sess->sess_ops->DataPDUInOrder)
  430. return iscsit_set_datain_values_no_and_no(cmd, datain);
  431. return NULL;
  432. }
  433. EXPORT_SYMBOL(iscsit_get_datain_values);