iscsi_target_datain_values.c 14 KB

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