Blame view
drivers/scsi/libiscsi.c
90.6 KB
7996a778f [SCSI] iscsi: add... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * iSCSI lib functions * * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004 - 2006 Mike Christie * Copyright (C) 2004 - 2005 Dmitry Yusupov * Copyright (C) 2004 - 2005 Alex Aizman * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/types.h> |
7996a778f [SCSI] iscsi: add... |
25 26 |
#include <linux/kfifo.h> #include <linux/delay.h> |
118365721 [SCSI] libiscsi: ... |
27 |
#include <linux/log2.h> |
5a0e3ad6a include cleanup: ... |
28 |
#include <linux/slab.h> |
acf3368ff scsi: Fix up file... |
29 |
#include <linux/module.h> |
8eb00539d [SCSI] libiscsi: ... |
30 |
#include <asm/unaligned.h> |
7996a778f [SCSI] iscsi: add... |
31 32 33 34 35 36 37 38 39 40 41 |
#include <net/tcp.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_tcq.h> #include <scsi/scsi_host.h> #include <scsi/scsi.h> #include <scsi/iscsi_proto.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_iscsi.h> #include <scsi/libiscsi.h> |
bd2199d41 libiscsi: add con... |
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
static int iscsi_dbg_lib_conn; module_param_named(debug_libiscsi_conn, iscsi_dbg_lib_conn, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug_libiscsi_conn, "Turn on debugging for connections in libiscsi module. " "Set to 1 to turn on, and zero to turn off. Default is off."); static int iscsi_dbg_lib_session; module_param_named(debug_libiscsi_session, iscsi_dbg_lib_session, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug_libiscsi_session, "Turn on debugging for sessions in libiscsi module. " "Set to 1 to turn on, and zero to turn off. Default is off."); static int iscsi_dbg_lib_eh; module_param_named(debug_libiscsi_eh, iscsi_dbg_lib_eh, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug_libiscsi_eh, "Turn on debugging for error handling in libiscsi module. " "Set to 1 to turn on, and zero to turn off. Default is off."); |
1b2c7af87 [SCSI] libiscsi: ... |
62 63 64 |
#define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \ do { \ |
bd2199d41 libiscsi: add con... |
65 |
if (iscsi_dbg_lib_conn) \ |
1b2c7af87 [SCSI] libiscsi: ... |
66 67 68 69 70 71 72 |
iscsi_conn_printk(KERN_INFO, _conn, \ "%s " dbg_fmt, \ __func__, ##arg); \ } while (0); #define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \ do { \ |
bd2199d41 libiscsi: add con... |
73 74 75 76 77 78 79 80 81 |
if (iscsi_dbg_lib_session) \ iscsi_session_printk(KERN_INFO, _session, \ "%s " dbg_fmt, \ __func__, ##arg); \ } while (0); #define ISCSI_DBG_EH(_session, dbg_fmt, arg...) \ do { \ if (iscsi_dbg_lib_eh) \ |
1b2c7af87 [SCSI] libiscsi: ... |
82 83 84 85 |
iscsi_session_printk(KERN_INFO, _session, \ "%s " dbg_fmt, \ __func__, ##arg); \ } while (0); |
32ae763e3 [SCSI] iscsi lib:... |
86 87 88 89 |
inline void iscsi_conn_queue_work(struct iscsi_conn *conn) { struct Scsi_Host *shost = conn->session->host; struct iscsi_host *ihost = shost_priv(shost); |
1336aed10 [SCSI] libiscsi: ... |
90 91 |
if (ihost->workq) queue_work(ihost->workq, &conn->xmitwork); |
32ae763e3 [SCSI] iscsi lib:... |
92 93 |
} EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); |
4c0ba5d25 [SCSI] libiscsi: ... |
94 95 |
static void __iscsi_update_cmdsn(struct iscsi_session *session, uint32_t exp_cmdsn, uint32_t max_cmdsn) |
7996a778f [SCSI] iscsi: add... |
96 |
{ |
77a23c21a [SCSI] libiscsi: ... |
97 98 99 100 101 102 103 104 105 |
/* * standard specifies this check for when to update expected and * max sequence numbers */ if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1)) return; if (exp_cmdsn != session->exp_cmdsn && !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn)) |
7996a778f [SCSI] iscsi: add... |
106 |
session->exp_cmdsn = exp_cmdsn; |
77a23c21a [SCSI] libiscsi: ... |
107 108 109 110 111 112 113 |
if (max_cmdsn != session->max_cmdsn && !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) { session->max_cmdsn = max_cmdsn; /* * if the window closed with IO queued, then kick the * xmit thread */ |
3bbaaad95 [SCSI] libiscsi: ... |
114 |
if (!list_empty(&session->leadconn->cmdqueue) || |
1336aed10 [SCSI] libiscsi: ... |
115 116 |
!list_empty(&session->leadconn->mgmtqueue)) iscsi_conn_queue_work(session->leadconn); |
77a23c21a [SCSI] libiscsi: ... |
117 |
} |
7996a778f [SCSI] iscsi: add... |
118 |
} |
4c0ba5d25 [SCSI] libiscsi: ... |
119 120 121 122 123 124 |
void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) { __iscsi_update_cmdsn(session, be32_to_cpu(hdr->exp_cmdsn), be32_to_cpu(hdr->max_cmdsn)); } |
77a23c21a [SCSI] libiscsi: ... |
125 |
EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
7996a778f [SCSI] iscsi: add... |
126 |
|
577577da6 [SCSI] libiscsi: ... |
127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
/** * iscsi_prep_data_out_pdu - initialize Data-Out * @task: scsi command task * @r2t: R2T info * @hdr: iscsi data in pdu * * Notes: * Initialize Data-Out within this R2T sequence and finds * proper data_offset within this SCSI command. * * This function is called with connection lock taken. **/ void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t, struct iscsi_data *hdr) |
7996a778f [SCSI] iscsi: add... |
141 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
142 |
struct iscsi_conn *conn = task->conn; |
577577da6 [SCSI] libiscsi: ... |
143 144 145 |
unsigned int left = r2t->data_length - r2t->sent; task->hdr_len = sizeof(struct iscsi_data); |
7996a778f [SCSI] iscsi: add... |
146 147 |
memset(hdr, 0, sizeof(struct iscsi_data)); |
577577da6 [SCSI] libiscsi: ... |
148 149 150 |
hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->datasn); r2t->datasn++; |
7996a778f [SCSI] iscsi: add... |
151 |
hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; |
55bdabdf4 iscsi: Use struct... |
152 |
hdr->lun = task->lun; |
577577da6 [SCSI] libiscsi: ... |
153 154 155 156 |
hdr->itt = task->hdr_itt; hdr->exp_statsn = r2t->exp_statsn; hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent); if (left > conn->max_xmit_dlength) { |
7996a778f [SCSI] iscsi: add... |
157 |
hton24(hdr->dlength, conn->max_xmit_dlength); |
577577da6 [SCSI] libiscsi: ... |
158 |
r2t->data_count = conn->max_xmit_dlength; |
7996a778f [SCSI] iscsi: add... |
159 160 |
hdr->flags = 0; } else { |
577577da6 [SCSI] libiscsi: ... |
161 162 |
hton24(hdr->dlength, left); r2t->data_count = left; |
7996a778f [SCSI] iscsi: add... |
163 164 |
hdr->flags = ISCSI_FLAG_CMD_FINAL; } |
577577da6 [SCSI] libiscsi: ... |
165 |
conn->dataout_pdus_cnt++; |
7996a778f [SCSI] iscsi: add... |
166 |
} |
577577da6 [SCSI] libiscsi: ... |
167 |
EXPORT_SYMBOL_GPL(iscsi_prep_data_out_pdu); |
7996a778f [SCSI] iscsi: add... |
168 |
|
9c19a7d03 [SCSI] libiscsi: ... |
169 |
static int iscsi_add_hdr(struct iscsi_task *task, unsigned len) |
004d6530f [SCSI] iscsi_tcp,... |
170 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
171 |
unsigned exp_len = task->hdr_len + len; |
004d6530f [SCSI] iscsi_tcp,... |
172 |
|
9c19a7d03 [SCSI] libiscsi: ... |
173 |
if (exp_len > task->hdr_max) { |
004d6530f [SCSI] iscsi_tcp,... |
174 175 176 177 178 |
WARN_ON(1); return -EINVAL; } WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */ |
9c19a7d03 [SCSI] libiscsi: ... |
179 |
task->hdr_len = exp_len; |
004d6530f [SCSI] iscsi_tcp,... |
180 181 |
return 0; } |
38d1c069d [SCSI] iscsi: ext... |
182 183 184 |
/* * make an extended cdb AHS */ |
9c19a7d03 [SCSI] libiscsi: ... |
185 |
static int iscsi_prep_ecdb_ahs(struct iscsi_task *task) |
38d1c069d [SCSI] iscsi: ext... |
186 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
187 |
struct scsi_cmnd *cmd = task->sc; |
38d1c069d [SCSI] iscsi: ext... |
188 189 190 191 |
unsigned rlen, pad_len; unsigned short ahslength; struct iscsi_ecdb_ahdr *ecdb_ahdr; int rc; |
9c19a7d03 [SCSI] libiscsi: ... |
192 |
ecdb_ahdr = iscsi_next_hdr(task); |
38d1c069d [SCSI] iscsi: ext... |
193 194 195 196 197 198 |
rlen = cmd->cmd_len - ISCSI_CDB_SIZE; BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb)); ahslength = rlen + sizeof(ecdb_ahdr->reserved); pad_len = iscsi_padding(rlen); |
9c19a7d03 [SCSI] libiscsi: ... |
199 |
rc = iscsi_add_hdr(task, sizeof(ecdb_ahdr->ahslength) + |
38d1c069d [SCSI] iscsi: ext... |
200 201 202 203 204 205 206 207 208 209 210 |
sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len); if (rc) return rc; if (pad_len) memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len); ecdb_ahdr->ahslength = cpu_to_be16(ahslength); ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB; ecdb_ahdr->reserved = 0; memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen); |
1b2c7af87 [SCSI] libiscsi: ... |
211 212 213 214 215 216 |
ISCSI_DBG_SESSION(task->conn->session, "iscsi_prep_ecdb_ahs: varlen_cdb_len %d " "rlen %d pad_len %d ahs_length %d iscsi_headers_size " "%u ", cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len); |
38d1c069d [SCSI] iscsi: ext... |
217 218 |
return 0; } |
9c19a7d03 [SCSI] libiscsi: ... |
219 |
static int iscsi_prep_bidi_ahs(struct iscsi_task *task) |
c07d44440 [SCSI] iscsi: bid... |
220 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
221 |
struct scsi_cmnd *sc = task->sc; |
c07d44440 [SCSI] iscsi: bid... |
222 223 |
struct iscsi_rlength_ahdr *rlen_ahdr; int rc; |
9c19a7d03 [SCSI] libiscsi: ... |
224 225 |
rlen_ahdr = iscsi_next_hdr(task); rc = iscsi_add_hdr(task, sizeof(*rlen_ahdr)); |
c07d44440 [SCSI] iscsi: bid... |
226 227 228 229 230 231 232 233 234 |
if (rc) return rc; rlen_ahdr->ahslength = cpu_to_be16(sizeof(rlen_ahdr->read_length) + sizeof(rlen_ahdr->reserved)); rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH; rlen_ahdr->reserved = 0; rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length); |
1b2c7af87 [SCSI] libiscsi: ... |
235 236 237 238 239 240 |
ISCSI_DBG_SESSION(task->conn->session, "bidi-in rlen_ahdr->read_length(%d) " "rlen_ahdr->ahslength(%d) ", be32_to_cpu(rlen_ahdr->read_length), be16_to_cpu(rlen_ahdr->ahslength)); |
c07d44440 [SCSI] iscsi: bid... |
241 242 |
return 0; } |
7996a778f [SCSI] iscsi: add... |
243 |
/** |
5d12c05e2 [SCSI] libiscsi: ... |
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
* iscsi_check_tmf_restrictions - check if a task is affected by TMF * @task: iscsi task * @opcode: opcode to check for * * During TMF a task has to be checked if it's affected. * All unrelated I/O can be passed through, but I/O to the * affected LUN should be restricted. * If 'fast_abort' is set we won't be sending any I/O to the * affected LUN. * Otherwise the target is waiting for all TTTs to be completed, * so we have to send all outstanding Data-Out PDUs to the target. */ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { struct iscsi_conn *conn = task->conn; struct iscsi_tm *tmf = &conn->tmhdr; unsigned int hdr_lun; if (conn->tmf_state == TMF_INITIAL) return 0; if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) return 0; switch (ISCSI_TM_FUNC_VALUE(tmf)) { case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: /* * Allow PDUs for unrelated LUNs */ |
55bdabdf4 iscsi: Use struct... |
273 |
hdr_lun = scsilun_to_int(&tmf->lun); |
5d12c05e2 [SCSI] libiscsi: ... |
274 275 |
if (hdr_lun != task->sc->device->lun) return 0; |
3fe5ae8b4 [SCSI] libiscsi: ... |
276 277 |
/* fall through */ case ISCSI_TM_FUNC_TARGET_WARM_RESET: |
5d12c05e2 [SCSI] libiscsi: ... |
278 279 280 281 282 283 |
/* * Fail all SCSI cmd PDUs */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { iscsi_conn_printk(KERN_INFO, conn, "task [op %x/%x itt " |
3fe5ae8b4 [SCSI] libiscsi: ... |
284 |
"0x%x/0x%x] " |
5d12c05e2 [SCSI] libiscsi: ... |
285 286 287 |
"rejected. ", task->hdr->opcode, opcode, |
3fe5ae8b4 [SCSI] libiscsi: ... |
288 |
task->itt, task->hdr_itt); |
5d12c05e2 [SCSI] libiscsi: ... |
289 290 291 292 293 294 295 296 297 |
return -EACCES; } /* * And also all data-out PDUs in response to R2T * if fast_abort is set. */ if (conn->session->fast_abort) { iscsi_conn_printk(KERN_INFO, conn, "task [op %x/%x itt " |
3fe5ae8b4 [SCSI] libiscsi: ... |
298 299 |
"0x%x/0x%x] fast abort. ", |
5d12c05e2 [SCSI] libiscsi: ... |
300 |
task->hdr->opcode, opcode, |
3fe5ae8b4 [SCSI] libiscsi: ... |
301 |
task->itt, task->hdr_itt); |
5d12c05e2 [SCSI] libiscsi: ... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
return -EACCES; } break; case ISCSI_TM_FUNC_ABORT_TASK: /* * the caller has already checked if the task * they want to abort was in the pending queue so if * we are here the cmd pdu has gone out already, and * we will only hit this for data-outs */ if (opcode == ISCSI_OP_SCSI_DATA_OUT && task->hdr_itt == tmf->rtt) { ISCSI_DBG_SESSION(conn->session, "Preventing task %x/%x from sending " "data-out due to abort task in " "progress ", task->itt, task->hdr_itt); return -EACCES; } break; } return 0; } /** |
7996a778f [SCSI] iscsi: add... |
329 |
* iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu |
9c19a7d03 [SCSI] libiscsi: ... |
330 |
* @task: iscsi task |
7996a778f [SCSI] iscsi: add... |
331 332 333 334 |
* * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set * fields like dlength or final based on how much data it sends */ |
9c19a7d03 [SCSI] libiscsi: ... |
335 |
static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) |
7996a778f [SCSI] iscsi: add... |
336 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
337 |
struct iscsi_conn *conn = task->conn; |
7996a778f [SCSI] iscsi: add... |
338 |
struct iscsi_session *session = conn->session; |
9c19a7d03 [SCSI] libiscsi: ... |
339 |
struct scsi_cmnd *sc = task->sc; |
123521830 iscsi: Resolve is... |
340 |
struct iscsi_scsi_req *hdr; |
38d1c069d [SCSI] iscsi: ext... |
341 |
unsigned hdrlength, cmd_len; |
262ef6362 [SCSI] libiscsi: ... |
342 |
itt_t itt; |
004d6530f [SCSI] iscsi_tcp,... |
343 |
int rc; |
7996a778f [SCSI] iscsi: add... |
344 |
|
5d12c05e2 [SCSI] libiscsi: ... |
345 346 347 |
rc = iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_CMD); if (rc) return rc; |
184b57c63 [SCSI] libiscsi: ... |
348 349 350 351 352 |
if (conn->session->tt->alloc_pdu) { rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); if (rc) return rc; } |
123521830 iscsi: Resolve is... |
353 |
hdr = (struct iscsi_scsi_req *)task->hdr; |
262ef6362 [SCSI] libiscsi: ... |
354 |
itt = hdr->itt; |
577577da6 [SCSI] libiscsi: ... |
355 |
memset(hdr, 0, sizeof(*hdr)); |
2ff79d52d [SCSI] libiscsi: ... |
356 357 358 359 360 |
if (session->tt->parse_pdu_itt) hdr->itt = task->hdr_itt = itt; else hdr->itt = task->hdr_itt = build_itt(task->itt, task->conn->session->age); |
9c19a7d03 [SCSI] libiscsi: ... |
361 362 |
task->hdr_len = 0; rc = iscsi_add_hdr(task, sizeof(*hdr)); |
004d6530f [SCSI] iscsi_tcp,... |
363 364 |
if (rc) return rc; |
a8ac6311c [SCSI] iscsi: con... |
365 366 |
hdr->opcode = ISCSI_OP_SCSI_CMD; hdr->flags = ISCSI_ATTR_SIMPLE; |
55bdabdf4 iscsi: Use struct... |
367 368 |
int_to_scsilun(sc->device->lun, &hdr->lun); task->lun = hdr->lun; |
a8ac6311c [SCSI] iscsi: con... |
369 |
hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
38d1c069d [SCSI] iscsi: ext... |
370 371 372 373 |
cmd_len = sc->cmd_len; if (cmd_len < ISCSI_CDB_SIZE) memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len); else if (cmd_len > ISCSI_CDB_SIZE) { |
9c19a7d03 [SCSI] libiscsi: ... |
374 |
rc = iscsi_prep_ecdb_ahs(task); |
38d1c069d [SCSI] iscsi: ext... |
375 376 377 378 379 |
if (rc) return rc; cmd_len = ISCSI_CDB_SIZE; } memcpy(hdr->cdb, sc->cmnd, cmd_len); |
7996a778f [SCSI] iscsi: add... |
380 |
|
9c19a7d03 [SCSI] libiscsi: ... |
381 |
task->imm_count = 0; |
c07d44440 [SCSI] iscsi: bid... |
382 383 |
if (scsi_bidi_cmnd(sc)) { hdr->flags |= ISCSI_FLAG_CMD_READ; |
9c19a7d03 [SCSI] libiscsi: ... |
384 |
rc = iscsi_prep_bidi_ahs(task); |
c07d44440 [SCSI] iscsi: bid... |
385 386 387 |
if (rc) return rc; } |
7996a778f [SCSI] iscsi: add... |
388 |
if (sc->sc_data_direction == DMA_TO_DEVICE) { |
c07d44440 [SCSI] iscsi: bid... |
389 |
unsigned out_len = scsi_out(sc)->length; |
577577da6 [SCSI] libiscsi: ... |
390 |
struct iscsi_r2t_info *r2t = &task->unsol_r2t; |
c07d44440 [SCSI] iscsi: bid... |
391 |
hdr->data_length = cpu_to_be32(out_len); |
7996a778f [SCSI] iscsi: add... |
392 393 394 395 396 397 398 399 400 401 402 |
hdr->flags |= ISCSI_FLAG_CMD_WRITE; /* * Write counters: * * imm_count bytes to be sent right after * SCSI PDU Header * * unsol_count bytes(as Data-Out) to be sent * without R2T ack right after * immediate data * |
577577da6 [SCSI] libiscsi: ... |
403 |
* r2t data_length bytes to be sent via R2T ack's |
7996a778f [SCSI] iscsi: add... |
404 405 406 |
* * pad_count bytes to be sent as zero-padding */ |
577577da6 [SCSI] libiscsi: ... |
407 |
memset(r2t, 0, sizeof(*r2t)); |
7996a778f [SCSI] iscsi: add... |
408 409 |
if (session->imm_data_en) { |
c07d44440 [SCSI] iscsi: bid... |
410 |
if (out_len >= session->first_burst) |
9c19a7d03 [SCSI] libiscsi: ... |
411 |
task->imm_count = min(session->first_burst, |
7996a778f [SCSI] iscsi: add... |
412 413 |
conn->max_xmit_dlength); else |
9c19a7d03 [SCSI] libiscsi: ... |
414 |
task->imm_count = min(out_len, |
7996a778f [SCSI] iscsi: add... |
415 |
conn->max_xmit_dlength); |
9c19a7d03 [SCSI] libiscsi: ... |
416 |
hton24(hdr->dlength, task->imm_count); |
7996a778f [SCSI] iscsi: add... |
417 |
} else |
a8ac6311c [SCSI] iscsi: con... |
418 |
zero_data(hdr->dlength); |
7996a778f [SCSI] iscsi: add... |
419 |
|
ffd0436ed [SCSI] libiscsi, ... |
420 |
if (!session->initial_r2t_en) { |
577577da6 [SCSI] libiscsi: ... |
421 422 423 424 425 |
r2t->data_length = min(session->first_burst, out_len) - task->imm_count; r2t->data_offset = task->imm_count; r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); r2t->exp_statsn = cpu_to_be32(conn->exp_statsn); |
ffd0436ed [SCSI] libiscsi, ... |
426 |
} |
577577da6 [SCSI] libiscsi: ... |
427 |
if (!task->unsol_r2t.data_length) |
7996a778f [SCSI] iscsi: add... |
428 |
/* No unsolicit Data-Out's */ |
a8ac6311c [SCSI] iscsi: con... |
429 |
hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
7996a778f [SCSI] iscsi: add... |
430 |
} else { |
7996a778f [SCSI] iscsi: add... |
431 432 |
hdr->flags |= ISCSI_FLAG_CMD_FINAL; zero_data(hdr->dlength); |
c07d44440 [SCSI] iscsi: bid... |
433 |
hdr->data_length = cpu_to_be32(scsi_in(sc)->length); |
7996a778f [SCSI] iscsi: add... |
434 435 436 437 |
if (sc->sc_data_direction == DMA_FROM_DEVICE) hdr->flags |= ISCSI_FLAG_CMD_READ; } |
004d6530f [SCSI] iscsi_tcp,... |
438 |
/* calculate size of additional header segments (AHSs) */ |
9c19a7d03 [SCSI] libiscsi: ... |
439 |
hdrlength = task->hdr_len - sizeof(*hdr); |
004d6530f [SCSI] iscsi_tcp,... |
440 441 442 443 444 445 |
WARN_ON(hdrlength & (ISCSI_PAD_LEN-1)); hdrlength /= ISCSI_PAD_LEN; WARN_ON(hdrlength >= 256); hdr->hlength = hdrlength & 0xFF; |
96b1f96dc [SCSI] libiscsi: ... |
446 |
hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); |
004d6530f [SCSI] iscsi_tcp,... |
447 |
|
577577da6 [SCSI] libiscsi: ... |
448 |
if (session->tt->init_task && session->tt->init_task(task)) |
052d01448 [SCSI] libiscsi: ... |
449 |
return -EIO; |
9c19a7d03 [SCSI] libiscsi: ... |
450 |
task->state = ISCSI_TASK_RUNNING; |
d3305f340 [SCSI] libiscsi: ... |
451 |
session->cmdsn++; |
77a23c21a [SCSI] libiscsi: ... |
452 |
|
a8ac6311c [SCSI] iscsi: con... |
453 |
conn->scsicmd_pdus_cnt++; |
1b2c7af87 [SCSI] libiscsi: ... |
454 455 456 457 458 459 460 461 462 463 |
ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " "itt 0x%x len %d bidi_len %d cmdsn %d win %d] ", scsi_bidi_cmnd(sc) ? "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", conn->id, sc, sc->cmnd[0], task->itt, scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
004d6530f [SCSI] iscsi_tcp,... |
464 |
return 0; |
7996a778f [SCSI] iscsi: add... |
465 |
} |
7996a778f [SCSI] iscsi: add... |
466 467 |
/** |
3bbaaad95 [SCSI] libiscsi: ... |
468 |
* iscsi_free_task - free a task |
9c19a7d03 [SCSI] libiscsi: ... |
469 |
* @task: iscsi cmd task |
7996a778f [SCSI] iscsi: add... |
470 471 |
* * Must be called with session lock. |
3e5c28ad0 [SCSI] libiscsi: ... |
472 473 |
* This function returns the scsi command to scsi-ml or cleans * up mgmt tasks then returns the task to the pool. |
7996a778f [SCSI] iscsi: add... |
474 |
*/ |
3bbaaad95 [SCSI] libiscsi: ... |
475 |
static void iscsi_free_task(struct iscsi_task *task) |
7996a778f [SCSI] iscsi: add... |
476 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
477 |
struct iscsi_conn *conn = task->conn; |
c1635cb78 [SCSI] libiscsi: ... |
478 |
struct iscsi_session *session = conn->session; |
9c19a7d03 [SCSI] libiscsi: ... |
479 |
struct scsi_cmnd *sc = task->sc; |
f41d47217 [SCSI] libiscsi: ... |
480 |
int oldstate = task->state; |
7996a778f [SCSI] iscsi: add... |
481 |
|
4421c9ebe [SCSI] libiscsi: ... |
482 483 484 |
ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p ", task->itt, task->state, task->sc); |
577577da6 [SCSI] libiscsi: ... |
485 |
session->tt->cleanup_task(task); |
3bbaaad95 [SCSI] libiscsi: ... |
486 |
task->state = ISCSI_TASK_FREE; |
9c19a7d03 [SCSI] libiscsi: ... |
487 |
task->sc = NULL; |
3e5c28ad0 [SCSI] libiscsi: ... |
488 |
/* |
9c19a7d03 [SCSI] libiscsi: ... |
489 |
* login task is preallocated so do not free |
3e5c28ad0 [SCSI] libiscsi: ... |
490 |
*/ |
9c19a7d03 [SCSI] libiscsi: ... |
491 |
if (conn->login_task == task) |
3e5c28ad0 [SCSI] libiscsi: ... |
492 |
return; |
7acd72eb8 kfifo: rename kfi... |
493 |
kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*)); |
052d01448 [SCSI] libiscsi: ... |
494 |
|
3e5c28ad0 [SCSI] libiscsi: ... |
495 |
if (sc) { |
9c19a7d03 [SCSI] libiscsi: ... |
496 |
task->sc = NULL; |
3e5c28ad0 [SCSI] libiscsi: ... |
497 498 499 |
/* SCSI eh reuses commands to verify us */ sc->SCp.ptr = NULL; /* |
f41d47217 [SCSI] libiscsi: ... |
500 501 |
* queue command may call this to free the task, so * it will decide how to return sc to scsi-ml. |
3e5c28ad0 [SCSI] libiscsi: ... |
502 |
*/ |
f41d47217 [SCSI] libiscsi: ... |
503 |
if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ) |
3e5c28ad0 [SCSI] libiscsi: ... |
504 505 |
sc->scsi_done(sc); } |
7996a778f [SCSI] iscsi: add... |
506 |
} |
913e5bf43 [SCSI] libiscsi, ... |
507 |
void __iscsi_get_task(struct iscsi_task *task) |
60ecebf5a [SCSI] add refcou... |
508 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
509 |
atomic_inc(&task->refcount); |
60ecebf5a [SCSI] add refcou... |
510 |
} |
913e5bf43 [SCSI] libiscsi, ... |
511 |
EXPORT_SYMBOL_GPL(__iscsi_get_task); |
60ecebf5a [SCSI] add refcou... |
512 |
|
8eea2f55a [SCSI] bnx2i: Add... |
513 |
void __iscsi_put_task(struct iscsi_task *task) |
60ecebf5a [SCSI] add refcou... |
514 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
515 |
if (atomic_dec_and_test(&task->refcount)) |
3bbaaad95 [SCSI] libiscsi: ... |
516 |
iscsi_free_task(task); |
60ecebf5a [SCSI] add refcou... |
517 |
} |
8eea2f55a [SCSI] bnx2i: Add... |
518 |
EXPORT_SYMBOL_GPL(__iscsi_put_task); |
60ecebf5a [SCSI] add refcou... |
519 |
|
9c19a7d03 [SCSI] libiscsi: ... |
520 |
void iscsi_put_task(struct iscsi_task *task) |
3e5c28ad0 [SCSI] libiscsi: ... |
521 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
522 |
struct iscsi_session *session = task->conn->session; |
3e5c28ad0 [SCSI] libiscsi: ... |
523 524 |
spin_lock_bh(&session->lock); |
9c19a7d03 [SCSI] libiscsi: ... |
525 |
__iscsi_put_task(task); |
3e5c28ad0 [SCSI] libiscsi: ... |
526 527 |
spin_unlock_bh(&session->lock); } |
9c19a7d03 [SCSI] libiscsi: ... |
528 |
EXPORT_SYMBOL_GPL(iscsi_put_task); |
3e5c28ad0 [SCSI] libiscsi: ... |
529 |
|
3bbaaad95 [SCSI] libiscsi: ... |
530 531 532 |
/** * iscsi_complete_task - finish a task * @task: iscsi cmd task |
b3cd5050b [SCSI] libiscsi: ... |
533 |
* @state: state to complete task with |
3bbaaad95 [SCSI] libiscsi: ... |
534 535 536 |
* * Must be called with session lock. */ |
b3cd5050b [SCSI] libiscsi: ... |
537 |
static void iscsi_complete_task(struct iscsi_task *task, int state) |
3bbaaad95 [SCSI] libiscsi: ... |
538 539 |
{ struct iscsi_conn *conn = task->conn; |
4421c9ebe [SCSI] libiscsi: ... |
540 541 542 543 |
ISCSI_DBG_SESSION(conn->session, "complete task itt 0x%x state %d sc %p ", task->itt, task->state, task->sc); |
b3cd5050b [SCSI] libiscsi: ... |
544 545 |
if (task->state == ISCSI_TASK_COMPLETED || task->state == ISCSI_TASK_ABRT_TMF || |
f41d47217 [SCSI] libiscsi: ... |
546 547 |
task->state == ISCSI_TASK_ABRT_SESS_RECOV || task->state == ISCSI_TASK_REQUEUE_SCSIQ) |
3bbaaad95 [SCSI] libiscsi: ... |
548 549 |
return; WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); |
b3cd5050b [SCSI] libiscsi: ... |
550 |
task->state = state; |
3bbaaad95 [SCSI] libiscsi: ... |
551 552 553 554 555 556 557 558 559 560 561 562 563 |
if (!list_empty(&task->running)) list_del_init(&task->running); if (conn->task == task) conn->task = NULL; if (conn->ping_task == task) conn->ping_task = NULL; /* release get from queueing */ __iscsi_put_task(task); } |
4c0ba5d25 [SCSI] libiscsi: ... |
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 |
/** * iscsi_complete_scsi_task - finish scsi task normally * @task: iscsi task for scsi cmd * @exp_cmdsn: expected cmd sn in cpu format * @max_cmdsn: max cmd sn in cpu format * * This is used when drivers do not need or cannot perform * lower level pdu processing. * * Called with session lock */ void iscsi_complete_scsi_task(struct iscsi_task *task, uint32_t exp_cmdsn, uint32_t max_cmdsn) { struct iscsi_conn *conn = task->conn; ISCSI_DBG_SESSION(conn->session, "[itt 0x%x] ", task->itt); conn->last_recv = jiffies; __iscsi_update_cmdsn(conn->session, exp_cmdsn, max_cmdsn); iscsi_complete_task(task, ISCSI_TASK_COMPLETED); } EXPORT_SYMBOL_GPL(iscsi_complete_scsi_task); |
b3a7ea8d5 [SCSI] libiscsi: ... |
588 |
/* |
3bbaaad95 [SCSI] libiscsi: ... |
589 590 591 |
* session lock must be held and if not called for a task that is * still pending or from the xmit thread, then xmit thread must * be suspended. |
b3a7ea8d5 [SCSI] libiscsi: ... |
592 |
*/ |
3bbaaad95 [SCSI] libiscsi: ... |
593 |
static void fail_scsi_task(struct iscsi_task *task, int err) |
b3a7ea8d5 [SCSI] libiscsi: ... |
594 |
{ |
3bbaaad95 [SCSI] libiscsi: ... |
595 |
struct iscsi_conn *conn = task->conn; |
b3a7ea8d5 [SCSI] libiscsi: ... |
596 |
struct scsi_cmnd *sc; |
b3cd5050b [SCSI] libiscsi: ... |
597 |
int state; |
b3a7ea8d5 [SCSI] libiscsi: ... |
598 |
|
3bbaaad95 [SCSI] libiscsi: ... |
599 600 601 602 603 |
/* * if a command completes and we get a successful tmf response * we will hit this because the scsi eh abort code does not take * a ref to the task. */ |
9c19a7d03 [SCSI] libiscsi: ... |
604 |
sc = task->sc; |
b3a7ea8d5 [SCSI] libiscsi: ... |
605 606 |
if (!sc) return; |
b3cd5050b [SCSI] libiscsi: ... |
607 |
if (task->state == ISCSI_TASK_PENDING) { |
b3a7ea8d5 [SCSI] libiscsi: ... |
608 609 610 611 612 |
/* * cmd never made it to the xmit thread, so we should not count * the cmd in the sequencing */ conn->session->queued_cmdsn--; |
b3cd5050b [SCSI] libiscsi: ... |
613 614 615 616 617 618 |
/* it was never sent so just complete like normal */ state = ISCSI_TASK_COMPLETED; } else if (err == DID_TRANSPORT_DISRUPTED) state = ISCSI_TASK_ABRT_SESS_RECOV; else state = ISCSI_TASK_ABRT_TMF; |
b3a7ea8d5 [SCSI] libiscsi: ... |
619 |
|
b3cd5050b [SCSI] libiscsi: ... |
620 |
sc->result = err << 16; |
c07d44440 [SCSI] iscsi: bid... |
621 622 623 624 625 626 |
if (!scsi_bidi_cmnd(sc)) scsi_set_resid(sc, scsi_bufflen(sc)); else { scsi_out(sc)->resid = scsi_out(sc)->length; scsi_in(sc)->resid = scsi_in(sc)->length; } |
3e5c28ad0 [SCSI] libiscsi: ... |
627 |
|
b3cd5050b [SCSI] libiscsi: ... |
628 |
iscsi_complete_task(task, state); |
b3a7ea8d5 [SCSI] libiscsi: ... |
629 |
} |
3e5c28ad0 [SCSI] libiscsi: ... |
630 |
static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
9c19a7d03 [SCSI] libiscsi: ... |
631 |
struct iscsi_task *task) |
052d01448 [SCSI] libiscsi: ... |
632 633 |
{ struct iscsi_session *session = conn->session; |
577577da6 [SCSI] libiscsi: ... |
634 |
struct iscsi_hdr *hdr = task->hdr; |
052d01448 [SCSI] libiscsi: ... |
635 |
struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; |
4f704dc03 [SCSI] libiscsi: ... |
636 |
uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK; |
052d01448 [SCSI] libiscsi: ... |
637 638 639 |
if (conn->session->state == ISCSI_STATE_LOGGING_OUT) return -ENOTCONN; |
4f704dc03 [SCSI] libiscsi: ... |
640 |
if (opcode != ISCSI_OP_LOGIN && opcode != ISCSI_OP_TEXT) |
052d01448 [SCSI] libiscsi: ... |
641 642 643 644 645 646 |
nop->exp_statsn = cpu_to_be32(conn->exp_statsn); /* * pre-format CmdSN for outgoing PDU. */ nop->cmdsn = cpu_to_be32(session->cmdsn); if (hdr->itt != RESERVED_ITT) { |
052d01448 [SCSI] libiscsi: ... |
647 |
/* |
4f704dc03 [SCSI] libiscsi: ... |
648 |
* TODO: We always use immediate for normal session pdus. |
052d01448 [SCSI] libiscsi: ... |
649 650 |
* If we start to send tmfs or nops as non-immediate then * we should start checking the cmdsn numbers for mgmt tasks. |
4f704dc03 [SCSI] libiscsi: ... |
651 652 653 |
* * During discovery sessions iscsid sends TEXT as non immediate, * but we always only send one PDU at a time. |
052d01448 [SCSI] libiscsi: ... |
654 655 656 657 658 659 660 |
*/ if (conn->c_stage == ISCSI_CONN_STARTED && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { session->queued_cmdsn++; session->cmdsn++; } } |
ae15f8017 [SCSI] libiscsi: ... |
661 662 |
if (session->tt->init_task && session->tt->init_task(task)) return -EIO; |
052d01448 [SCSI] libiscsi: ... |
663 664 665 |
if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) session->state = ISCSI_STATE_LOGGING_OUT; |
577577da6 [SCSI] libiscsi: ... |
666 |
task->state = ISCSI_TASK_RUNNING; |
1b2c7af87 [SCSI] libiscsi: ... |
667 668 669 670 |
ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " "datalen %d] ", hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, task->data_count); |
052d01448 [SCSI] libiscsi: ... |
671 672 |
return 0; } |
9c19a7d03 [SCSI] libiscsi: ... |
673 |
static struct iscsi_task * |
f6d5180c7 [SCSI] libiscsi: ... |
674 675 676 677 |
__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { struct iscsi_session *session = conn->session; |
1336aed10 [SCSI] libiscsi: ... |
678 |
struct iscsi_host *ihost = shost_priv(session->host); |
4f704dc03 [SCSI] libiscsi: ... |
679 |
uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK; |
9c19a7d03 [SCSI] libiscsi: ... |
680 |
struct iscsi_task *task; |
262ef6362 [SCSI] libiscsi: ... |
681 |
itt_t itt; |
f6d5180c7 [SCSI] libiscsi: ... |
682 683 684 |
if (session->state == ISCSI_STATE_TERMINATE) return NULL; |
4f704dc03 [SCSI] libiscsi: ... |
685 |
if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) { |
f6d5180c7 [SCSI] libiscsi: ... |
686 687 688 |
/* * Login and Text are sent serially, in * request-followed-by-response sequence. |
3e5c28ad0 [SCSI] libiscsi: ... |
689 690 |
* Same task can be used. Same ITT must be used. * Note that login_task is preallocated at conn_create(). |
f6d5180c7 [SCSI] libiscsi: ... |
691 |
*/ |
4f704dc03 [SCSI] libiscsi: ... |
692 693 694 695 696 697 |
if (conn->login_task->state != ISCSI_TASK_FREE) { iscsi_conn_printk(KERN_ERR, conn, "Login/Text in " "progress. Cannot start new task. "); return NULL; } |
9c19a7d03 [SCSI] libiscsi: ... |
698 |
task = conn->login_task; |
4f704dc03 [SCSI] libiscsi: ... |
699 |
} else { |
26013ad4c [SCSI] libiscsi: ... |
700 701 |
if (session->state != ISCSI_STATE_LOGGED_IN) return NULL; |
f6d5180c7 [SCSI] libiscsi: ... |
702 703 |
BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
7acd72eb8 kfifo: rename kfi... |
704 |
if (!kfifo_out(&session->cmdpool.queue, |
9c19a7d03 [SCSI] libiscsi: ... |
705 |
(void*)&task, sizeof(void*))) |
f6d5180c7 [SCSI] libiscsi: ... |
706 707 |
return NULL; } |
3e5c28ad0 [SCSI] libiscsi: ... |
708 709 710 711 712 |
/* * released in complete pdu for task we expect a response for, and * released by the lld when it has transmitted the task for * pdus we do not expect a response for. */ |
9c19a7d03 [SCSI] libiscsi: ... |
713 714 715 |
atomic_set(&task->refcount, 1); task->conn = conn; task->sc = NULL; |
3bbaaad95 [SCSI] libiscsi: ... |
716 717 |
INIT_LIST_HEAD(&task->running); task->state = ISCSI_TASK_PENDING; |
f6d5180c7 [SCSI] libiscsi: ... |
718 719 |
if (data_size) { |
9c19a7d03 [SCSI] libiscsi: ... |
720 721 |
memcpy(task->data, data, data_size); task->data_count = data_size; |
f6d5180c7 [SCSI] libiscsi: ... |
722 |
} else |
9c19a7d03 [SCSI] libiscsi: ... |
723 |
task->data_count = 0; |
f6d5180c7 [SCSI] libiscsi: ... |
724 |
|
184b57c63 [SCSI] libiscsi: ... |
725 726 727 728 729 |
if (conn->session->tt->alloc_pdu) { if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " "pdu for mgmt task. "); |
3bbaaad95 [SCSI] libiscsi: ... |
730 |
goto free_task; |
184b57c63 [SCSI] libiscsi: ... |
731 |
} |
577577da6 [SCSI] libiscsi: ... |
732 |
} |
184b57c63 [SCSI] libiscsi: ... |
733 |
|
262ef6362 [SCSI] libiscsi: ... |
734 |
itt = task->hdr->itt; |
577577da6 [SCSI] libiscsi: ... |
735 |
task->hdr_len = sizeof(struct iscsi_hdr); |
9c19a7d03 [SCSI] libiscsi: ... |
736 |
memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
262ef6362 [SCSI] libiscsi: ... |
737 738 739 740 741 742 743 744 |
if (hdr->itt != RESERVED_ITT) { if (session->tt->parse_pdu_itt) task->hdr->itt = itt; else task->hdr->itt = build_itt(task->itt, task->conn->session->age); } |
1336aed10 [SCSI] libiscsi: ... |
745 |
if (!ihost->workq) { |
577577da6 [SCSI] libiscsi: ... |
746 747 |
if (iscsi_prep_mgmt_task(conn, task)) goto free_task; |
052d01448 [SCSI] libiscsi: ... |
748 |
|
9c19a7d03 [SCSI] libiscsi: ... |
749 |
if (session->tt->xmit_task(task)) |
577577da6 [SCSI] libiscsi: ... |
750 |
goto free_task; |
3bbaaad95 [SCSI] libiscsi: ... |
751 752 |
} else { list_add_tail(&task->running, &conn->mgmtqueue); |
32ae763e3 [SCSI] iscsi lib:... |
753 |
iscsi_conn_queue_work(conn); |
3bbaaad95 [SCSI] libiscsi: ... |
754 |
} |
052d01448 [SCSI] libiscsi: ... |
755 |
|
9c19a7d03 [SCSI] libiscsi: ... |
756 |
return task; |
577577da6 [SCSI] libiscsi: ... |
757 758 759 760 |
free_task: __iscsi_put_task(task); return NULL; |
f6d5180c7 [SCSI] libiscsi: ... |
761 762 763 764 765 766 767 768 769 770 771 772 773 |
} int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; int err = 0; spin_lock_bh(&session->lock); if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) err = -EPERM; spin_unlock_bh(&session->lock); |
f6d5180c7 [SCSI] libiscsi: ... |
774 775 776 |
return err; } EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); |
7996a778f [SCSI] iscsi: add... |
777 778 779 780 |
/** * iscsi_cmd_rsp - SCSI Command Response processing * @conn: iscsi connection * @hdr: iscsi header |
9c19a7d03 [SCSI] libiscsi: ... |
781 |
* @task: scsi command task |
7996a778f [SCSI] iscsi: add... |
782 783 784 785 |
* @data: cmd data buffer * @datalen: len of buffer * * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and |
9c19a7d03 [SCSI] libiscsi: ... |
786 |
* then completes the command and task. |
7996a778f [SCSI] iscsi: add... |
787 |
**/ |
77a23c21a [SCSI] libiscsi: ... |
788 |
static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
9c19a7d03 [SCSI] libiscsi: ... |
789 |
struct iscsi_task *task, char *data, |
77a23c21a [SCSI] libiscsi: ... |
790 |
int datalen) |
7996a778f [SCSI] iscsi: add... |
791 |
{ |
123521830 iscsi: Resolve is... |
792 |
struct iscsi_scsi_rsp *rhdr = (struct iscsi_scsi_rsp *)hdr; |
7996a778f [SCSI] iscsi: add... |
793 |
struct iscsi_session *session = conn->session; |
9c19a7d03 [SCSI] libiscsi: ... |
794 |
struct scsi_cmnd *sc = task->sc; |
7996a778f [SCSI] iscsi: add... |
795 |
|
77a23c21a [SCSI] libiscsi: ... |
796 |
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); |
7996a778f [SCSI] iscsi: add... |
797 798 799 800 801 802 803 804 805 806 |
conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; sc->result = (DID_OK << 16) | rhdr->cmd_status; if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { sc->result = DID_ERROR << 16; goto out; } if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) { |
9b80cb4be [SCSI] libiscsi: ... |
807 |
uint16_t senselen; |
7996a778f [SCSI] iscsi: add... |
808 809 810 |
if (datalen < 2) { invalid_datalen: |
322d739da [SCSI] iscsi: fix... |
811 812 813 814 |
iscsi_conn_printk(KERN_ERR, conn, "Got CHECK_CONDITION but invalid data " "buffer size of %d ", datalen); |
7996a778f [SCSI] iscsi: add... |
815 816 817 |
sc->result = DID_BAD_TARGET << 16; goto out; } |
8f333991b [SCSI] scsi: use ... |
818 |
senselen = get_unaligned_be16(data); |
7996a778f [SCSI] iscsi: add... |
819 820 821 822 |
if (datalen < senselen) goto invalid_datalen; memcpy(sc->sense_buffer, data + 2, |
9b80cb4be [SCSI] libiscsi: ... |
823 |
min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); |
1b2c7af87 [SCSI] libiscsi: ... |
824 825 826 827 |
ISCSI_DBG_SESSION(session, "copied %d bytes of sense ", min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); |
7996a778f [SCSI] iscsi: add... |
828 |
} |
c07d44440 [SCSI] iscsi: bid... |
829 830 831 832 833 834 835 836 837 838 839 |
if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW | ISCSI_FLAG_CMD_BIDI_OVERFLOW)) { int res_count = be32_to_cpu(rhdr->bi_residual_count); if (scsi_bidi_cmnd(sc) && res_count > 0 && (rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW || res_count <= scsi_in(sc)->length)) scsi_in(sc)->resid = res_count; else sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; } |
7207fea45 [SCSI] iscsi: Pre... |
840 841 |
if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) { |
7996a778f [SCSI] iscsi: add... |
842 |
int res_count = be32_to_cpu(rhdr->residual_count); |
7207fea45 [SCSI] iscsi: Pre... |
843 844 845 |
if (res_count > 0 && (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW || res_count <= scsi_bufflen(sc))) |
c07d44440 [SCSI] iscsi: bid... |
846 |
/* write side for bidi or uni-io set_resid */ |
1c1389915 [SCSI] iscsi_tcp:... |
847 |
scsi_set_resid(sc, res_count); |
7996a778f [SCSI] iscsi: add... |
848 849 |
else sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
c07d44440 [SCSI] iscsi: bid... |
850 |
} |
7996a778f [SCSI] iscsi: add... |
851 |
out: |
3bbaaad95 [SCSI] libiscsi: ... |
852 853 |
ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x] ", |
1b2c7af87 [SCSI] libiscsi: ... |
854 |
sc, sc->result, task->itt); |
7996a778f [SCSI] iscsi: add... |
855 |
conn->scsirsp_pdus_cnt++; |
b3cd5050b [SCSI] libiscsi: ... |
856 |
iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
7996a778f [SCSI] iscsi: add... |
857 |
} |
1d9edf027 [SCSI] libiscsi: ... |
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
/** * iscsi_data_in_rsp - SCSI Data-In Response processing * @conn: iscsi connection * @hdr: iscsi pdu * @task: scsi command task **/ static void iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, struct iscsi_task *task) { struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)hdr; struct scsi_cmnd *sc = task->sc; if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS)) return; |
edbc9aa05 [SCSI] libiscsi: ... |
873 |
iscsi_update_cmdsn(conn->session, (struct iscsi_nopin *)hdr); |
1d9edf027 [SCSI] libiscsi: ... |
874 875 876 877 878 879 880 881 882 883 884 885 886 |
sc->result = (DID_OK << 16) | rhdr->cmd_status; conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW | ISCSI_FLAG_DATA_OVERFLOW)) { int res_count = be32_to_cpu(rhdr->residual_count); if (res_count > 0 && (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW || res_count <= scsi_in(sc)->length)) scsi_in(sc)->resid = res_count; else sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; } |
3bbaaad95 [SCSI] libiscsi: ... |
887 888 889 890 |
ISCSI_DBG_SESSION(conn->session, "data in with status done " "[sc %p res %d itt 0x%x] ", sc, sc->result, task->itt); |
1d9edf027 [SCSI] libiscsi: ... |
891 |
conn->scsirsp_pdus_cnt++; |
b3cd5050b [SCSI] libiscsi: ... |
892 |
iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
1d9edf027 [SCSI] libiscsi: ... |
893 |
} |
7ea8b8284 [SCSI] iscsi bugf... |
894 895 896 897 898 899 |
static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; |
843c0a8a7 [SCSI] libiscsi, ... |
900 |
if (conn->tmf_state != TMF_QUEUED) |
7ea8b8284 [SCSI] iscsi bugf... |
901 902 903 |
return; if (tmf->response == ISCSI_TMF_RSP_COMPLETE) |
843c0a8a7 [SCSI] libiscsi, ... |
904 |
conn->tmf_state = TMF_SUCCESS; |
7ea8b8284 [SCSI] iscsi bugf... |
905 |
else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) |
843c0a8a7 [SCSI] libiscsi, ... |
906 |
conn->tmf_state = TMF_NOT_FOUND; |
7ea8b8284 [SCSI] iscsi bugf... |
907 |
else |
843c0a8a7 [SCSI] libiscsi, ... |
908 |
conn->tmf_state = TMF_FAILED; |
7ea8b8284 [SCSI] iscsi bugf... |
909 910 |
wake_up(&conn->ehwait); } |
f6d5180c7 [SCSI] libiscsi: ... |
911 912 913 |
static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) { struct iscsi_nopout hdr; |
9c19a7d03 [SCSI] libiscsi: ... |
914 |
struct iscsi_task *task; |
f6d5180c7 [SCSI] libiscsi: ... |
915 |
|
9c19a7d03 [SCSI] libiscsi: ... |
916 |
if (!rhdr && conn->ping_task) |
f6d5180c7 [SCSI] libiscsi: ... |
917 918 919 920 921 922 923 |
return; memset(&hdr, 0, sizeof(struct iscsi_nopout)); hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; hdr.flags = ISCSI_FLAG_CMD_FINAL; if (rhdr) { |
55bdabdf4 iscsi: Use struct... |
924 |
hdr.lun = rhdr->lun; |
f6d5180c7 [SCSI] libiscsi: ... |
925 926 927 928 |
hdr.ttt = rhdr->ttt; hdr.itt = RESERVED_ITT; } else hdr.ttt = RESERVED_ITT; |
9c19a7d03 [SCSI] libiscsi: ... |
929 930 |
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); if (!task) |
322d739da [SCSI] iscsi: fix... |
931 932 |
iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout "); |
d3acf0226 [SCSI] libiscsi R... |
933 934 935 936 937 |
else if (!rhdr) { /* only track our nops */ conn->ping_task = task; conn->last_ping = jiffies; } |
f6d5180c7 [SCSI] libiscsi: ... |
938 |
} |
8afa1439f [SCSI] libiscsi: ... |
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 |
static int iscsi_nop_out_rsp(struct iscsi_task *task, struct iscsi_nopin *nop, char *data, int datalen) { struct iscsi_conn *conn = task->conn; int rc = 0; if (conn->ping_task != task) { /* * If this is not in response to one of our * nops then it must be from userspace. */ if (iscsi_recv_pdu(conn->cls_conn, (struct iscsi_hdr *)nop, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; } else mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); iscsi_complete_task(task, ISCSI_TASK_COMPLETED); return rc; } |
62f383003 [SCSI] iscsi_tcp:... |
958 959 960 961 962 |
static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, int datalen) { struct iscsi_reject *reject = (struct iscsi_reject *)hdr; struct iscsi_hdr rejected_pdu; |
8afa1439f [SCSI] libiscsi: ... |
963 |
int opcode, rc = 0; |
62f383003 [SCSI] iscsi_tcp:... |
964 965 |
conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; |
8afa1439f [SCSI] libiscsi: ... |
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 |
if (ntoh24(reject->dlength) > datalen || ntoh24(reject->dlength) < sizeof(struct iscsi_hdr)) { iscsi_conn_printk(KERN_ERR, conn, "Cannot handle rejected " "pdu. Invalid data length (pdu dlength " "%u, datalen %d ", ntoh24(reject->dlength), datalen); return ISCSI_ERR_PROTO; } memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); opcode = rejected_pdu.opcode & ISCSI_OPCODE_MASK; switch (reject->reason) { case ISCSI_REASON_DATA_DIGEST_ERROR: iscsi_conn_printk(KERN_ERR, conn, "pdu (op 0x%x itt 0x%x) rejected " "due to DataDigest error. ", rejected_pdu.itt, opcode); break; case ISCSI_REASON_IMM_CMD_REJECT: iscsi_conn_printk(KERN_ERR, conn, "pdu (op 0x%x itt 0x%x) rejected. Too many " "immediate commands. ", rejected_pdu.itt, opcode); /* * We only send one TMF at a time so if the target could not * handle it, then it should get fixed (RFC mandates that * a target can handle one immediate TMF per conn). * * For nops-outs, we could have sent more than one if * the target is sending us lots of nop-ins */ if (opcode != ISCSI_OP_NOOP_OUT) return 0; |
62f383003 [SCSI] iscsi_tcp:... |
1002 |
|
8afa1439f [SCSI] libiscsi: ... |
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 |
if (rejected_pdu.itt == cpu_to_be32(ISCSI_RESERVED_TAG)) /* * nop-out in response to target's nop-out rejected. * Just resend. */ iscsi_send_nopout(conn, (struct iscsi_nopin*)&rejected_pdu); else { struct iscsi_task *task; /* * Our nop as ping got dropped. We know the target * and transport are ok so just clean up */ task = iscsi_itt_to_task(conn, rejected_pdu.itt); if (!task) { iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu reject. Could " "not lookup rejected task. "); rc = ISCSI_ERR_BAD_ITT; } else rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)&rejected_pdu, NULL, 0); |
62f383003 [SCSI] iscsi_tcp:... |
1027 |
} |
8afa1439f [SCSI] libiscsi: ... |
1028 1029 1030 1031 1032 1033 1034 1035 |
break; default: iscsi_conn_printk(KERN_ERR, conn, "pdu (op 0x%x itt 0x%x) rejected. Reason " "code 0x%x ", rejected_pdu.itt, rejected_pdu.opcode, reject->reason); break; |
62f383003 [SCSI] iscsi_tcp:... |
1036 |
} |
8afa1439f [SCSI] libiscsi: ... |
1037 |
return rc; |
62f383003 [SCSI] iscsi_tcp:... |
1038 |
} |
7996a778f [SCSI] iscsi: add... |
1039 |
/** |
913e5bf43 [SCSI] libiscsi, ... |
1040 1041 1042 1043 1044 1045 1046 1047 1048 |
* iscsi_itt_to_task - look up task by itt * @conn: iscsi connection * @itt: itt * * This should be used for mgmt tasks like login and nops, or if * the LDD's itt space does not include the session age. * * The session lock must be held. */ |
8f9256cea [SCSI] libiscsi: ... |
1049 |
struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
913e5bf43 [SCSI] libiscsi, ... |
1050 1051 |
{ struct iscsi_session *session = conn->session; |
262ef6362 [SCSI] libiscsi: ... |
1052 |
int i; |
913e5bf43 [SCSI] libiscsi, ... |
1053 1054 1055 |
if (itt == RESERVED_ITT) return NULL; |
262ef6362 [SCSI] libiscsi: ... |
1056 1057 1058 1059 |
if (session->tt->parse_pdu_itt) session->tt->parse_pdu_itt(conn, itt, &i, NULL); else i = get_itt(itt); |
913e5bf43 [SCSI] libiscsi, ... |
1060 1061 1062 1063 1064 |
if (i >= session->cmds_max) return NULL; return session->cmds[i]; } |
8f9256cea [SCSI] libiscsi: ... |
1065 |
EXPORT_SYMBOL_GPL(iscsi_itt_to_task); |
913e5bf43 [SCSI] libiscsi, ... |
1066 1067 |
/** |
7996a778f [SCSI] iscsi: add... |
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 |
* __iscsi_complete_pdu - complete pdu * @conn: iscsi conn * @hdr: iscsi header * @data: data buffer * @datalen: len of data buffer * * Completes pdu processing by freeing any resources allocated at * queuecommand or send generic. session lock must be held and verify * itt must have been called. */ |
913e5bf43 [SCSI] libiscsi, ... |
1078 1079 |
int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, int datalen) |
7996a778f [SCSI] iscsi: add... |
1080 1081 1082 |
{ struct iscsi_session *session = conn->session; int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; |
9c19a7d03 [SCSI] libiscsi: ... |
1083 |
struct iscsi_task *task; |
7996a778f [SCSI] iscsi: add... |
1084 |
uint32_t itt; |
f6d5180c7 [SCSI] libiscsi: ... |
1085 |
conn->last_recv = jiffies; |
0af967f5d [SCSI] libiscsi, ... |
1086 1087 1088 |
rc = iscsi_verify_itt(conn, hdr->itt); if (rc) return rc; |
b43773564 [PATCH] iscsi end... |
1089 1090 |
if (hdr->itt != RESERVED_ITT) itt = get_itt(hdr->itt); |
7996a778f [SCSI] iscsi: add... |
1091 |
else |
b43773564 [PATCH] iscsi end... |
1092 |
itt = ~0U; |
7996a778f [SCSI] iscsi: add... |
1093 |
|
1b2c7af87 [SCSI] libiscsi: ... |
1094 1095 1096 |
ISCSI_DBG_SESSION(session, "[op 0x%x cid %d itt 0x%x len %d] ", opcode, conn->id, itt, datalen); |
7996a778f [SCSI] iscsi: add... |
1097 |
|
3e5c28ad0 [SCSI] libiscsi: ... |
1098 |
if (itt == ~0U) { |
77a23c21a [SCSI] libiscsi: ... |
1099 |
iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
62f383003 [SCSI] iscsi_tcp:... |
1100 |
|
7996a778f [SCSI] iscsi: add... |
1101 1102 |
switch(opcode) { case ISCSI_OP_NOOP_IN: |
40527afea [SCSI] iscsi bugf... |
1103 |
if (datalen) { |
7996a778f [SCSI] iscsi: add... |
1104 |
rc = ISCSI_ERR_PROTO; |
40527afea [SCSI] iscsi bugf... |
1105 1106 |
break; } |
b43773564 [PATCH] iscsi end... |
1107 |
if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) |
40527afea [SCSI] iscsi bugf... |
1108 |
break; |
f6d5180c7 [SCSI] libiscsi: ... |
1109 |
iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr); |
7996a778f [SCSI] iscsi: add... |
1110 1111 |
break; case ISCSI_OP_REJECT: |
62f383003 [SCSI] iscsi_tcp:... |
1112 1113 |
rc = iscsi_handle_reject(conn, hdr, data, datalen); break; |
7996a778f [SCSI] iscsi: add... |
1114 |
case ISCSI_OP_ASYNC_EVENT: |
8d2860b3c [SCSI] iscsi: inc... |
1115 |
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
5831c737f [SCSI] libiscsi: ... |
1116 1117 |
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; |
7996a778f [SCSI] iscsi: add... |
1118 1119 1120 1121 1122 |
break; default: rc = ISCSI_ERR_BAD_OPCODE; break; } |
3e5c28ad0 [SCSI] libiscsi: ... |
1123 1124 |
goto out; } |
3e5c28ad0 [SCSI] libiscsi: ... |
1125 1126 |
switch(opcode) { case ISCSI_OP_SCSI_CMD_RSP: |
913e5bf43 [SCSI] libiscsi, ... |
1127 1128 1129 1130 |
case ISCSI_OP_SCSI_DATA_IN: task = iscsi_itt_to_ctask(conn, hdr->itt); if (!task) return ISCSI_ERR_BAD_ITT; |
d355e57d5 libiscsi: don't r... |
1131 |
task->last_xfer = jiffies; |
913e5bf43 [SCSI] libiscsi, ... |
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 |
break; case ISCSI_OP_R2T: /* * LLD handles R2Ts if they need to. */ return 0; case ISCSI_OP_LOGOUT_RSP: case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: case ISCSI_OP_SCSI_TMFUNC_RSP: case ISCSI_OP_NOOP_IN: task = iscsi_itt_to_task(conn, hdr->itt); if (!task) return ISCSI_ERR_BAD_ITT; break; default: return ISCSI_ERR_BAD_OPCODE; } switch(opcode) { case ISCSI_OP_SCSI_CMD_RSP: |
9c19a7d03 [SCSI] libiscsi: ... |
1153 |
iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen); |
3e5c28ad0 [SCSI] libiscsi: ... |
1154 1155 |
break; case ISCSI_OP_SCSI_DATA_IN: |
1d9edf027 [SCSI] libiscsi: ... |
1156 |
iscsi_data_in_rsp(conn, hdr, task); |
3e5c28ad0 [SCSI] libiscsi: ... |
1157 |
break; |
3e5c28ad0 [SCSI] libiscsi: ... |
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 |
case ISCSI_OP_LOGOUT_RSP: iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); if (datalen) { rc = ISCSI_ERR_PROTO; break; } conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; goto recv_pdu; case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); /* * login related PDU's exp_statsn is handled in * userspace */ goto recv_pdu; case ISCSI_OP_SCSI_TMFUNC_RSP: iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); if (datalen) { rc = ISCSI_ERR_PROTO; break; } iscsi_tmf_rsp(conn, hdr); |
b3cd5050b [SCSI] libiscsi: ... |
1182 |
iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
3e5c28ad0 [SCSI] libiscsi: ... |
1183 1184 1185 1186 1187 1188 1189 1190 |
break; case ISCSI_OP_NOOP_IN: iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { rc = ISCSI_ERR_PROTO; break; } conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
8afa1439f [SCSI] libiscsi: ... |
1191 1192 |
rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)hdr, data, datalen); |
3e5c28ad0 [SCSI] libiscsi: ... |
1193 1194 1195 1196 1197 |
break; default: rc = ISCSI_ERR_BAD_OPCODE; break; } |
7996a778f [SCSI] iscsi: add... |
1198 |
|
3e5c28ad0 [SCSI] libiscsi: ... |
1199 1200 1201 1202 1203 |
out: return rc; recv_pdu: if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; |
b3cd5050b [SCSI] libiscsi: ... |
1204 |
iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
7996a778f [SCSI] iscsi: add... |
1205 1206 |
return rc; } |
913e5bf43 [SCSI] libiscsi, ... |
1207 |
EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); |
7996a778f [SCSI] iscsi: add... |
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 |
int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, int datalen) { int rc; spin_lock(&conn->session->lock); rc = __iscsi_complete_pdu(conn, hdr, data, datalen); spin_unlock(&conn->session->lock); return rc; } EXPORT_SYMBOL_GPL(iscsi_complete_pdu); |
0af967f5d [SCSI] libiscsi, ... |
1220 |
int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) |
7996a778f [SCSI] iscsi: add... |
1221 1222 |
{ struct iscsi_session *session = conn->session; |
262ef6362 [SCSI] libiscsi: ... |
1223 |
int age = 0, i = 0; |
7996a778f [SCSI] iscsi: add... |
1224 |
|
0af967f5d [SCSI] libiscsi, ... |
1225 1226 |
if (itt == RESERVED_ITT) return 0; |
7996a778f [SCSI] iscsi: add... |
1227 |
|
262ef6362 [SCSI] libiscsi: ... |
1228 1229 1230 1231 1232 1233 1234 1235 |
if (session->tt->parse_pdu_itt) session->tt->parse_pdu_itt(conn, itt, &i, &age); else { i = get_itt(itt); age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK; } if (age != session->age) { |
0af967f5d [SCSI] libiscsi, ... |
1236 1237 1238 |
iscsi_conn_printk(KERN_ERR, conn, "received itt %x expected session age (%x) ", |
913e5bf43 [SCSI] libiscsi, ... |
1239 |
(__force u32)itt, session->age); |
0af967f5d [SCSI] libiscsi, ... |
1240 1241 |
return ISCSI_ERR_BAD_ITT; } |
7996a778f [SCSI] iscsi: add... |
1242 |
|
3e5c28ad0 [SCSI] libiscsi: ... |
1243 1244 1245 1246 1247 1248 |
if (i >= session->cmds_max) { iscsi_conn_printk(KERN_ERR, conn, "received invalid itt index %u (max cmds " "%u. ", i, session->cmds_max); return ISCSI_ERR_BAD_ITT; |
7996a778f [SCSI] iscsi: add... |
1249 |
} |
7996a778f [SCSI] iscsi: add... |
1250 1251 1252 |
return 0; } EXPORT_SYMBOL_GPL(iscsi_verify_itt); |
913e5bf43 [SCSI] libiscsi, ... |
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 |
/** * iscsi_itt_to_ctask - look up ctask by itt * @conn: iscsi connection * @itt: itt * * This should be used for cmd tasks. * * The session lock must be held. */ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt) |
0af967f5d [SCSI] libiscsi, ... |
1263 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
1264 |
struct iscsi_task *task; |
0af967f5d [SCSI] libiscsi, ... |
1265 1266 1267 |
if (iscsi_verify_itt(conn, itt)) return NULL; |
913e5bf43 [SCSI] libiscsi, ... |
1268 1269 |
task = iscsi_itt_to_task(conn, itt); if (!task || !task->sc) |
0af967f5d [SCSI] libiscsi, ... |
1270 |
return NULL; |
913e5bf43 [SCSI] libiscsi, ... |
1271 1272 1273 1274 1275 |
if (task->sc->SCp.phase != conn->session->age) { iscsi_session_printk(KERN_ERR, conn->session, "task's session age %d, expected %d ", task->sc->SCp.phase, conn->session->age); |
0af967f5d [SCSI] libiscsi, ... |
1276 |
return NULL; |
913e5bf43 [SCSI] libiscsi, ... |
1277 |
} |
0af967f5d [SCSI] libiscsi, ... |
1278 |
|
9c19a7d03 [SCSI] libiscsi: ... |
1279 |
return task; |
0af967f5d [SCSI] libiscsi, ... |
1280 1281 |
} EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask); |
40a06e755 [SCSI] libiscsi: ... |
1282 |
void iscsi_session_failure(struct iscsi_session *session, |
e5bd7b54e [SCSI] libiscsi: ... |
1283 1284 |
enum iscsi_err err) { |
e5bd7b54e [SCSI] libiscsi: ... |
1285 1286 |
struct iscsi_conn *conn; struct device *dev; |
e5bd7b54e [SCSI] libiscsi: ... |
1287 |
|
bfcf72e44 [SCSI] libiscsi: ... |
1288 |
spin_lock_bh(&session->lock); |
e5bd7b54e [SCSI] libiscsi: ... |
1289 1290 |
conn = session->leadconn; if (session->state == ISCSI_STATE_TERMINATE || !conn) { |
bfcf72e44 [SCSI] libiscsi: ... |
1291 |
spin_unlock_bh(&session->lock); |
e5bd7b54e [SCSI] libiscsi: ... |
1292 1293 1294 1295 |
return; } dev = get_device(&conn->cls_conn->dev); |
bfcf72e44 [SCSI] libiscsi: ... |
1296 |
spin_unlock_bh(&session->lock); |
e5bd7b54e [SCSI] libiscsi: ... |
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
if (!dev) return; /* * if the host is being removed bypass the connection * recovery initialization because we are going to kill * the session. */ if (err == ISCSI_ERR_INVALID_HOST) iscsi_conn_error_event(conn->cls_conn, err); else iscsi_conn_failure(conn, err); put_device(dev); } EXPORT_SYMBOL_GPL(iscsi_session_failure); |
7996a778f [SCSI] iscsi: add... |
1311 1312 1313 |
void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) { struct iscsi_session *session = conn->session; |
7996a778f [SCSI] iscsi: add... |
1314 |
|
bfcf72e44 [SCSI] libiscsi: ... |
1315 |
spin_lock_bh(&session->lock); |
656cffc95 [SCSI] iscsi: fix... |
1316 |
if (session->state == ISCSI_STATE_FAILED) { |
bfcf72e44 [SCSI] libiscsi: ... |
1317 |
spin_unlock_bh(&session->lock); |
656cffc95 [SCSI] iscsi: fix... |
1318 1319 |
return; } |
67a611149 [SCSI] iscsi: don... |
1320 |
if (conn->stop_stage == 0) |
7996a778f [SCSI] iscsi: add... |
1321 |
session->state = ISCSI_STATE_FAILED; |
bfcf72e44 [SCSI] libiscsi: ... |
1322 |
spin_unlock_bh(&session->lock); |
e5bd7b54e [SCSI] libiscsi: ... |
1323 |
|
7996a778f [SCSI] iscsi: add... |
1324 1325 |
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); |
e5bd7b54e [SCSI] libiscsi: ... |
1326 |
iscsi_conn_error_event(conn->cls_conn, err); |
7996a778f [SCSI] iscsi: add... |
1327 1328 |
} EXPORT_SYMBOL_GPL(iscsi_conn_failure); |
77a23c21a [SCSI] libiscsi: ... |
1329 1330 1331 1332 1333 1334 1335 |
static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) { struct iscsi_session *session = conn->session; /* * Check for iSCSI window and take care of CmdSN wrap-around */ |
e07264071 [SCSI] libiscsi: ... |
1336 |
if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { |
1b2c7af87 [SCSI] libiscsi: ... |
1337 1338 1339 1340 1341 |
ISCSI_DBG_SESSION(session, "iSCSI CmdSN closed. ExpCmdSn " "%u MaxCmdSN %u CmdSN %u/%u ", session->exp_cmdsn, session->max_cmdsn, session->cmdsn, session->queued_cmdsn); |
77a23c21a [SCSI] libiscsi: ... |
1342 1343 1344 1345 |
return -ENOSPC; } return 0; } |
9c19a7d03 [SCSI] libiscsi: ... |
1346 |
static int iscsi_xmit_task(struct iscsi_conn *conn) |
77a23c21a [SCSI] libiscsi: ... |
1347 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
1348 |
struct iscsi_task *task = conn->task; |
843c0a8a7 [SCSI] libiscsi, ... |
1349 |
int rc; |
77a23c21a [SCSI] libiscsi: ... |
1350 |
|
70b31c152 [SCSI] libiscsi, ... |
1351 1352 |
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) return -ENODATA; |
9c19a7d03 [SCSI] libiscsi: ... |
1353 |
__iscsi_get_task(task); |
77a23c21a [SCSI] libiscsi: ... |
1354 |
spin_unlock_bh(&conn->session->lock); |
9c19a7d03 [SCSI] libiscsi: ... |
1355 |
rc = conn->session->tt->xmit_task(task); |
77a23c21a [SCSI] libiscsi: ... |
1356 |
spin_lock_bh(&conn->session->lock); |
d355e57d5 libiscsi: don't r... |
1357 |
if (!rc) { |
9c19a7d03 [SCSI] libiscsi: ... |
1358 |
/* done with this task */ |
d355e57d5 libiscsi: don't r... |
1359 |
task->last_xfer = jiffies; |
9c19a7d03 [SCSI] libiscsi: ... |
1360 |
conn->task = NULL; |
d355e57d5 libiscsi: don't r... |
1361 1362 |
} __iscsi_put_task(task); |
77a23c21a [SCSI] libiscsi: ... |
1363 1364 |
return rc; } |
7996a778f [SCSI] iscsi: add... |
1365 |
/** |
9c19a7d03 [SCSI] libiscsi: ... |
1366 1367 |
* iscsi_requeue_task - requeue task to run from session workqueue * @task: task to requeue |
843c0a8a7 [SCSI] libiscsi, ... |
1368 |
* |
9c19a7d03 [SCSI] libiscsi: ... |
1369 |
* LLDs that need to run a task from the session workqueue should call |
052d01448 [SCSI] libiscsi: ... |
1370 1371 |
* this. The session lock must be held. This should only be called * by software drivers. |
843c0a8a7 [SCSI] libiscsi, ... |
1372 |
*/ |
9c19a7d03 [SCSI] libiscsi: ... |
1373 |
void iscsi_requeue_task(struct iscsi_task *task) |
843c0a8a7 [SCSI] libiscsi, ... |
1374 |
{ |
9c19a7d03 [SCSI] libiscsi: ... |
1375 |
struct iscsi_conn *conn = task->conn; |
843c0a8a7 [SCSI] libiscsi, ... |
1376 |
|
3bbaaad95 [SCSI] libiscsi: ... |
1377 1378 1379 1380 1381 1382 |
/* * this may be on the requeue list already if the xmit_task callout * is handling the r2ts while we are adding new ones */ if (list_empty(&task->running)) list_add_tail(&task->running, &conn->requeue); |
32ae763e3 [SCSI] iscsi lib:... |
1383 |
iscsi_conn_queue_work(conn); |
843c0a8a7 [SCSI] libiscsi, ... |
1384 |
} |
9c19a7d03 [SCSI] libiscsi: ... |
1385 |
EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
843c0a8a7 [SCSI] libiscsi, ... |
1386 1387 |
/** |
7996a778f [SCSI] iscsi: add... |
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 |
* iscsi_data_xmit - xmit any command into the scheduled connection * @conn: iscsi connection * * Notes: * The function can return -EAGAIN in which case the caller must * re-schedule it again later or recover. '0' return code means * successful xmit. **/ static int iscsi_data_xmit(struct iscsi_conn *conn) { |
5d12c05e2 [SCSI] libiscsi: ... |
1398 |
struct iscsi_task *task; |
3219e5294 [SCSI] iscsi: fix... |
1399 |
int rc = 0; |
7996a778f [SCSI] iscsi: add... |
1400 |
|
77a23c21a [SCSI] libiscsi: ... |
1401 |
spin_lock_bh(&conn->session->lock); |
70b31c152 [SCSI] libiscsi, ... |
1402 |
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { |
1b2c7af87 [SCSI] libiscsi: ... |
1403 1404 |
ISCSI_DBG_SESSION(conn->session, "Tx suspended! "); |
77a23c21a [SCSI] libiscsi: ... |
1405 |
spin_unlock_bh(&conn->session->lock); |
3219e5294 [SCSI] iscsi: fix... |
1406 |
return -ENODATA; |
7996a778f [SCSI] iscsi: add... |
1407 |
} |
7996a778f [SCSI] iscsi: add... |
1408 |
|
9c19a7d03 [SCSI] libiscsi: ... |
1409 1410 |
if (conn->task) { rc = iscsi_xmit_task(conn); |
3219e5294 [SCSI] iscsi: fix... |
1411 |
if (rc) |
70b31c152 [SCSI] libiscsi, ... |
1412 |
goto done; |
7996a778f [SCSI] iscsi: add... |
1413 |
} |
77a23c21a [SCSI] libiscsi: ... |
1414 1415 1416 1417 1418 1419 |
/* * process mgmt pdus like nops before commands since we should * only have one nop-out as a ping from us and targets should not * overflow us with nop-ins */ check_mgmt: |
843c0a8a7 [SCSI] libiscsi, ... |
1420 |
while (!list_empty(&conn->mgmtqueue)) { |
9c19a7d03 [SCSI] libiscsi: ... |
1421 1422 |
conn->task = list_entry(conn->mgmtqueue.next, struct iscsi_task, running); |
3bbaaad95 [SCSI] libiscsi: ... |
1423 |
list_del_init(&conn->task->running); |
9c19a7d03 [SCSI] libiscsi: ... |
1424 1425 1426 |
if (iscsi_prep_mgmt_task(conn, conn->task)) { __iscsi_put_task(conn->task); conn->task = NULL; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1427 1428 |
continue; } |
9c19a7d03 [SCSI] libiscsi: ... |
1429 |
rc = iscsi_xmit_task(conn); |
77a23c21a [SCSI] libiscsi: ... |
1430 |
if (rc) |
70b31c152 [SCSI] libiscsi, ... |
1431 |
goto done; |
7996a778f [SCSI] iscsi: add... |
1432 |
} |
843c0a8a7 [SCSI] libiscsi, ... |
1433 |
/* process pending command queue */ |
3bbaaad95 [SCSI] libiscsi: ... |
1434 |
while (!list_empty(&conn->cmdqueue)) { |
5d12c05e2 [SCSI] libiscsi: ... |
1435 1436 |
conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task, running); |
3bbaaad95 [SCSI] libiscsi: ... |
1437 |
list_del_init(&conn->task->running); |
b3a7ea8d5 [SCSI] libiscsi: ... |
1438 |
if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
b3cd5050b [SCSI] libiscsi: ... |
1439 |
fail_scsi_task(conn->task, DID_IMM_RETRY); |
b3a7ea8d5 [SCSI] libiscsi: ... |
1440 1441 |
continue; } |
577577da6 [SCSI] libiscsi: ... |
1442 1443 |
rc = iscsi_prep_scsi_cmd_pdu(conn->task); if (rc) { |
5d12c05e2 [SCSI] libiscsi: ... |
1444 |
if (rc == -ENOMEM || rc == -EACCES) { |
3bbaaad95 [SCSI] libiscsi: ... |
1445 1446 |
list_add_tail(&conn->task->running, &conn->cmdqueue); |
577577da6 [SCSI] libiscsi: ... |
1447 |
conn->task = NULL; |
70b31c152 [SCSI] libiscsi, ... |
1448 |
goto done; |
577577da6 [SCSI] libiscsi: ... |
1449 |
} else |
b3cd5050b [SCSI] libiscsi: ... |
1450 |
fail_scsi_task(conn->task, DID_ABORT); |
004d6530f [SCSI] iscsi_tcp,... |
1451 1452 |
continue; } |
9c19a7d03 [SCSI] libiscsi: ... |
1453 |
rc = iscsi_xmit_task(conn); |
77a23c21a [SCSI] libiscsi: ... |
1454 |
if (rc) |
70b31c152 [SCSI] libiscsi, ... |
1455 |
goto done; |
77a23c21a [SCSI] libiscsi: ... |
1456 |
/* |
9c19a7d03 [SCSI] libiscsi: ... |
1457 |
* we could continuously get new task requests so |
77a23c21a [SCSI] libiscsi: ... |
1458 1459 1460 |
* we need to check the mgmt queue for nops that need to * be sent to aviod starvation */ |
843c0a8a7 [SCSI] libiscsi, ... |
1461 1462 1463 1464 1465 |
if (!list_empty(&conn->mgmtqueue)) goto check_mgmt; } while (!list_empty(&conn->requeue)) { |
b3a7ea8d5 [SCSI] libiscsi: ... |
1466 1467 1468 1469 1470 |
/* * we always do fastlogout - conn stop code will clean up. */ if (conn->session->state == ISCSI_STATE_LOGGING_OUT) break; |
5d12c05e2 [SCSI] libiscsi: ... |
1471 1472 1473 1474 1475 1476 |
task = list_entry(conn->requeue.next, struct iscsi_task, running); if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT)) break; conn->task = task; |
3bbaaad95 [SCSI] libiscsi: ... |
1477 |
list_del_init(&conn->task->running); |
9c19a7d03 [SCSI] libiscsi: ... |
1478 |
conn->task->state = ISCSI_TASK_RUNNING; |
9c19a7d03 [SCSI] libiscsi: ... |
1479 |
rc = iscsi_xmit_task(conn); |
843c0a8a7 [SCSI] libiscsi, ... |
1480 |
if (rc) |
70b31c152 [SCSI] libiscsi, ... |
1481 |
goto done; |
843c0a8a7 [SCSI] libiscsi, ... |
1482 |
if (!list_empty(&conn->mgmtqueue)) |
77a23c21a [SCSI] libiscsi: ... |
1483 |
goto check_mgmt; |
7996a778f [SCSI] iscsi: add... |
1484 |
} |
b6c395ed0 [SCSI] iscsi bugf... |
1485 |
spin_unlock_bh(&conn->session->lock); |
3219e5294 [SCSI] iscsi: fix... |
1486 |
return -ENODATA; |
7996a778f [SCSI] iscsi: add... |
1487 |
|
70b31c152 [SCSI] libiscsi, ... |
1488 |
done: |
77a23c21a [SCSI] libiscsi: ... |
1489 |
spin_unlock_bh(&conn->session->lock); |
3219e5294 [SCSI] iscsi: fix... |
1490 |
return rc; |
7996a778f [SCSI] iscsi: add... |
1491 |
} |
c4028958b WorkStruct: make ... |
1492 |
static void iscsi_xmitworker(struct work_struct *work) |
7996a778f [SCSI] iscsi: add... |
1493 |
{ |
c4028958b WorkStruct: make ... |
1494 1495 |
struct iscsi_conn *conn = container_of(work, struct iscsi_conn, xmitwork); |
3219e5294 [SCSI] iscsi: fix... |
1496 |
int rc; |
7996a778f [SCSI] iscsi: add... |
1497 1498 1499 |
/* * serialize Xmit worker on a per-connection basis. */ |
3219e5294 [SCSI] iscsi: fix... |
1500 1501 1502 |
do { rc = iscsi_data_xmit(conn); } while (rc >= 0 || rc == -EAGAIN); |
7996a778f [SCSI] iscsi: add... |
1503 |
} |
577577da6 [SCSI] libiscsi: ... |
1504 1505 1506 1507 |
static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, struct scsi_cmnd *sc) { struct iscsi_task *task; |
7acd72eb8 kfifo: rename kfi... |
1508 |
if (!kfifo_out(&conn->session->cmdpool.queue, |
577577da6 [SCSI] libiscsi: ... |
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 |
(void *) &task, sizeof(void *))) return NULL; sc->SCp.phase = conn->session->age; sc->SCp.ptr = (char *) task; atomic_set(&task->refcount, 1); task->state = ISCSI_TASK_PENDING; task->conn = conn; task->sc = sc; |
d355e57d5 libiscsi: don't r... |
1519 1520 1521 |
task->have_checked_conn = false; task->last_timeout = jiffies; task->last_xfer = jiffies; |
577577da6 [SCSI] libiscsi: ... |
1522 1523 1524 |
INIT_LIST_HEAD(&task->running); return task; } |
7996a778f [SCSI] iscsi: add... |
1525 1526 1527 1528 1529 |
enum { FAILURE_BAD_HOST = 1, FAILURE_SESSION_FAILED, FAILURE_SESSION_FREED, FAILURE_WINDOW_CLOSED, |
60ecebf5a [SCSI] add refcou... |
1530 |
FAILURE_OOM, |
7996a778f [SCSI] iscsi: add... |
1531 |
FAILURE_SESSION_TERMINATE, |
656cffc95 [SCSI] iscsi: fix... |
1532 |
FAILURE_SESSION_IN_RECOVERY, |
7996a778f [SCSI] iscsi: add... |
1533 |
FAILURE_SESSION_RECOVERY_TIMEOUT, |
b3a7ea8d5 [SCSI] libiscsi: ... |
1534 |
FAILURE_SESSION_LOGGING_OUT, |
6eabafbe6 [SCSI] iscsi clas... |
1535 |
FAILURE_SESSION_NOT_READY, |
7996a778f [SCSI] iscsi: add... |
1536 |
}; |
f41d47217 [SCSI] libiscsi: ... |
1537 |
int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) |
7996a778f [SCSI] iscsi: add... |
1538 |
{ |
756135215 [SCSI] iscsi: rem... |
1539 |
struct iscsi_cls_session *cls_session; |
1336aed10 [SCSI] libiscsi: ... |
1540 |
struct iscsi_host *ihost; |
7996a778f [SCSI] iscsi: add... |
1541 1542 1543 |
int reason = 0; struct iscsi_session *session; struct iscsi_conn *conn; |
9c19a7d03 [SCSI] libiscsi: ... |
1544 |
struct iscsi_task *task = NULL; |
7996a778f [SCSI] iscsi: add... |
1545 |
|
7996a778f [SCSI] iscsi: add... |
1546 |
sc->result = 0; |
f47f2cf5d [SCSI] libiscsi: ... |
1547 |
sc->SCp.ptr = NULL; |
7996a778f [SCSI] iscsi: add... |
1548 |
|
1336aed10 [SCSI] libiscsi: ... |
1549 |
ihost = shost_priv(host); |
7996a778f [SCSI] iscsi: add... |
1550 |
|
756135215 [SCSI] iscsi: rem... |
1551 1552 |
cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; |
f41d47217 [SCSI] libiscsi: ... |
1553 |
spin_lock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
1554 |
|
756135215 [SCSI] iscsi: rem... |
1555 |
reason = iscsi_session_chkready(cls_session); |
6eabafbe6 [SCSI] iscsi clas... |
1556 1557 1558 1559 |
if (reason) { sc->result = reason; goto fault; } |
301e0f7e4 [SCSI] libiscsi: ... |
1560 |
if (session->state != ISCSI_STATE_LOGGED_IN) { |
656cffc95 [SCSI] iscsi: fix... |
1561 1562 1563 1564 1565 1566 |
/* * to handle the race between when we set the recovery state * and block the session we requeue here (commands could * be entering our queuecommand while a block is starting * up because the block code is not locked) */ |
9000bcd64 [SCSI] libiscsi: ... |
1567 |
switch (session->state) { |
301e0f7e4 [SCSI] libiscsi: ... |
1568 |
case ISCSI_STATE_FAILED: |
9000bcd64 [SCSI] libiscsi: ... |
1569 |
case ISCSI_STATE_IN_RECOVERY: |
656cffc95 [SCSI] iscsi: fix... |
1570 |
reason = FAILURE_SESSION_IN_RECOVERY; |
301e0f7e4 [SCSI] libiscsi: ... |
1571 1572 |
sc->result = DID_IMM_RETRY << 16; break; |
9000bcd64 [SCSI] libiscsi: ... |
1573 1574 |
case ISCSI_STATE_LOGGING_OUT: reason = FAILURE_SESSION_LOGGING_OUT; |
301e0f7e4 [SCSI] libiscsi: ... |
1575 1576 |
sc->result = DID_IMM_RETRY << 16; break; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1577 |
case ISCSI_STATE_RECOVERY_FAILED: |
656cffc95 [SCSI] iscsi: fix... |
1578 |
reason = FAILURE_SESSION_RECOVERY_TIMEOUT; |
56d7fcfa8 [SCSI] iscsi clas... |
1579 |
sc->result = DID_TRANSPORT_FAILFAST << 16; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1580 1581 |
break; case ISCSI_STATE_TERMINATE: |
656cffc95 [SCSI] iscsi: fix... |
1582 |
reason = FAILURE_SESSION_TERMINATE; |
6eabafbe6 [SCSI] iscsi clas... |
1583 |
sc->result = DID_NO_CONNECT << 16; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1584 |
break; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1585 |
default: |
656cffc95 [SCSI] iscsi: fix... |
1586 |
reason = FAILURE_SESSION_FREED; |
6eabafbe6 [SCSI] iscsi clas... |
1587 |
sc->result = DID_NO_CONNECT << 16; |
b3a7ea8d5 [SCSI] libiscsi: ... |
1588 |
} |
7996a778f [SCSI] iscsi: add... |
1589 1590 |
goto fault; } |
7996a778f [SCSI] iscsi: add... |
1591 |
conn = session->leadconn; |
986440479 [SCSI] libiscsi: ... |
1592 1593 |
if (!conn) { reason = FAILURE_SESSION_FREED; |
6eabafbe6 [SCSI] iscsi clas... |
1594 |
sc->result = DID_NO_CONNECT << 16; |
986440479 [SCSI] libiscsi: ... |
1595 1596 |
goto fault; } |
7996a778f [SCSI] iscsi: add... |
1597 |
|
661134ad3 [SCSI] libiscsi, ... |
1598 1599 1600 1601 1602 |
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { reason = FAILURE_SESSION_IN_RECOVERY; sc->result = DID_REQUEUE; goto fault; } |
77a23c21a [SCSI] libiscsi: ... |
1603 1604 1605 1606 |
if (iscsi_check_cmdsn_window_closed(conn)) { reason = FAILURE_WINDOW_CLOSED; goto reject; } |
577577da6 [SCSI] libiscsi: ... |
1607 1608 |
task = iscsi_alloc_task(conn, sc); if (!task) { |
60ecebf5a [SCSI] add refcou... |
1609 1610 1611 |
reason = FAILURE_OOM; goto reject; } |
7996a778f [SCSI] iscsi: add... |
1612 |
|
1336aed10 [SCSI] libiscsi: ... |
1613 |
if (!ihost->workq) { |
577577da6 [SCSI] libiscsi: ... |
1614 1615 |
reason = iscsi_prep_scsi_cmd_pdu(task); if (reason) { |
5d12c05e2 [SCSI] libiscsi: ... |
1616 |
if (reason == -ENOMEM || reason == -EACCES) { |
577577da6 [SCSI] libiscsi: ... |
1617 1618 1619 1620 1621 1622 |
reason = FAILURE_OOM; goto prepd_reject; } else { sc->result = DID_ABORT << 16; goto prepd_fault; } |
052d01448 [SCSI] libiscsi: ... |
1623 |
} |
9c19a7d03 [SCSI] libiscsi: ... |
1624 |
if (session->tt->xmit_task(task)) { |
d3305f340 [SCSI] libiscsi: ... |
1625 |
session->cmdsn--; |
052d01448 [SCSI] libiscsi: ... |
1626 |
reason = FAILURE_SESSION_NOT_READY; |
577577da6 [SCSI] libiscsi: ... |
1627 |
goto prepd_reject; |
052d01448 [SCSI] libiscsi: ... |
1628 |
} |
3bbaaad95 [SCSI] libiscsi: ... |
1629 1630 |
} else { list_add_tail(&task->running, &conn->cmdqueue); |
32ae763e3 [SCSI] iscsi lib:... |
1631 |
iscsi_conn_queue_work(conn); |
3bbaaad95 [SCSI] libiscsi: ... |
1632 |
} |
052d01448 [SCSI] libiscsi: ... |
1633 1634 |
session->queued_cmdsn++; |
f41d47217 [SCSI] libiscsi: ... |
1635 |
spin_unlock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
1636 |
return 0; |
577577da6 [SCSI] libiscsi: ... |
1637 |
prepd_reject: |
f41d47217 [SCSI] libiscsi: ... |
1638 |
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); |
7996a778f [SCSI] iscsi: add... |
1639 |
reject: |
f41d47217 [SCSI] libiscsi: ... |
1640 |
spin_unlock_bh(&session->lock); |
1b2c7af87 [SCSI] libiscsi: ... |
1641 1642 1643 |
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d) ", sc->cmnd[0], reason); |
d6d13ee19 [SCSI] libiscsi: ... |
1644 |
return SCSI_MLQUEUE_TARGET_BUSY; |
7996a778f [SCSI] iscsi: add... |
1645 |
|
577577da6 [SCSI] libiscsi: ... |
1646 |
prepd_fault: |
f41d47217 [SCSI] libiscsi: ... |
1647 |
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); |
7996a778f [SCSI] iscsi: add... |
1648 |
fault: |
f41d47217 [SCSI] libiscsi: ... |
1649 |
spin_unlock_bh(&session->lock); |
1b2c7af87 [SCSI] libiscsi: ... |
1650 1651 1652 |
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d) ", sc->cmnd[0], reason); |
c07d44440 [SCSI] iscsi: bid... |
1653 1654 1655 1656 1657 1658 |
if (!scsi_bidi_cmnd(sc)) scsi_set_resid(sc, scsi_bufflen(sc)); else { scsi_out(sc)->resid = scsi_out(sc)->length; scsi_in(sc)->resid = scsi_in(sc)->length; } |
f41d47217 [SCSI] libiscsi: ... |
1659 |
sc->scsi_done(sc); |
7996a778f [SCSI] iscsi: add... |
1660 1661 1662 |
return 0; } EXPORT_SYMBOL_GPL(iscsi_queuecommand); |
e881a172d [SCSI] modify cha... |
1663 |
int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) |
7996a778f [SCSI] iscsi: add... |
1664 |
{ |
1796e7229 [SCSI] libiscsi: ... |
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 |
switch (reason) { case SCSI_QDEPTH_DEFAULT: scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); break; case SCSI_QDEPTH_QFULL: scsi_track_queue_full(sdev, depth); break; case SCSI_QDEPTH_RAMP_UP: scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); break; default: |
e881a172d [SCSI] modify cha... |
1676 |
return -EOPNOTSUPP; |
1796e7229 [SCSI] libiscsi: ... |
1677 |
} |
7996a778f [SCSI] iscsi: add... |
1678 1679 1680 |
return sdev->queue_depth; } EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); |
6b5d6c443 [SCSI] cxgb3i, is... |
1681 1682 1683 1684 1685 1686 1687 1688 1689 |
int iscsi_target_alloc(struct scsi_target *starget) { struct iscsi_cls_session *cls_session = starget_to_session(starget); struct iscsi_session *session = cls_session->dd_data; starget->can_queue = session->scsi_cmds_max; return 0; } EXPORT_SYMBOL_GPL(iscsi_target_alloc); |
843c0a8a7 [SCSI] libiscsi, ... |
1690 |
static void iscsi_tmf_timedout(unsigned long data) |
7996a778f [SCSI] iscsi: add... |
1691 |
{ |
843c0a8a7 [SCSI] libiscsi, ... |
1692 |
struct iscsi_conn *conn = (struct iscsi_conn *)data; |
7996a778f [SCSI] iscsi: add... |
1693 1694 1695 |
struct iscsi_session *session = conn->session; spin_lock(&session->lock); |
843c0a8a7 [SCSI] libiscsi, ... |
1696 1697 |
if (conn->tmf_state == TMF_QUEUED) { conn->tmf_state = TMF_TIMEDOUT; |
bd2199d41 libiscsi: add con... |
1698 1699 |
ISCSI_DBG_EH(session, "tmf timedout "); |
7996a778f [SCSI] iscsi: add... |
1700 1701 1702 1703 1704 |
/* unblock eh_abort() */ wake_up(&conn->ehwait); } spin_unlock(&session->lock); } |
9c19a7d03 [SCSI] libiscsi: ... |
1705 |
static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, |
f6d5180c7 [SCSI] libiscsi: ... |
1706 1707 |
struct iscsi_tm *hdr, int age, int timeout) |
7996a778f [SCSI] iscsi: add... |
1708 |
{ |
7996a778f [SCSI] iscsi: add... |
1709 |
struct iscsi_session *session = conn->session; |
9c19a7d03 [SCSI] libiscsi: ... |
1710 |
struct iscsi_task *task; |
7996a778f [SCSI] iscsi: add... |
1711 |
|
9c19a7d03 [SCSI] libiscsi: ... |
1712 |
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, |
843c0a8a7 [SCSI] libiscsi, ... |
1713 |
NULL, 0); |
9c19a7d03 [SCSI] libiscsi: ... |
1714 |
if (!task) { |
6724add1b [SCSI] libiscsi: ... |
1715 |
spin_unlock_bh(&session->lock); |
df4da5cdf [SCSI] libiscsi: ... |
1716 1717 |
iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF. "); |
7996a778f [SCSI] iscsi: add... |
1718 |
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
843c0a8a7 [SCSI] libiscsi, ... |
1719 |
spin_lock_bh(&session->lock); |
77a23c21a [SCSI] libiscsi: ... |
1720 |
return -EPERM; |
7996a778f [SCSI] iscsi: add... |
1721 |
} |
843c0a8a7 [SCSI] libiscsi, ... |
1722 |
conn->tmfcmd_pdus_cnt++; |
f6d5180c7 [SCSI] libiscsi: ... |
1723 |
conn->tmf_timer.expires = timeout * HZ + jiffies; |
843c0a8a7 [SCSI] libiscsi, ... |
1724 1725 1726 |
conn->tmf_timer.function = iscsi_tmf_timedout; conn->tmf_timer.data = (unsigned long)conn; add_timer(&conn->tmf_timer); |
bd2199d41 libiscsi: add con... |
1727 1728 |
ISCSI_DBG_EH(session, "tmf set timeout "); |
7996a778f [SCSI] iscsi: add... |
1729 |
|
7996a778f [SCSI] iscsi: add... |
1730 |
spin_unlock_bh(&session->lock); |
6724add1b [SCSI] libiscsi: ... |
1731 |
mutex_unlock(&session->eh_mutex); |
7996a778f [SCSI] iscsi: add... |
1732 1733 1734 1735 |
/* * block eh thread until: * |
843c0a8a7 [SCSI] libiscsi, ... |
1736 1737 |
* 1) tmf response * 2) tmf timeout |
7996a778f [SCSI] iscsi: add... |
1738 1739 1740 |
* 3) session is terminated or restarted or userspace has * given up on recovery */ |
843c0a8a7 [SCSI] libiscsi, ... |
1741 |
wait_event_interruptible(conn->ehwait, age != session->age || |
7996a778f [SCSI] iscsi: add... |
1742 |
session->state != ISCSI_STATE_LOGGED_IN || |
843c0a8a7 [SCSI] libiscsi, ... |
1743 |
conn->tmf_state != TMF_QUEUED); |
7996a778f [SCSI] iscsi: add... |
1744 1745 |
if (signal_pending(current)) flush_signals(current); |
843c0a8a7 [SCSI] libiscsi, ... |
1746 |
del_timer_sync(&conn->tmf_timer); |
6724add1b [SCSI] libiscsi: ... |
1747 |
mutex_lock(&session->eh_mutex); |
77a23c21a [SCSI] libiscsi: ... |
1748 |
spin_lock_bh(&session->lock); |
9c19a7d03 [SCSI] libiscsi: ... |
1749 |
/* if the session drops it will clean up the task */ |
843c0a8a7 [SCSI] libiscsi, ... |
1750 1751 1752 |
if (age != session->age || session->state != ISCSI_STATE_LOGGED_IN) return -ENOTCONN; |
7996a778f [SCSI] iscsi: add... |
1753 1754 1755 1756 |
return 0; } /* |
843c0a8a7 [SCSI] libiscsi, ... |
1757 1758 1759 |
* Fail commands. session lock held and recv side suspended and xmit * thread flushed */ |
3bbaaad95 [SCSI] libiscsi: ... |
1760 1761 |
static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, int error) |
843c0a8a7 [SCSI] libiscsi, ... |
1762 |
{ |
3bbaaad95 [SCSI] libiscsi: ... |
1763 1764 |
struct iscsi_task *task; int i; |
843c0a8a7 [SCSI] libiscsi, ... |
1765 |
|
3bbaaad95 [SCSI] libiscsi: ... |
1766 1767 1768 1769 |
for (i = 0; i < conn->session->cmds_max; i++) { task = conn->session->cmds[i]; if (!task->sc || task->state == ISCSI_TASK_FREE) continue; |
843c0a8a7 [SCSI] libiscsi, ... |
1770 |
|
3bbaaad95 [SCSI] libiscsi: ... |
1771 1772 |
if (lun != -1 && lun != task->sc->device->lun) continue; |
843c0a8a7 [SCSI] libiscsi, ... |
1773 |
|
3bbaaad95 [SCSI] libiscsi: ... |
1774 1775 1776 1777 |
ISCSI_DBG_SESSION(conn->session, "failing sc %p itt 0x%x state %d ", task->sc, task->itt, task->state); |
b3cd5050b [SCSI] libiscsi: ... |
1778 |
fail_scsi_task(task, error); |
843c0a8a7 [SCSI] libiscsi, ... |
1779 1780 |
} } |
661134ad3 [SCSI] libiscsi, ... |
1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 |
/** * iscsi_suspend_queue - suspend iscsi_queuecommand * @conn: iscsi conn to stop queueing IO on * * This grabs the session lock to make sure no one is in * xmit_task/queuecommand, and then sets suspend to prevent * new commands from being queued. This only needs to be called * by offload drivers that need to sync a path like ep disconnect * with the iscsi_queuecommand/xmit_task. To start IO again libiscsi * will call iscsi_start_tx and iscsi_unblock_session when in FFP. */ void iscsi_suspend_queue(struct iscsi_conn *conn) { spin_lock_bh(&conn->session->lock); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); spin_unlock_bh(&conn->session->lock); } EXPORT_SYMBOL_GPL(iscsi_suspend_queue); /** * iscsi_suspend_tx - suspend iscsi_data_xmit * @conn: iscsi conn tp stop processing IO on. * * This function sets the suspend bit to prevent iscsi_data_xmit * from sending new IO, and if work is queued on the xmit thread * it will wait for it to be completed. */ |
b40977d95 [SCSI] iser: fix ... |
1808 |
void iscsi_suspend_tx(struct iscsi_conn *conn) |
6724add1b [SCSI] libiscsi: ... |
1809 |
{ |
32ae763e3 [SCSI] iscsi lib:... |
1810 1811 |
struct Scsi_Host *shost = conn->session->host; struct iscsi_host *ihost = shost_priv(shost); |
6724add1b [SCSI] libiscsi: ... |
1812 |
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1336aed10 [SCSI] libiscsi: ... |
1813 |
if (ihost->workq) |
32ae763e3 [SCSI] iscsi lib:... |
1814 |
flush_workqueue(ihost->workq); |
6724add1b [SCSI] libiscsi: ... |
1815 |
} |
b40977d95 [SCSI] iser: fix ... |
1816 |
EXPORT_SYMBOL_GPL(iscsi_suspend_tx); |
6724add1b [SCSI] libiscsi: ... |
1817 1818 1819 1820 |
static void iscsi_start_tx(struct iscsi_conn *conn) { clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1336aed10 [SCSI] libiscsi: ... |
1821 |
iscsi_conn_queue_work(conn); |
6724add1b [SCSI] libiscsi: ... |
1822 |
} |
4c48a8293 [SCSI] libiscsi: ... |
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 |
/* * We want to make sure a ping is in flight. It has timed out. * And we are not busy processing a pdu that is making * progress but got started before the ping and is taking a while * to complete so the ping is just stuck behind it in a queue. */ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) { if (conn->ping_task && time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) return 1; else return 0; } |
d355e57d5 libiscsi: don't r... |
1838 |
static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) |
f6d5180c7 [SCSI] libiscsi: ... |
1839 |
{ |
d355e57d5 libiscsi: don't r... |
1840 |
enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; |
92ed4d699 [SCSI] libiscsi: ... |
1841 |
struct iscsi_task *task = NULL, *running_task; |
f6d5180c7 [SCSI] libiscsi: ... |
1842 1843 1844 |
struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; |
92ed4d699 [SCSI] libiscsi: ... |
1845 |
int i; |
f6d5180c7 [SCSI] libiscsi: ... |
1846 |
|
d355e57d5 libiscsi: don't r... |
1847 |
cls_session = starget_to_session(scsi_target(sc->device)); |
756135215 [SCSI] iscsi: rem... |
1848 |
session = cls_session->dd_data; |
f6d5180c7 [SCSI] libiscsi: ... |
1849 |
|
bd2199d41 libiscsi: add con... |
1850 1851 |
ISCSI_DBG_EH(session, "scsi cmd %p timedout ", sc); |
f6d5180c7 [SCSI] libiscsi: ... |
1852 1853 1854 1855 1856 1857 1858 |
spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { /* * We are probably in the middle of iscsi recovery so let * that complete and handle the error. */ |
242f9dcb8 block: unify requ... |
1859 |
rc = BLK_EH_RESET_TIMER; |
f6d5180c7 [SCSI] libiscsi: ... |
1860 1861 1862 1863 1864 1865 |
goto done; } conn = session->leadconn; if (!conn) { /* In the middle of shuting down */ |
242f9dcb8 block: unify requ... |
1866 |
rc = BLK_EH_RESET_TIMER; |
f6d5180c7 [SCSI] libiscsi: ... |
1867 1868 |
goto done; } |
d355e57d5 libiscsi: don't r... |
1869 |
task = (struct iscsi_task *)sc->SCp.ptr; |
92ed4d699 [SCSI] libiscsi: ... |
1870 1871 1872 1873 1874 1875 |
if (!task) { /* * Raced with completion. Just reset timer, and let it * complete normally */ rc = BLK_EH_RESET_TIMER; |
d355e57d5 libiscsi: don't r... |
1876 |
goto done; |
92ed4d699 [SCSI] libiscsi: ... |
1877 |
} |
d355e57d5 libiscsi: don't r... |
1878 1879 1880 1881 1882 1883 1884 |
/* * If we have sent (at least queued to the network layer) a pdu or * recvd one for the task since the last timeout ask for * more time. If on the next timeout we have not made progress * we can check if it is the task or connection when we send the * nop as a ping. */ |
92ed4d699 [SCSI] libiscsi: ... |
1885 |
if (time_after(task->last_xfer, task->last_timeout)) { |
bd2199d41 libiscsi: add con... |
1886 1887 |
ISCSI_DBG_EH(session, "Command making progress. Asking " "scsi-ml for more time to complete. " |
92ed4d699 [SCSI] libiscsi: ... |
1888 |
"Last data xfer at %lu. Last timeout was at " |
bd2199d41 libiscsi: add con... |
1889 1890 |
"%lu .", task->last_xfer, task->last_timeout); |
d355e57d5 libiscsi: don't r... |
1891 1892 1893 1894 |
task->have_checked_conn = false; rc = BLK_EH_RESET_TIMER; goto done; } |
f6d5180c7 [SCSI] libiscsi: ... |
1895 1896 1897 1898 1899 1900 |
if (!conn->recv_timeout && !conn->ping_timeout) goto done; /* * if the ping timedout then we are in the middle of cleaning up * and can let the iscsi eh handle it */ |
4c48a8293 [SCSI] libiscsi: ... |
1901 |
if (iscsi_has_ping_timed_out(conn)) { |
242f9dcb8 block: unify requ... |
1902 |
rc = BLK_EH_RESET_TIMER; |
4c48a8293 [SCSI] libiscsi: ... |
1903 1904 |
goto done; } |
d355e57d5 libiscsi: don't r... |
1905 |
|
92ed4d699 [SCSI] libiscsi: ... |
1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 |
for (i = 0; i < conn->session->cmds_max; i++) { running_task = conn->session->cmds[i]; if (!running_task->sc || running_task == task || running_task->state != ISCSI_TASK_RUNNING) continue; /* * Only check if cmds started before this one have made * progress, or this could never fail */ if (time_after(running_task->sc->jiffies_at_alloc, task->sc->jiffies_at_alloc)) continue; if (time_after(running_task->last_xfer, task->last_timeout)) { /* * This task has not made progress, but a task * started before us has transferred data since * we started/last-checked. We could be queueing * too many tasks or the LU is bad. * * If the device is bad the cmds ahead of us on * other devs will complete, and this loop will * eventually fail starting the scsi eh. */ ISCSI_DBG_EH(session, "Command has not made progress " "but commands ahead of it have. " "Asking scsi-ml for more time to " "complete. Our last xfer vs running task " "last xfer %lu/%lu. Last check %lu. ", task->last_xfer, running_task->last_xfer, task->last_timeout); rc = BLK_EH_RESET_TIMER; goto done; } } |
d355e57d5 libiscsi: don't r... |
1943 1944 1945 |
/* Assumes nop timeout is shorter than scsi cmd timeout */ if (task->have_checked_conn) goto done; |
f6d5180c7 [SCSI] libiscsi: ... |
1946 |
/* |
d355e57d5 libiscsi: don't r... |
1947 1948 |
* Checking the transport already or nop from a cmd timeout still * running |
f6d5180c7 [SCSI] libiscsi: ... |
1949 |
*/ |
d355e57d5 libiscsi: don't r... |
1950 1951 |
if (conn->ping_task) { task->have_checked_conn = true; |
242f9dcb8 block: unify requ... |
1952 |
rc = BLK_EH_RESET_TIMER; |
4c48a8293 [SCSI] libiscsi: ... |
1953 1954 |
goto done; } |
d355e57d5 libiscsi: don't r... |
1955 1956 1957 1958 |
/* Make sure there is a transport check done */ iscsi_send_nopout(conn, NULL); task->have_checked_conn = true; rc = BLK_EH_RESET_TIMER; |
f6d5180c7 [SCSI] libiscsi: ... |
1959 |
done: |
d355e57d5 libiscsi: don't r... |
1960 1961 |
if (task) task->last_timeout = jiffies; |
f6d5180c7 [SCSI] libiscsi: ... |
1962 |
spin_unlock(&session->lock); |
bd2199d41 libiscsi: add con... |
1963 1964 1965 |
ISCSI_DBG_EH(session, "return %s ", rc == BLK_EH_RESET_TIMER ? "timer reset" : "nh"); |
f6d5180c7 [SCSI] libiscsi: ... |
1966 1967 1968 1969 1970 1971 1972 |
return rc; } static void iscsi_check_transport_timeouts(unsigned long data) { struct iscsi_conn *conn = (struct iscsi_conn *)data; struct iscsi_session *session = conn->session; |
4cf104359 [SCSI] libiscsi r... |
1973 |
unsigned long recv_timeout, next_timeout = 0, last_recv; |
f6d5180c7 [SCSI] libiscsi: ... |
1974 1975 1976 1977 |
spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) goto done; |
4cf104359 [SCSI] libiscsi r... |
1978 1979 |
recv_timeout = conn->recv_timeout; if (!recv_timeout) |
f6d5180c7 [SCSI] libiscsi: ... |
1980 |
goto done; |
4cf104359 [SCSI] libiscsi r... |
1981 |
recv_timeout *= HZ; |
f6d5180c7 [SCSI] libiscsi: ... |
1982 |
last_recv = conn->last_recv; |
4c48a8293 [SCSI] libiscsi: ... |
1983 1984 |
if (iscsi_has_ping_timed_out(conn)) { |
322d739da [SCSI] iscsi: fix... |
1985 |
iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " |
4c48a8293 [SCSI] libiscsi: ... |
1986 1987 1988 1989 1990 |
"expired, recv timeout %d, last rx %lu, " "last ping %lu, now %lu ", conn->ping_timeout, conn->recv_timeout, last_recv, conn->last_ping, jiffies); |
f6d5180c7 [SCSI] libiscsi: ... |
1991 1992 1993 1994 |
spin_unlock(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); return; } |
4cf104359 [SCSI] libiscsi r... |
1995 |
if (time_before_eq(last_recv + recv_timeout, jiffies)) { |
c8611f975 [SCSI] libiscsi r... |
1996 |
/* send a ping to try to provoke some traffic */ |
1b2c7af87 [SCSI] libiscsi: ... |
1997 1998 |
ISCSI_DBG_CONN(conn, "Sending nopout as ping "); |
c8611f975 [SCSI] libiscsi r... |
1999 |
iscsi_send_nopout(conn, NULL); |
4cf104359 [SCSI] libiscsi r... |
2000 |
next_timeout = conn->last_ping + (conn->ping_timeout * HZ); |
ad294e9cd [SCSI] libiscsi: ... |
2001 |
} else |
4cf104359 [SCSI] libiscsi r... |
2002 |
next_timeout = last_recv + recv_timeout; |
f6d5180c7 [SCSI] libiscsi: ... |
2003 |
|
1b2c7af87 [SCSI] libiscsi: ... |
2004 2005 |
ISCSI_DBG_CONN(conn, "Setting next tmo %lu ", next_timeout); |
ad294e9cd [SCSI] libiscsi: ... |
2006 |
mod_timer(&conn->transport_timer, next_timeout); |
f6d5180c7 [SCSI] libiscsi: ... |
2007 2008 2009 |
done: spin_unlock(&session->lock); } |
9c19a7d03 [SCSI] libiscsi: ... |
2010 |
static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, |
843c0a8a7 [SCSI] libiscsi, ... |
2011 2012 2013 2014 2015 2016 |
struct iscsi_tm *hdr) { memset(hdr, 0, sizeof(*hdr)); hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
55bdabdf4 iscsi: Use struct... |
2017 |
hdr->lun = task->lun; |
577577da6 [SCSI] libiscsi: ... |
2018 2019 |
hdr->rtt = task->hdr_itt; hdr->refcmdsn = task->cmdsn; |
843c0a8a7 [SCSI] libiscsi, ... |
2020 |
} |
7996a778f [SCSI] iscsi: add... |
2021 2022 |
int iscsi_eh_abort(struct scsi_cmnd *sc) { |
756135215 [SCSI] iscsi: rem... |
2023 2024 |
struct iscsi_cls_session *cls_session; struct iscsi_session *session; |
f47f2cf5d [SCSI] libiscsi: ... |
2025 |
struct iscsi_conn *conn; |
9c19a7d03 [SCSI] libiscsi: ... |
2026 |
struct iscsi_task *task; |
843c0a8a7 [SCSI] libiscsi, ... |
2027 2028 |
struct iscsi_tm *hdr; int rc, age; |
7996a778f [SCSI] iscsi: add... |
2029 |
|
756135215 [SCSI] iscsi: rem... |
2030 2031 |
cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; |
bd2199d41 libiscsi: add con... |
2032 2033 |
ISCSI_DBG_EH(session, "aborting sc %p ", sc); |
4421c9ebe [SCSI] libiscsi: ... |
2034 |
|
6724add1b [SCSI] libiscsi: ... |
2035 2036 |
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); |
f47f2cf5d [SCSI] libiscsi: ... |
2037 2038 2039 2040 2041 |
/* * if session was ISCSI_STATE_IN_RECOVERY then we may not have * got the command. */ if (!sc->SCp.ptr) { |
bd2199d41 libiscsi: add con... |
2042 2043 2044 |
ISCSI_DBG_EH(session, "sc never reached iscsi layer or " "it completed. "); |
6724add1b [SCSI] libiscsi: ... |
2045 2046 |
spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); |
f47f2cf5d [SCSI] libiscsi: ... |
2047 2048 |
return SUCCESS; } |
7996a778f [SCSI] iscsi: add... |
2049 2050 2051 2052 |
/* * If we are not logged in or we have started a new session * then let the host reset code handle this */ |
843c0a8a7 [SCSI] libiscsi, ... |
2053 2054 2055 2056 |
if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN || sc->SCp.phase != session->age) { spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); |
bd2199d41 libiscsi: add con... |
2057 |
ISCSI_DBG_EH(session, "failing abort due to dropped " |
4421c9ebe [SCSI] libiscsi: ... |
2058 2059 |
"session. "); |
843c0a8a7 [SCSI] libiscsi, ... |
2060 2061 2062 2063 2064 2065 |
return FAILED; } conn = session->leadconn; conn->eh_abort_cnt++; age = session->age; |
9c19a7d03 [SCSI] libiscsi: ... |
2066 |
task = (struct iscsi_task *)sc->SCp.ptr; |
bd2199d41 libiscsi: add con... |
2067 2068 2069 |
ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x] ", sc, task->itt); |
7996a778f [SCSI] iscsi: add... |
2070 |
|
9c19a7d03 [SCSI] libiscsi: ... |
2071 2072 |
/* task completed before time out */ if (!task->sc) { |
bd2199d41 libiscsi: add con... |
2073 2074 |
ISCSI_DBG_EH(session, "sc completed while abort in progress "); |
77a23c21a [SCSI] libiscsi: ... |
2075 |
goto success; |
7ea8b8284 [SCSI] iscsi bugf... |
2076 |
} |
7996a778f [SCSI] iscsi: add... |
2077 |
|
9c19a7d03 [SCSI] libiscsi: ... |
2078 |
if (task->state == ISCSI_TASK_PENDING) { |
b3cd5050b [SCSI] libiscsi: ... |
2079 |
fail_scsi_task(task, DID_ABORT); |
77a23c21a [SCSI] libiscsi: ... |
2080 2081 |
goto success; } |
7996a778f [SCSI] iscsi: add... |
2082 |
|
843c0a8a7 [SCSI] libiscsi, ... |
2083 2084 |
/* only have one tmf outstanding at a time */ if (conn->tmf_state != TMF_INITIAL) |
7996a778f [SCSI] iscsi: add... |
2085 |
goto failed; |
843c0a8a7 [SCSI] libiscsi, ... |
2086 |
conn->tmf_state = TMF_QUEUED; |
7996a778f [SCSI] iscsi: add... |
2087 |
|
843c0a8a7 [SCSI] libiscsi, ... |
2088 |
hdr = &conn->tmhdr; |
9c19a7d03 [SCSI] libiscsi: ... |
2089 |
iscsi_prep_abort_task_pdu(task, hdr); |
843c0a8a7 [SCSI] libiscsi, ... |
2090 |
|
9c19a7d03 [SCSI] libiscsi: ... |
2091 |
if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { |
843c0a8a7 [SCSI] libiscsi, ... |
2092 2093 2094 2095 2096 2097 |
rc = FAILED; goto failed; } switch (conn->tmf_state) { case TMF_SUCCESS: |
77a23c21a [SCSI] libiscsi: ... |
2098 |
spin_unlock_bh(&session->lock); |
913e5bf43 [SCSI] libiscsi, ... |
2099 2100 2101 2102 |
/* * stop tx side incase the target had sent a abort rsp but * the initiator was still writing out data. */ |
6724add1b [SCSI] libiscsi: ... |
2103 |
iscsi_suspend_tx(conn); |
77a23c21a [SCSI] libiscsi: ... |
2104 |
/* |
913e5bf43 [SCSI] libiscsi, ... |
2105 2106 2107 |
* we do not stop the recv side because targets have been * good and have never sent us a successful tmf response * then sent more data for the cmd. |
77a23c21a [SCSI] libiscsi: ... |
2108 |
*/ |
6187c2420 [SCSI] libiscsi: ... |
2109 |
spin_lock_bh(&session->lock); |
b3cd5050b [SCSI] libiscsi: ... |
2110 |
fail_scsi_task(task, DID_ABORT); |
843c0a8a7 [SCSI] libiscsi, ... |
2111 |
conn->tmf_state = TMF_INITIAL; |
5d12c05e2 [SCSI] libiscsi: ... |
2112 |
memset(hdr, 0, sizeof(*hdr)); |
6187c2420 [SCSI] libiscsi: ... |
2113 |
spin_unlock_bh(&session->lock); |
6724add1b [SCSI] libiscsi: ... |
2114 |
iscsi_start_tx(conn); |
77a23c21a [SCSI] libiscsi: ... |
2115 |
goto success_unlocked; |
843c0a8a7 [SCSI] libiscsi, ... |
2116 2117 |
case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); |
df4da5cdf [SCSI] libiscsi: ... |
2118 |
iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); |
843c0a8a7 [SCSI] libiscsi, ... |
2119 2120 2121 2122 |
goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { conn->tmf_state = TMF_INITIAL; |
5d12c05e2 [SCSI] libiscsi: ... |
2123 |
memset(hdr, 0, sizeof(*hdr)); |
9c19a7d03 [SCSI] libiscsi: ... |
2124 |
/* task completed before tmf abort response */ |
bd2199d41 libiscsi: add con... |
2125 2126 2127 |
ISCSI_DBG_EH(session, "sc completed while abort in " "progress "); |
77a23c21a [SCSI] libiscsi: ... |
2128 |
goto success; |
7ea8b8284 [SCSI] iscsi bugf... |
2129 2130 2131 |
} /* fall through */ default: |
843c0a8a7 [SCSI] libiscsi, ... |
2132 2133 |
conn->tmf_state = TMF_INITIAL; goto failed; |
7996a778f [SCSI] iscsi: add... |
2134 |
} |
77a23c21a [SCSI] libiscsi: ... |
2135 |
success: |
7996a778f [SCSI] iscsi: add... |
2136 |
spin_unlock_bh(&session->lock); |
77a23c21a [SCSI] libiscsi: ... |
2137 |
success_unlocked: |
bd2199d41 libiscsi: add con... |
2138 2139 2140 |
ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x] ", sc, task->itt); |
6724add1b [SCSI] libiscsi: ... |
2141 |
mutex_unlock(&session->eh_mutex); |
7996a778f [SCSI] iscsi: add... |
2142 2143 2144 2145 |
return SUCCESS; failed: spin_unlock_bh(&session->lock); |
77a23c21a [SCSI] libiscsi: ... |
2146 |
failed_unlocked: |
bd2199d41 libiscsi: add con... |
2147 2148 2149 |
ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x] ", sc, task ? task->itt : 0); |
6724add1b [SCSI] libiscsi: ... |
2150 |
mutex_unlock(&session->eh_mutex); |
7996a778f [SCSI] iscsi: add... |
2151 2152 2153 |
return FAILED; } EXPORT_SYMBOL_GPL(iscsi_eh_abort); |
843c0a8a7 [SCSI] libiscsi, ... |
2154 2155 2156 2157 2158 2159 |
static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) { memset(hdr, 0, sizeof(*hdr)); hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
55bdabdf4 iscsi: Use struct... |
2160 |
int_to_scsilun(sc->device->lun, &hdr->lun); |
f6d5180c7 [SCSI] libiscsi: ... |
2161 |
hdr->rtt = RESERVED_ITT; |
843c0a8a7 [SCSI] libiscsi, ... |
2162 2163 2164 2165 |
} int iscsi_eh_device_reset(struct scsi_cmnd *sc) { |
756135215 [SCSI] iscsi: rem... |
2166 2167 |
struct iscsi_cls_session *cls_session; struct iscsi_session *session; |
843c0a8a7 [SCSI] libiscsi, ... |
2168 2169 2170 |
struct iscsi_conn *conn; struct iscsi_tm *hdr; int rc = FAILED; |
756135215 [SCSI] iscsi: rem... |
2171 2172 |
cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; |
bd2199d41 libiscsi: add con... |
2173 2174 |
ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u] ", sc, sc->device->lun); |
843c0a8a7 [SCSI] libiscsi, ... |
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 |
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); /* * Just check if we are not logged in. We cannot check for * the phase because the reset could come from a ioctl. */ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) goto unlock; conn = session->leadconn; /* only have one tmf outstanding at a time */ if (conn->tmf_state != TMF_INITIAL) goto unlock; conn->tmf_state = TMF_QUEUED; hdr = &conn->tmhdr; iscsi_prep_lun_reset_pdu(sc, hdr); |
9c19a7d03 [SCSI] libiscsi: ... |
2193 |
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, |
f6d5180c7 [SCSI] libiscsi: ... |
2194 |
session->lu_reset_timeout)) { |
843c0a8a7 [SCSI] libiscsi, ... |
2195 2196 2197 2198 2199 2200 2201 2202 2203 |
rc = FAILED; goto unlock; } switch (conn->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); |
df4da5cdf [SCSI] libiscsi: ... |
2204 |
iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); |
843c0a8a7 [SCSI] libiscsi, ... |
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 |
goto done; default: conn->tmf_state = TMF_INITIAL; goto unlock; } rc = SUCCESS; spin_unlock_bh(&session->lock); iscsi_suspend_tx(conn); |
913e5bf43 [SCSI] libiscsi, ... |
2215 |
|
a34391483 libiscsi: fix loc... |
2216 |
spin_lock_bh(&session->lock); |
5d12c05e2 [SCSI] libiscsi: ... |
2217 |
memset(hdr, 0, sizeof(*hdr)); |
3bbaaad95 [SCSI] libiscsi: ... |
2218 |
fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); |
843c0a8a7 [SCSI] libiscsi, ... |
2219 |
conn->tmf_state = TMF_INITIAL; |
a34391483 libiscsi: fix loc... |
2220 |
spin_unlock_bh(&session->lock); |
843c0a8a7 [SCSI] libiscsi, ... |
2221 2222 2223 2224 2225 2226 2227 |
iscsi_start_tx(conn); goto done; unlock: spin_unlock_bh(&session->lock); done: |
bd2199d41 libiscsi: add con... |
2228 2229 2230 |
ISCSI_DBG_EH(session, "dev reset result = %s ", rc == SUCCESS ? "SUCCESS" : "FAILED"); |
843c0a8a7 [SCSI] libiscsi, ... |
2231 2232 2233 2234 |
mutex_unlock(&session->eh_mutex); return rc; } EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 |
void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = cls_session->dd_data; spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; if (session->leadconn) wake_up(&session->leadconn->ehwait); } spin_unlock_bh(&session->lock); } EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); /** * iscsi_eh_session_reset - drop session and attempt relogin * @sc: scsi command * * This function will wait for a relogin, session termination from * userspace, or a recovery/replacement timeout. */ |
309ce156a [SCSI] libiscsi: ... |
2256 |
int iscsi_eh_session_reset(struct scsi_cmnd *sc) |
3fe5ae8b4 [SCSI] libiscsi: ... |
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 |
{ struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; conn = session->leadconn; mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { failed: ISCSI_DBG_EH(session, "failing session reset: Could not log back into " "%s, %s [age %d] ", session->targetname, conn->persistent_address, session->age); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return FAILED; } spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); /* * we drop the lock here but the leadconn cannot be destoyed while * we are in the scsi eh */ |
df4da5cdf [SCSI] libiscsi: ... |
2286 |
iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 |
ISCSI_DBG_EH(session, "wait for relogin "); wait_event_interruptible(conn->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || session->state == ISCSI_STATE_RECOVERY_FAILED); if (signal_pending(current)) flush_signals(current); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_LOGGED_IN) { ISCSI_DBG_EH(session, "session reset succeeded for %s,%s ", session->targetname, conn->persistent_address); } else goto failed; spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return SUCCESS; } |
309ce156a [SCSI] libiscsi: ... |
2310 |
EXPORT_SYMBOL_GPL(iscsi_eh_session_reset); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 |
static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) { memset(hdr, 0, sizeof(*hdr)); hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; hdr->flags = ISCSI_TM_FUNC_TARGET_WARM_RESET & ISCSI_FLAG_TM_FUNC_MASK; hdr->flags |= ISCSI_FLAG_CMD_FINAL; hdr->rtt = RESERVED_ITT; } /** * iscsi_eh_target_reset - reset target * @sc: scsi command * |
309ce156a [SCSI] libiscsi: ... |
2325 |
* This will attempt to send a warm target reset. |
3fe5ae8b4 [SCSI] libiscsi: ... |
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 |
*/ int iscsi_eh_target_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_tm *hdr; int rc = FAILED; cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; ISCSI_DBG_EH(session, "tgt Reset [sc %p tgt %s] ", sc, session->targetname); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); /* * Just check if we are not logged in. We cannot check for * the phase because the reset could come from a ioctl. */ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) goto unlock; conn = session->leadconn; /* only have one tmf outstanding at a time */ if (conn->tmf_state != TMF_INITIAL) goto unlock; conn->tmf_state = TMF_QUEUED; hdr = &conn->tmhdr; iscsi_prep_tgt_reset_pdu(sc, hdr); if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, session->tgt_reset_timeout)) { rc = FAILED; goto unlock; } switch (conn->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); |
df4da5cdf [SCSI] libiscsi: ... |
2371 |
iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 |
goto done; default: conn->tmf_state = TMF_INITIAL; goto unlock; } rc = SUCCESS; spin_unlock_bh(&session->lock); iscsi_suspend_tx(conn); spin_lock_bh(&session->lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, -1, DID_ERROR); conn->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->lock); iscsi_start_tx(conn); goto done; unlock: spin_unlock_bh(&session->lock); done: ISCSI_DBG_EH(session, "tgt %s reset result = %s ", session->targetname, rc == SUCCESS ? "SUCCESS" : "FAILED"); mutex_unlock(&session->eh_mutex); |
309ce156a [SCSI] libiscsi: ... |
2399 2400 2401 |
return rc; } EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2402 |
|
309ce156a [SCSI] libiscsi: ... |
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 |
/** * iscsi_eh_recover_target - reset target and possibly the session * @sc: scsi command * * This will attempt to send a warm target reset. If that fails, * we will escalate to ERL0 session recovery. */ int iscsi_eh_recover_target(struct scsi_cmnd *sc) { int rc; rc = iscsi_eh_target_reset(sc); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2415 2416 2417 2418 |
if (rc == FAILED) rc = iscsi_eh_session_reset(sc); return rc; } |
309ce156a [SCSI] libiscsi: ... |
2419 |
EXPORT_SYMBOL_GPL(iscsi_eh_recover_target); |
3fe5ae8b4 [SCSI] libiscsi: ... |
2420 |
|
6320377fd [SCSI] libiscsi, ... |
2421 2422 2423 2424 2425 2426 |
/* * Pre-allocate a pool of @max items of @item_size. By default, the pool * should be accessed via kfifo_{get,put} on q->queue. * Optionally, the caller can obtain the array of object pointers * by passing in a non-NULL @items pointer */ |
7996a778f [SCSI] iscsi: add... |
2427 |
int |
6320377fd [SCSI] libiscsi, ... |
2428 |
iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) |
7996a778f [SCSI] iscsi: add... |
2429 |
{ |
6320377fd [SCSI] libiscsi, ... |
2430 |
int i, num_arrays = 1; |
7996a778f [SCSI] iscsi: add... |
2431 |
|
6320377fd [SCSI] libiscsi, ... |
2432 |
memset(q, 0, sizeof(*q)); |
7996a778f [SCSI] iscsi: add... |
2433 2434 |
q->max = max; |
6320377fd [SCSI] libiscsi, ... |
2435 2436 2437 2438 2439 2440 2441 |
/* If the user passed an items pointer, he wants a copy of * the array. */ if (items) num_arrays++; q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL); if (q->pool == NULL) |
f474a37bc [SCSI] libiscsi: ... |
2442 |
return -ENOMEM; |
7996a778f [SCSI] iscsi: add... |
2443 |
|
c1e13f256 kfifo: move out s... |
2444 |
kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*)); |
7996a778f [SCSI] iscsi: add... |
2445 2446 |
for (i = 0; i < max; i++) { |
6320377fd [SCSI] libiscsi, ... |
2447 |
q->pool[i] = kzalloc(item_size, GFP_KERNEL); |
7996a778f [SCSI] iscsi: add... |
2448 |
if (q->pool[i] == NULL) { |
6320377fd [SCSI] libiscsi, ... |
2449 2450 |
q->max = i; goto enomem; |
7996a778f [SCSI] iscsi: add... |
2451 |
} |
7acd72eb8 kfifo: rename kfi... |
2452 |
kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*)); |
7996a778f [SCSI] iscsi: add... |
2453 |
} |
6320377fd [SCSI] libiscsi, ... |
2454 2455 2456 2457 2458 |
if (items) { *items = q->pool + max; memcpy(*items, q->pool, max * sizeof(void *)); } |
7996a778f [SCSI] iscsi: add... |
2459 |
return 0; |
6320377fd [SCSI] libiscsi, ... |
2460 2461 2462 2463 |
enomem: iscsi_pool_free(q); return -ENOMEM; |
7996a778f [SCSI] iscsi: add... |
2464 2465 |
} EXPORT_SYMBOL_GPL(iscsi_pool_init); |
6320377fd [SCSI] libiscsi, ... |
2466 |
void iscsi_pool_free(struct iscsi_pool *q) |
7996a778f [SCSI] iscsi: add... |
2467 2468 2469 2470 |
{ int i; for (i = 0; i < q->max; i++) |
6320377fd [SCSI] libiscsi, ... |
2471 |
kfree(q->pool[i]); |
f474a37bc [SCSI] libiscsi: ... |
2472 |
kfree(q->pool); |
7996a778f [SCSI] iscsi: add... |
2473 2474 |
} EXPORT_SYMBOL_GPL(iscsi_pool_free); |
a4804cd6e [SCSI] iscsi: add... |
2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 |
/** * iscsi_host_add - add host to system * @shost: scsi host * @pdev: parent device * * This should be called by partial offload and software iscsi drivers * to add a host to the system. */ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) { |
8e9a20cee [SCSI] libiscsi, ... |
2485 2486 |
if (!shost->can_queue) shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX; |
4d1083509 [SCSI] iscsi lib:... |
2487 2488 |
if (!shost->cmd_per_lun) shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN; |
308cec14e [SCSI] libiscsi: ... |
2489 2490 |
if (!shost->transportt->eh_timed_out) shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; |
a4804cd6e [SCSI] iscsi: add... |
2491 2492 2493 2494 2495 2496 2497 2498 |
return scsi_add_host(shost, pdev); } EXPORT_SYMBOL_GPL(iscsi_host_add); /** * iscsi_host_alloc - allocate a host and driver data * @sht: scsi host template * @dd_data_size: driver host data size |
32ae763e3 [SCSI] iscsi lib:... |
2499 |
* @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue |
a4804cd6e [SCSI] iscsi: add... |
2500 2501 2502 2503 2504 |
* * This should be called by partial offload and software iscsi drivers. * To access the driver specific memory use the iscsi_host_priv() macro. */ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, |
4d1083509 [SCSI] iscsi lib:... |
2505 |
int dd_data_size, bool xmit_can_sleep) |
756135215 [SCSI] iscsi: rem... |
2506 |
{ |
a4804cd6e [SCSI] iscsi: add... |
2507 |
struct Scsi_Host *shost; |
e5bd7b54e [SCSI] libiscsi: ... |
2508 |
struct iscsi_host *ihost; |
a4804cd6e [SCSI] iscsi: add... |
2509 2510 2511 2512 |
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size); if (!shost) return NULL; |
e5bd7b54e [SCSI] libiscsi: ... |
2513 |
ihost = shost_priv(shost); |
32ae763e3 [SCSI] iscsi lib:... |
2514 2515 2516 2517 2518 2519 2520 2521 |
if (xmit_can_sleep) { snprintf(ihost->workq_name, sizeof(ihost->workq_name), "iscsi_q_%d", shost->host_no); ihost->workq = create_singlethread_workqueue(ihost->workq_name); if (!ihost->workq) goto free_host; } |
e5bd7b54e [SCSI] libiscsi: ... |
2522 2523 2524 2525 |
spin_lock_init(&ihost->lock); ihost->state = ISCSI_HOST_SETUP; ihost->num_sessions = 0; init_waitqueue_head(&ihost->session_removal_wq); |
a4804cd6e [SCSI] iscsi: add... |
2526 |
return shost; |
32ae763e3 [SCSI] iscsi lib:... |
2527 2528 2529 2530 |
free_host: scsi_host_put(shost); return NULL; |
a4804cd6e [SCSI] iscsi: add... |
2531 2532 |
} EXPORT_SYMBOL_GPL(iscsi_host_alloc); |
e5bd7b54e [SCSI] libiscsi: ... |
2533 2534 |
static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session) { |
40a06e755 [SCSI] libiscsi: ... |
2535 |
iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_INVALID_HOST); |
e5bd7b54e [SCSI] libiscsi: ... |
2536 |
} |
a4804cd6e [SCSI] iscsi: add... |
2537 2538 2539 2540 |
/** * iscsi_host_remove - remove host and sessions * @shost: scsi host * |
e5bd7b54e [SCSI] libiscsi: ... |
2541 2542 |
* If there are any sessions left, this will initiate the removal and wait * for the completion. |
a4804cd6e [SCSI] iscsi: add... |
2543 2544 2545 |
*/ void iscsi_host_remove(struct Scsi_Host *shost) { |
e5bd7b54e [SCSI] libiscsi: ... |
2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 |
struct iscsi_host *ihost = shost_priv(shost); unsigned long flags; spin_lock_irqsave(&ihost->lock, flags); ihost->state = ISCSI_HOST_REMOVED; spin_unlock_irqrestore(&ihost->lock, flags); iscsi_host_for_each_session(shost, iscsi_notify_host_removed); wait_event_interruptible(ihost->session_removal_wq, ihost->num_sessions == 0); if (signal_pending(current)) flush_signals(current); |
a4804cd6e [SCSI] iscsi: add... |
2558 |
scsi_remove_host(shost); |
32ae763e3 [SCSI] iscsi lib:... |
2559 2560 |
if (ihost->workq) destroy_workqueue(ihost->workq); |
756135215 [SCSI] iscsi: rem... |
2561 |
} |
a4804cd6e [SCSI] iscsi: add... |
2562 |
EXPORT_SYMBOL_GPL(iscsi_host_remove); |
7996a778f [SCSI] iscsi: add... |
2563 |
|
a4804cd6e [SCSI] iscsi: add... |
2564 |
void iscsi_host_free(struct Scsi_Host *shost) |
756135215 [SCSI] iscsi: rem... |
2565 2566 |
{ struct iscsi_host *ihost = shost_priv(shost); |
7996a778f [SCSI] iscsi: add... |
2567 |
|
756135215 [SCSI] iscsi: rem... |
2568 2569 2570 |
kfree(ihost->netdev); kfree(ihost->hwaddress); kfree(ihost->initiatorname); |
a4804cd6e [SCSI] iscsi: add... |
2571 |
scsi_host_put(shost); |
756135215 [SCSI] iscsi: rem... |
2572 |
} |
a4804cd6e [SCSI] iscsi: add... |
2573 |
EXPORT_SYMBOL_GPL(iscsi_host_free); |
7996a778f [SCSI] iscsi: add... |
2574 |
|
e5bd7b54e [SCSI] libiscsi: ... |
2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 |
static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost) { struct iscsi_host *ihost = shost_priv(shost); unsigned long flags; shost = scsi_host_get(shost); if (!shost) { printk(KERN_ERR "Invalid state. Cannot notify host removal " "of session teardown event because host already " "removed. "); return; } spin_lock_irqsave(&ihost->lock, flags); ihost->num_sessions--; if (ihost->num_sessions == 0) wake_up(&ihost->session_removal_wq); spin_unlock_irqrestore(&ihost->lock, flags); scsi_host_put(shost); } |
7996a778f [SCSI] iscsi: add... |
2596 2597 |
/** * iscsi_session_setup - create iscsi cls session and host and session |
7996a778f [SCSI] iscsi: add... |
2598 |
* @iscsit: iscsi transport template |
756135215 [SCSI] iscsi: rem... |
2599 2600 |
* @shost: scsi host * @cmds_max: session can queue |
9c19a7d03 [SCSI] libiscsi: ... |
2601 |
* @cmd_task_size: LLD task private data size |
7996a778f [SCSI] iscsi: add... |
2602 |
* @initial_cmdsn: initial CmdSN |
7996a778f [SCSI] iscsi: add... |
2603 2604 2605 |
* * This can be used by software iscsi_transports that allocate * a session per scsi host. |
3cf7b233f [SCSI] libiscsi: ... |
2606 2607 2608 2609 |
* * Callers should set cmds_max to the largest total numer (mgmt + scsi) of * tasks they support. The iscsi layer reserves ISCSI_MGMT_CMDS_MAX tasks * for nop handling and login/logout requests. |
756135215 [SCSI] iscsi: rem... |
2610 |
*/ |
7996a778f [SCSI] iscsi: add... |
2611 |
struct iscsi_cls_session * |
756135215 [SCSI] iscsi: rem... |
2612 |
iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
b8b9e1b81 [SCSI] libiscsi: ... |
2613 |
uint16_t cmds_max, int dd_size, int cmd_task_size, |
7970634b8 [SCSI] iscsi clas... |
2614 |
uint32_t initial_cmdsn, unsigned int id) |
7996a778f [SCSI] iscsi: add... |
2615 |
{ |
e5bd7b54e [SCSI] libiscsi: ... |
2616 |
struct iscsi_host *ihost = shost_priv(shost); |
7996a778f [SCSI] iscsi: add... |
2617 2618 |
struct iscsi_session *session; struct iscsi_cls_session *cls_session; |
3cf7b233f [SCSI] libiscsi: ... |
2619 |
int cmd_i, scsi_cmds, total_cmds = cmds_max; |
e5bd7b54e [SCSI] libiscsi: ... |
2620 2621 2622 2623 2624 2625 2626 2627 2628 |
unsigned long flags; spin_lock_irqsave(&ihost->lock, flags); if (ihost->state == ISCSI_HOST_REMOVED) { spin_unlock_irqrestore(&ihost->lock, flags); return NULL; } ihost->num_sessions++; spin_unlock_irqrestore(&ihost->lock, flags); |
8e9a20cee [SCSI] libiscsi, ... |
2629 2630 2631 |
if (!total_cmds) total_cmds = ISCSI_DEF_XMIT_CMDS_MAX; |
3e5c28ad0 [SCSI] libiscsi: ... |
2632 |
/* |
3cf7b233f [SCSI] libiscsi: ... |
2633 2634 2635 |
* The iscsi layer needs some tasks for nop handling and tmfs, * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX * + 1 command for scsi IO. |
3e5c28ad0 [SCSI] libiscsi: ... |
2636 |
*/ |
3cf7b233f [SCSI] libiscsi: ... |
2637 2638 2639 2640 2641 |
if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " "must be a power of two that is at least %d. ", total_cmds, ISCSI_TOTAL_CMDS_MIN); |
e5bd7b54e [SCSI] libiscsi: ... |
2642 |
goto dec_session_count; |
3cf7b233f [SCSI] libiscsi: ... |
2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 |
} if (total_cmds > ISCSI_TOTAL_CMDS_MAX) { printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " "must be a power of 2 less than or equal to %d. ", cmds_max, ISCSI_TOTAL_CMDS_MAX); total_cmds = ISCSI_TOTAL_CMDS_MAX; } if (!is_power_of_2(total_cmds)) { printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " "must be a power of 2. ", total_cmds); total_cmds = rounddown_pow_of_two(total_cmds); if (total_cmds < ISCSI_TOTAL_CMDS_MIN) return NULL; printk(KERN_INFO "iscsi: Rounding can_queue to %d. ", total_cmds); |
1548271ec [SCSI] libiscsi: ... |
2663 |
} |
3cf7b233f [SCSI] libiscsi: ... |
2664 |
scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; |
1548271ec [SCSI] libiscsi: ... |
2665 |
|
5d91e209f [SCSI] iscsi: rem... |
2666 |
cls_session = iscsi_alloc_session(shost, iscsit, |
b8b9e1b81 [SCSI] libiscsi: ... |
2667 2668 |
sizeof(struct iscsi_session) + dd_size); |
756135215 [SCSI] iscsi: rem... |
2669 |
if (!cls_session) |
e5bd7b54e [SCSI] libiscsi: ... |
2670 |
goto dec_session_count; |
756135215 [SCSI] iscsi: rem... |
2671 2672 |
session = cls_session->dd_data; session->cls_session = cls_session; |
7996a778f [SCSI] iscsi: add... |
2673 2674 |
session->host = shost; session->state = ISCSI_STATE_FREE; |
f6d5180c7 [SCSI] libiscsi: ... |
2675 |
session->fast_abort = 1; |
3fe5ae8b4 [SCSI] libiscsi: ... |
2676 |
session->tgt_reset_timeout = 30; |
4cd49ea13 [SCSI] libiscsi, ... |
2677 2678 |
session->lu_reset_timeout = 15; session->abort_timeout = 10; |
3cf7b233f [SCSI] libiscsi: ... |
2679 2680 |
session->scsi_cmds_max = scsi_cmds; session->cmds_max = total_cmds; |
e07264071 [SCSI] libiscsi: ... |
2681 |
session->queued_cmdsn = session->cmdsn = initial_cmdsn; |
7996a778f [SCSI] iscsi: add... |
2682 2683 2684 2685 |
session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; session->tt = iscsit; |
b8b9e1b81 [SCSI] libiscsi: ... |
2686 |
session->dd_data = cls_session->dd_data + sizeof(*session); |
6724add1b [SCSI] libiscsi: ... |
2687 |
mutex_init(&session->eh_mutex); |
756135215 [SCSI] iscsi: rem... |
2688 |
spin_lock_init(&session->lock); |
7996a778f [SCSI] iscsi: add... |
2689 2690 2691 2692 |
/* initialize SCSI PDU commands pool */ if (iscsi_pool_init(&session->cmdpool, session->cmds_max, (void***)&session->cmds, |
9c19a7d03 [SCSI] libiscsi: ... |
2693 |
cmd_task_size + sizeof(struct iscsi_task))) |
7996a778f [SCSI] iscsi: add... |
2694 2695 2696 2697 |
goto cmdpool_alloc_fail; /* pre-format cmds pool with ITT */ for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
9c19a7d03 [SCSI] libiscsi: ... |
2698 |
struct iscsi_task *task = session->cmds[cmd_i]; |
7996a778f [SCSI] iscsi: add... |
2699 |
|
9c19a7d03 [SCSI] libiscsi: ... |
2700 2701 2702 |
if (cmd_task_size) task->dd_data = &task[1]; task->itt = cmd_i; |
3bbaaad95 [SCSI] libiscsi: ... |
2703 |
task->state = ISCSI_TASK_FREE; |
9c19a7d03 [SCSI] libiscsi: ... |
2704 |
INIT_LIST_HEAD(&task->running); |
7996a778f [SCSI] iscsi: add... |
2705 |
} |
f53a88da1 [SCSI] iscsi: fix... |
2706 |
if (!try_module_get(iscsit->owner)) |
756135215 [SCSI] iscsi: rem... |
2707 |
goto module_get_fail; |
7996a778f [SCSI] iscsi: add... |
2708 |
|
7970634b8 [SCSI] iscsi clas... |
2709 |
if (iscsi_add_session(cls_session, id)) |
756135215 [SCSI] iscsi: rem... |
2710 |
goto cls_session_fail; |
e5bd7b54e [SCSI] libiscsi: ... |
2711 |
|
7996a778f [SCSI] iscsi: add... |
2712 2713 2714 |
return cls_session; cls_session_fail: |
756135215 [SCSI] iscsi: rem... |
2715 2716 |
module_put(iscsit->owner); module_get_fail: |
6320377fd [SCSI] libiscsi, ... |
2717 |
iscsi_pool_free(&session->cmdpool); |
7996a778f [SCSI] iscsi: add... |
2718 |
cmdpool_alloc_fail: |
756135215 [SCSI] iscsi: rem... |
2719 |
iscsi_free_session(cls_session); |
e5bd7b54e [SCSI] libiscsi: ... |
2720 2721 |
dec_session_count: iscsi_host_dec_session_cnt(shost); |
7996a778f [SCSI] iscsi: add... |
2722 2723 2724 2725 2726 2727 |
return NULL; } EXPORT_SYMBOL_GPL(iscsi_session_setup); /** * iscsi_session_teardown - destroy session, host, and cls_session |
756135215 [SCSI] iscsi: rem... |
2728 |
* @cls_session: iscsi session |
7996a778f [SCSI] iscsi: add... |
2729 |
* |
756135215 [SCSI] iscsi: rem... |
2730 2731 2732 |
* The driver must have called iscsi_remove_session before * calling this. */ |
7996a778f [SCSI] iscsi: add... |
2733 2734 |
void iscsi_session_teardown(struct iscsi_cls_session *cls_session) { |
756135215 [SCSI] iscsi: rem... |
2735 |
struct iscsi_session *session = cls_session->dd_data; |
63f75cc8a [SCSI] iscsi bugf... |
2736 |
struct module *owner = cls_session->transport->owner; |
e5bd7b54e [SCSI] libiscsi: ... |
2737 |
struct Scsi_Host *shost = session->host; |
7996a778f [SCSI] iscsi: add... |
2738 |
|
6320377fd [SCSI] libiscsi, ... |
2739 |
iscsi_pool_free(&session->cmdpool); |
7996a778f [SCSI] iscsi: add... |
2740 |
|
b2c641673 [SCSI] iscsi clas... |
2741 2742 2743 2744 |
kfree(session->password); kfree(session->password_in); kfree(session->username); kfree(session->username_in); |
f3ff0c362 [SCSI] iscsi bugf... |
2745 |
kfree(session->targetname); |
88dfd340b [SCSI] iscsi clas... |
2746 2747 |
kfree(session->initiatorname); kfree(session->ifacename); |
f3ff0c362 [SCSI] iscsi bugf... |
2748 |
|
756135215 [SCSI] iscsi: rem... |
2749 |
iscsi_destroy_session(cls_session); |
e5bd7b54e [SCSI] libiscsi: ... |
2750 |
iscsi_host_dec_session_cnt(shost); |
63f75cc8a [SCSI] iscsi bugf... |
2751 |
module_put(owner); |
7996a778f [SCSI] iscsi: add... |
2752 2753 2754 2755 2756 2757 |
} EXPORT_SYMBOL_GPL(iscsi_session_teardown); /** * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn * @cls_session: iscsi_cls_session |
5d91e209f [SCSI] iscsi: rem... |
2758 |
* @dd_size: private driver data size |
7996a778f [SCSI] iscsi: add... |
2759 |
* @conn_idx: cid |
5d91e209f [SCSI] iscsi: rem... |
2760 |
*/ |
7996a778f [SCSI] iscsi: add... |
2761 |
struct iscsi_cls_conn * |
5d91e209f [SCSI] iscsi: rem... |
2762 2763 |
iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, uint32_t conn_idx) |
7996a778f [SCSI] iscsi: add... |
2764 |
{ |
756135215 [SCSI] iscsi: rem... |
2765 |
struct iscsi_session *session = cls_session->dd_data; |
7996a778f [SCSI] iscsi: add... |
2766 2767 |
struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; |
d36ab6f32 [SCSI] iscsi: onl... |
2768 |
char *data; |
7996a778f [SCSI] iscsi: add... |
2769 |
|
5d91e209f [SCSI] iscsi: rem... |
2770 2771 |
cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size, conn_idx); |
7996a778f [SCSI] iscsi: add... |
2772 2773 2774 |
if (!cls_conn) return NULL; conn = cls_conn->dd_data; |
5d91e209f [SCSI] iscsi: rem... |
2775 |
memset(conn, 0, sizeof(*conn) + dd_size); |
7996a778f [SCSI] iscsi: add... |
2776 |
|
5d91e209f [SCSI] iscsi: rem... |
2777 |
conn->dd_data = cls_conn->dd_data + sizeof(*conn); |
7996a778f [SCSI] iscsi: add... |
2778 2779 2780 2781 2782 |
conn->session = session; conn->cls_conn = cls_conn; conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; |
843c0a8a7 [SCSI] libiscsi, ... |
2783 |
conn->tmf_state = TMF_INITIAL; |
f6d5180c7 [SCSI] libiscsi: ... |
2784 2785 2786 2787 |
init_timer(&conn->transport_timer); conn->transport_timer.data = (unsigned long)conn; conn->transport_timer.function = iscsi_check_transport_timeouts; |
843c0a8a7 [SCSI] libiscsi, ... |
2788 |
INIT_LIST_HEAD(&conn->mgmtqueue); |
3bbaaad95 [SCSI] libiscsi: ... |
2789 |
INIT_LIST_HEAD(&conn->cmdqueue); |
843c0a8a7 [SCSI] libiscsi, ... |
2790 |
INIT_LIST_HEAD(&conn->requeue); |
c4028958b WorkStruct: make ... |
2791 |
INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
7996a778f [SCSI] iscsi: add... |
2792 |
|
9c19a7d03 [SCSI] libiscsi: ... |
2793 |
/* allocate login_task used for the login/text sequences */ |
7996a778f [SCSI] iscsi: add... |
2794 |
spin_lock_bh(&session->lock); |
7acd72eb8 kfifo: rename kfi... |
2795 |
if (!kfifo_out(&session->cmdpool.queue, |
9c19a7d03 [SCSI] libiscsi: ... |
2796 |
(void*)&conn->login_task, |
7996a778f [SCSI] iscsi: add... |
2797 2798 |
sizeof(void*))) { spin_unlock_bh(&session->lock); |
9c19a7d03 [SCSI] libiscsi: ... |
2799 |
goto login_task_alloc_fail; |
7996a778f [SCSI] iscsi: add... |
2800 2801 |
} spin_unlock_bh(&session->lock); |
cfeb2cf95 [SCSI] libiscsi: ... |
2802 2803 |
data = (char *) __get_free_pages(GFP_KERNEL, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); |
d36ab6f32 [SCSI] iscsi: onl... |
2804 |
if (!data) |
9c19a7d03 [SCSI] libiscsi: ... |
2805 2806 |
goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data; |
d36ab6f32 [SCSI] iscsi: onl... |
2807 |
|
843c0a8a7 [SCSI] libiscsi, ... |
2808 |
init_timer(&conn->tmf_timer); |
7996a778f [SCSI] iscsi: add... |
2809 2810 2811 |
init_waitqueue_head(&conn->ehwait); return cls_conn; |
9c19a7d03 [SCSI] libiscsi: ... |
2812 |
login_task_data_alloc_fail: |
7acd72eb8 kfifo: rename kfi... |
2813 |
kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, |
d36ab6f32 [SCSI] iscsi: onl... |
2814 |
sizeof(void*)); |
9c19a7d03 [SCSI] libiscsi: ... |
2815 |
login_task_alloc_fail: |
7996a778f [SCSI] iscsi: add... |
2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 |
iscsi_destroy_conn(cls_conn); return NULL; } EXPORT_SYMBOL_GPL(iscsi_conn_setup); /** * iscsi_conn_teardown - teardown iscsi connection * cls_conn: iscsi class connection * * TODO: we may need to make this into a two step process * like scsi-mls remove + put host */ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; unsigned long flags; |
f6d5180c7 [SCSI] libiscsi: ... |
2833 |
del_timer_sync(&conn->transport_timer); |
7996a778f [SCSI] iscsi: add... |
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 |
spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; if (session->leadconn == conn) { /* * leading connection? then give up on recovery. */ session->state = ISCSI_STATE_TERMINATE; wake_up(&conn->ehwait); } spin_unlock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 |
/* * Block until all in-progress commands for this connection * time out or fail. */ for (;;) { spin_lock_irqsave(session->host->host_lock, flags); if (!session->host->host_busy) { /* OK for ERL == 0 */ spin_unlock_irqrestore(session->host->host_lock, flags); break; } spin_unlock_irqrestore(session->host->host_lock, flags); msleep_interruptible(500); |
322d739da [SCSI] iscsi: fix... |
2856 2857 2858 2859 2860 |
iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): " "host_busy %d host_failed %d ", session->host->host_busy, session->host->host_failed); |
7996a778f [SCSI] iscsi: add... |
2861 2862 2863 2864 2865 |
/* * force eh_abort() to unblock */ wake_up(&conn->ehwait); } |
779ea1207 [SCSI] libiscsi: ... |
2866 |
/* flush queued up work because we free the connection below */ |
843c0a8a7 [SCSI] libiscsi, ... |
2867 |
iscsi_suspend_tx(conn); |
779ea1207 [SCSI] libiscsi: ... |
2868 |
|
7996a778f [SCSI] iscsi: add... |
2869 |
spin_lock_bh(&session->lock); |
cfeb2cf95 [SCSI] libiscsi: ... |
2870 2871 |
free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); |
f3ff0c362 [SCSI] iscsi bugf... |
2872 |
kfree(conn->persistent_address); |
7acd72eb8 kfifo: rename kfi... |
2873 |
kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, |
7996a778f [SCSI] iscsi: add... |
2874 |
sizeof(void*)); |
e07264071 [SCSI] libiscsi: ... |
2875 |
if (session->leadconn == conn) |
7996a778f [SCSI] iscsi: add... |
2876 |
session->leadconn = NULL; |
7996a778f [SCSI] iscsi: add... |
2877 |
spin_unlock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
2878 2879 2880 2881 2882 2883 2884 2885 |
iscsi_destroy_conn(cls_conn); } EXPORT_SYMBOL_GPL(iscsi_conn_teardown); int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; |
ffd0436ed [SCSI] libiscsi, ... |
2886 |
if (!session) { |
322d739da [SCSI] iscsi: fix... |
2887 2888 2889 |
iscsi_conn_printk(KERN_ERR, conn, "can't start unbound connection "); |
7996a778f [SCSI] iscsi: add... |
2890 2891 |
return -EPERM; } |
db98ccde0 [SCSI] libiscsi: ... |
2892 2893 |
if ((session->imm_data_en || !session->initial_r2t_en) && session->first_burst > session->max_burst) { |
322d739da [SCSI] iscsi: fix... |
2894 2895 2896 2897 |
iscsi_conn_printk(KERN_INFO, conn, "invalid burst lengths: " "first_burst %d max_burst %d ", session->first_burst, session->max_burst); |
ffd0436ed [SCSI] libiscsi, ... |
2898 2899 |
return -EINVAL; } |
f6d5180c7 [SCSI] libiscsi: ... |
2900 |
if (conn->ping_timeout && !conn->recv_timeout) { |
322d739da [SCSI] iscsi: fix... |
2901 2902 2903 |
iscsi_conn_printk(KERN_ERR, conn, "invalid recv timeout of " "zero. Using 5 seconds ."); |
f6d5180c7 [SCSI] libiscsi: ... |
2904 2905 2906 2907 |
conn->recv_timeout = 5; } if (conn->recv_timeout && !conn->ping_timeout) { |
322d739da [SCSI] iscsi: fix... |
2908 2909 2910 |
iscsi_conn_printk(KERN_ERR, conn, "invalid ping timeout of " "zero. Using 5 seconds. "); |
f6d5180c7 [SCSI] libiscsi: ... |
2911 2912 |
conn->ping_timeout = 5; } |
7996a778f [SCSI] iscsi: add... |
2913 2914 2915 |
spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STARTED; session->state = ISCSI_STATE_LOGGED_IN; |
e07264071 [SCSI] libiscsi: ... |
2916 |
session->queued_cmdsn = session->cmdsn; |
7996a778f [SCSI] iscsi: add... |
2917 |
|
f6d5180c7 [SCSI] libiscsi: ... |
2918 2919 2920 2921 2922 |
conn->last_recv = jiffies; conn->last_ping = jiffies; if (conn->recv_timeout && conn->ping_timeout) mod_timer(&conn->transport_timer, jiffies + (conn->recv_timeout * HZ)); |
7996a778f [SCSI] iscsi: add... |
2923 2924 2925 2926 2927 2928 |
switch(conn->stop_stage) { case STOP_CONN_RECOVER: /* * unblock eh_abort() if it is blocked. re-try all * commands after successful recovery */ |
7996a778f [SCSI] iscsi: add... |
2929 |
conn->stop_stage = 0; |
843c0a8a7 [SCSI] libiscsi, ... |
2930 |
conn->tmf_state = TMF_INITIAL; |
7996a778f [SCSI] iscsi: add... |
2931 |
session->age++; |
8b1d03434 [SCSI] libiscsi: ... |
2932 2933 |
if (session->age == 16) session->age = 0; |
6eabafbe6 [SCSI] iscsi clas... |
2934 |
break; |
7996a778f [SCSI] iscsi: add... |
2935 |
case STOP_CONN_TERM: |
7996a778f [SCSI] iscsi: add... |
2936 |
conn->stop_stage = 0; |
7996a778f [SCSI] iscsi: add... |
2937 2938 2939 2940 2941 |
break; default: break; } spin_unlock_bh(&session->lock); |
756135215 [SCSI] iscsi: rem... |
2942 |
iscsi_unblock_session(session->cls_session); |
6eabafbe6 [SCSI] iscsi clas... |
2943 |
wake_up(&conn->ehwait); |
7996a778f [SCSI] iscsi: add... |
2944 2945 2946 2947 2948 |
return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); static void |
3bbaaad95 [SCSI] libiscsi: ... |
2949 |
fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) |
7996a778f [SCSI] iscsi: add... |
2950 |
{ |
3bbaaad95 [SCSI] libiscsi: ... |
2951 |
struct iscsi_task *task; |
b3cd5050b [SCSI] libiscsi: ... |
2952 |
int i, state; |
7996a778f [SCSI] iscsi: add... |
2953 |
|
3bbaaad95 [SCSI] libiscsi: ... |
2954 2955 2956 2957 |
for (i = 0; i < conn->session->cmds_max; i++) { task = conn->session->cmds[i]; if (task->sc) continue; |
7996a778f [SCSI] iscsi: add... |
2958 |
|
3bbaaad95 [SCSI] libiscsi: ... |
2959 2960 |
if (task->state == ISCSI_TASK_FREE) continue; |
7996a778f [SCSI] iscsi: add... |
2961 |
|
3bbaaad95 [SCSI] libiscsi: ... |
2962 2963 2964 2965 |
ISCSI_DBG_SESSION(conn->session, "failing mgmt itt 0x%x state %d ", task->itt, task->state); |
b3cd5050b [SCSI] libiscsi: ... |
2966 2967 2968 2969 |
state = ISCSI_TASK_ABRT_SESS_RECOV; if (task->state == ISCSI_TASK_PENDING) state = ISCSI_TASK_COMPLETED; iscsi_complete_task(task, state); |
3bbaaad95 [SCSI] libiscsi: ... |
2970 |
} |
7996a778f [SCSI] iscsi: add... |
2971 |
} |
656cffc95 [SCSI] iscsi: fix... |
2972 2973 |
static void iscsi_start_session_recovery(struct iscsi_session *session, struct iscsi_conn *conn, int flag) |
7996a778f [SCSI] iscsi: add... |
2974 |
{ |
ed2abc7ff [SCSI] iscsi: fix... |
2975 |
int old_stop_stage; |
6724add1b [SCSI] libiscsi: ... |
2976 |
mutex_lock(&session->eh_mutex); |
7996a778f [SCSI] iscsi: add... |
2977 |
spin_lock_bh(&session->lock); |
ed2abc7ff [SCSI] iscsi: fix... |
2978 |
if (conn->stop_stage == STOP_CONN_TERM) { |
7996a778f [SCSI] iscsi: add... |
2979 |
spin_unlock_bh(&session->lock); |
6724add1b [SCSI] libiscsi: ... |
2980 2981 2982 2983 2984 |
mutex_unlock(&session->eh_mutex); return; } /* |
ed2abc7ff [SCSI] iscsi: fix... |
2985 |
* When this is called for the in_login state, we only want to clean |
9c19a7d03 [SCSI] libiscsi: ... |
2986 |
* up the login task and connection. We do not need to block and set |
67a611149 [SCSI] iscsi: don... |
2987 |
* the recovery state again |
ed2abc7ff [SCSI] iscsi: fix... |
2988 |
*/ |
67a611149 [SCSI] iscsi: don... |
2989 2990 2991 2992 |
if (flag == STOP_CONN_TERM) session->state = ISCSI_STATE_TERMINATE; else if (conn->stop_stage != STOP_CONN_RECOVER) session->state = ISCSI_STATE_IN_RECOVERY; |
4ae0a6c15 [SCSI] libiscsi: ... |
2993 2994 2995 |
old_stop_stage = conn->stop_stage; conn->stop_stage = flag; |
26013ad4c [SCSI] libiscsi: ... |
2996 |
spin_unlock_bh(&session->lock); |
ed2abc7ff [SCSI] iscsi: fix... |
2997 |
|
26013ad4c [SCSI] libiscsi: ... |
2998 2999 3000 3001 |
del_timer_sync(&conn->transport_timer); iscsi_suspend_tx(conn); spin_lock_bh(&session->lock); |
67a611149 [SCSI] iscsi: don... |
3002 |
conn->c_stage = ISCSI_CONN_STOPPED; |
7996a778f [SCSI] iscsi: add... |
3003 |
spin_unlock_bh(&session->lock); |
6724add1b [SCSI] libiscsi: ... |
3004 |
|
7996a778f [SCSI] iscsi: add... |
3005 3006 3007 3008 3009 3010 3011 3012 3013 |
/* * for connection level recovery we should not calculate * header digest. conn->hdr_size used for optimization * in hdr_extract() and will be re-negotiated at * set_param() time. */ if (flag == STOP_CONN_RECOVER) { conn->hdrdgst_en = 0; conn->datadgst_en = 0; |
656cffc95 [SCSI] iscsi: fix... |
3014 |
if (session->state == ISCSI_STATE_IN_RECOVERY && |
67a611149 [SCSI] iscsi: don... |
3015 |
old_stop_stage != STOP_CONN_RECOVER) { |
1b2c7af87 [SCSI] libiscsi: ... |
3016 3017 |
ISCSI_DBG_SESSION(session, "blocking session "); |
756135215 [SCSI] iscsi: rem... |
3018 |
iscsi_block_session(session->cls_session); |
67a611149 [SCSI] iscsi: don... |
3019 |
} |
7996a778f [SCSI] iscsi: add... |
3020 |
} |
656cffc95 [SCSI] iscsi: fix... |
3021 |
|
656cffc95 [SCSI] iscsi: fix... |
3022 3023 3024 3025 |
/* * flush queues. */ spin_lock_bh(&session->lock); |
b3cd5050b [SCSI] libiscsi: ... |
3026 |
fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); |
3bbaaad95 [SCSI] libiscsi: ... |
3027 |
fail_mgmt_tasks(session, conn); |
5d12c05e2 [SCSI] libiscsi: ... |
3028 |
memset(&conn->tmhdr, 0, sizeof(conn->tmhdr)); |
656cffc95 [SCSI] iscsi: fix... |
3029 |
spin_unlock_bh(&session->lock); |
6724add1b [SCSI] libiscsi: ... |
3030 |
mutex_unlock(&session->eh_mutex); |
7996a778f [SCSI] iscsi: add... |
3031 |
} |
7996a778f [SCSI] iscsi: add... |
3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 |
void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; switch (flag) { case STOP_CONN_RECOVER: case STOP_CONN_TERM: iscsi_start_session_recovery(session, conn, flag); |
8d2860b3c [SCSI] iscsi: inc... |
3042 |
break; |
7996a778f [SCSI] iscsi: add... |
3043 |
default: |
322d739da [SCSI] iscsi: fix... |
3044 3045 3046 |
iscsi_conn_printk(KERN_ERR, conn, "invalid stop flag %d ", flag); |
7996a778f [SCSI] iscsi: add... |
3047 3048 3049 3050 3051 3052 3053 |
} } EXPORT_SYMBOL_GPL(iscsi_conn_stop); int iscsi_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, int is_leading) { |
756135215 [SCSI] iscsi: rem... |
3054 |
struct iscsi_session *session = cls_session->dd_data; |
986440479 [SCSI] libiscsi: ... |
3055 |
struct iscsi_conn *conn = cls_conn->dd_data; |
7996a778f [SCSI] iscsi: add... |
3056 |
|
7996a778f [SCSI] iscsi: add... |
3057 |
spin_lock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
3058 3059 |
if (is_leading) session->leadconn = conn; |
986440479 [SCSI] libiscsi: ... |
3060 |
spin_unlock_bh(&session->lock); |
7996a778f [SCSI] iscsi: add... |
3061 3062 3063 3064 3065 3066 3067 3068 3069 |
/* * Unblock xmitworker(), Login Phase will pass through. */ clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_bind); |
5700b1af9 [SCSI] libiscsi: ... |
3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 |
static int iscsi_switch_str_param(char **param, char *new_val_buf) { char *new_val; if (*param) { if (!strcmp(*param, new_val_buf)) return 0; } new_val = kstrdup(new_val_buf, GFP_NOIO); if (!new_val) return -ENOMEM; kfree(*param); *param = new_val; return 0; } |
a54a52caa [SCSI] iscsi: fix... |
3087 3088 3089 3090 3091 3092 |
int iscsi_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; |
a54a52caa [SCSI] iscsi: fix... |
3093 3094 |
switch(param) { |
843c0a8a7 [SCSI] libiscsi, ... |
3095 3096 3097 |
case ISCSI_PARAM_FAST_ABORT: sscanf(buf, "%d", &session->fast_abort); break; |
f6d5180c7 [SCSI] libiscsi: ... |
3098 3099 3100 3101 3102 3103 |
case ISCSI_PARAM_ABORT_TMO: sscanf(buf, "%d", &session->abort_timeout); break; case ISCSI_PARAM_LU_RESET_TMO: sscanf(buf, "%d", &session->lu_reset_timeout); break; |
3fe5ae8b4 [SCSI] libiscsi: ... |
3104 3105 3106 |
case ISCSI_PARAM_TGT_RESET_TMO: sscanf(buf, "%d", &session->tgt_reset_timeout); break; |
f6d5180c7 [SCSI] libiscsi: ... |
3107 3108 3109 3110 3111 3112 |
case ISCSI_PARAM_PING_TMO: sscanf(buf, "%d", &conn->ping_timeout); break; case ISCSI_PARAM_RECV_TMO: sscanf(buf, "%d", &conn->recv_timeout); break; |
a54a52caa [SCSI] iscsi: fix... |
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 |
case ISCSI_PARAM_MAX_RECV_DLENGTH: sscanf(buf, "%d", &conn->max_recv_dlength); break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: sscanf(buf, "%d", &conn->max_xmit_dlength); break; case ISCSI_PARAM_HDRDGST_EN: sscanf(buf, "%d", &conn->hdrdgst_en); break; case ISCSI_PARAM_DATADGST_EN: sscanf(buf, "%d", &conn->datadgst_en); break; case ISCSI_PARAM_INITIAL_R2T_EN: sscanf(buf, "%d", &session->initial_r2t_en); break; case ISCSI_PARAM_MAX_R2T: sscanf(buf, "%d", &session->max_r2t); break; case ISCSI_PARAM_IMM_DATA_EN: sscanf(buf, "%d", &session->imm_data_en); break; case ISCSI_PARAM_FIRST_BURST: sscanf(buf, "%d", &session->first_burst); break; case ISCSI_PARAM_MAX_BURST: sscanf(buf, "%d", &session->max_burst); break; case ISCSI_PARAM_PDU_INORDER_EN: sscanf(buf, "%d", &session->pdu_inorder_en); break; case ISCSI_PARAM_DATASEQ_INORDER_EN: sscanf(buf, "%d", &session->dataseq_inorder_en); break; case ISCSI_PARAM_ERL: sscanf(buf, "%d", &session->erl); break; |
a54a52caa [SCSI] iscsi: fix... |
3149 3150 3151 |
case ISCSI_PARAM_EXP_STATSN: sscanf(buf, "%u", &conn->exp_statsn); break; |
b2c641673 [SCSI] iscsi clas... |
3152 |
case ISCSI_PARAM_USERNAME: |
5700b1af9 [SCSI] libiscsi: ... |
3153 |
return iscsi_switch_str_param(&session->username, buf); |
b2c641673 [SCSI] iscsi clas... |
3154 |
case ISCSI_PARAM_USERNAME_IN: |
5700b1af9 [SCSI] libiscsi: ... |
3155 |
return iscsi_switch_str_param(&session->username_in, buf); |
b2c641673 [SCSI] iscsi clas... |
3156 |
case ISCSI_PARAM_PASSWORD: |
5700b1af9 [SCSI] libiscsi: ... |
3157 |
return iscsi_switch_str_param(&session->password, buf); |
b2c641673 [SCSI] iscsi clas... |
3158 |
case ISCSI_PARAM_PASSWORD_IN: |
5700b1af9 [SCSI] libiscsi: ... |
3159 |
return iscsi_switch_str_param(&session->password_in, buf); |
a54a52caa [SCSI] iscsi: fix... |
3160 |
case ISCSI_PARAM_TARGET_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3161 |
return iscsi_switch_str_param(&session->targetname, buf); |
a54a52caa [SCSI] iscsi: fix... |
3162 3163 3164 3165 3166 3167 3168 |
case ISCSI_PARAM_TPGT: sscanf(buf, "%d", &session->tpgt); break; case ISCSI_PARAM_PERSISTENT_PORT: sscanf(buf, "%d", &conn->persistent_port); break; case ISCSI_PARAM_PERSISTENT_ADDRESS: |
5700b1af9 [SCSI] libiscsi: ... |
3169 |
return iscsi_switch_str_param(&conn->persistent_address, buf); |
88dfd340b [SCSI] iscsi clas... |
3170 |
case ISCSI_PARAM_IFACE_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3171 |
return iscsi_switch_str_param(&session->ifacename, buf); |
88dfd340b [SCSI] iscsi clas... |
3172 |
case ISCSI_PARAM_INITIATOR_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3173 |
return iscsi_switch_str_param(&session->initiatorname, buf); |
a54a52caa [SCSI] iscsi: fix... |
3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 |
default: return -ENOSYS; } return 0; } EXPORT_SYMBOL_GPL(iscsi_set_param); int iscsi_session_get_param(struct iscsi_cls_session *cls_session, enum iscsi_param param, char *buf) { |
756135215 [SCSI] iscsi: rem... |
3185 |
struct iscsi_session *session = cls_session->dd_data; |
a54a52caa [SCSI] iscsi: fix... |
3186 3187 3188 |
int len; switch(param) { |
843c0a8a7 [SCSI] libiscsi, ... |
3189 3190 3191 3192 |
case ISCSI_PARAM_FAST_ABORT: len = sprintf(buf, "%d ", session->fast_abort); break; |
f6d5180c7 [SCSI] libiscsi: ... |
3193 3194 3195 3196 3197 3198 3199 3200 |
case ISCSI_PARAM_ABORT_TMO: len = sprintf(buf, "%d ", session->abort_timeout); break; case ISCSI_PARAM_LU_RESET_TMO: len = sprintf(buf, "%d ", session->lu_reset_timeout); break; |
3fe5ae8b4 [SCSI] libiscsi: ... |
3201 3202 3203 3204 |
case ISCSI_PARAM_TGT_RESET_TMO: len = sprintf(buf, "%d ", session->tgt_reset_timeout); break; |
a54a52caa [SCSI] iscsi: fix... |
3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 |
case ISCSI_PARAM_INITIAL_R2T_EN: len = sprintf(buf, "%d ", session->initial_r2t_en); break; case ISCSI_PARAM_MAX_R2T: len = sprintf(buf, "%hu ", session->max_r2t); break; case ISCSI_PARAM_IMM_DATA_EN: len = sprintf(buf, "%d ", session->imm_data_en); break; case ISCSI_PARAM_FIRST_BURST: len = sprintf(buf, "%u ", session->first_burst); break; case ISCSI_PARAM_MAX_BURST: len = sprintf(buf, "%u ", session->max_burst); break; case ISCSI_PARAM_PDU_INORDER_EN: len = sprintf(buf, "%d ", session->pdu_inorder_en); break; case ISCSI_PARAM_DATASEQ_INORDER_EN: len = sprintf(buf, "%d ", session->dataseq_inorder_en); break; case ISCSI_PARAM_ERL: len = sprintf(buf, "%d ", session->erl); break; case ISCSI_PARAM_TARGET_NAME: len = sprintf(buf, "%s ", session->targetname); break; case ISCSI_PARAM_TPGT: len = sprintf(buf, "%d ", session->tpgt); break; |
b2c641673 [SCSI] iscsi clas... |
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 |
case ISCSI_PARAM_USERNAME: len = sprintf(buf, "%s ", session->username); break; case ISCSI_PARAM_USERNAME_IN: len = sprintf(buf, "%s ", session->username_in); break; case ISCSI_PARAM_PASSWORD: len = sprintf(buf, "%s ", session->password); break; case ISCSI_PARAM_PASSWORD_IN: len = sprintf(buf, "%s ", session->password_in); break; |
88dfd340b [SCSI] iscsi clas... |
3261 3262 3263 3264 3265 |
case ISCSI_PARAM_IFACE_NAME: len = sprintf(buf, "%s ", session->ifacename); break; case ISCSI_PARAM_INITIATOR_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3266 3267 |
len = sprintf(buf, "%s ", session->initiatorname); |
88dfd340b [SCSI] iscsi clas... |
3268 |
break; |
a54a52caa [SCSI] iscsi: fix... |
3269 3270 3271 3272 3273 3274 3275 |
default: return -ENOSYS; } return len; } EXPORT_SYMBOL_GPL(iscsi_session_get_param); |
00f3708e6 [SCSI] libiscsi: ... |
3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 |
int iscsi_conn_get_addr_param(struct sockaddr_storage *addr, enum iscsi_param param, char *buf) { struct sockaddr_in6 *sin6 = NULL; struct sockaddr_in *sin = NULL; int len; switch (addr->ss_family) { case AF_INET: sin = (struct sockaddr_in *)addr; break; case AF_INET6: sin6 = (struct sockaddr_in6 *)addr; break; default: return -EINVAL; } switch (param) { case ISCSI_PARAM_CONN_ADDRESS: case ISCSI_HOST_PARAM_IPADDRESS: if (sin) len = sprintf(buf, "%pI4 ", &sin->sin_addr.s_addr); else len = sprintf(buf, "%pI6 ", &sin6->sin6_addr); break; case ISCSI_PARAM_CONN_PORT: if (sin) len = sprintf(buf, "%hu ", be16_to_cpu(sin->sin_port)); else len = sprintf(buf, "%hu ", be16_to_cpu(sin6->sin6_port)); break; default: return -EINVAL; } return len; } EXPORT_SYMBOL_GPL(iscsi_conn_get_addr_param); |
a54a52caa [SCSI] iscsi: fix... |
3320 3321 3322 3323 3324 3325 3326 |
int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf) { struct iscsi_conn *conn = cls_conn->dd_data; int len; switch(param) { |
f6d5180c7 [SCSI] libiscsi: ... |
3327 3328 3329 3330 3331 3332 3333 3334 |
case ISCSI_PARAM_PING_TMO: len = sprintf(buf, "%u ", conn->ping_timeout); break; case ISCSI_PARAM_RECV_TMO: len = sprintf(buf, "%u ", conn->recv_timeout); break; |
a54a52caa [SCSI] iscsi: fix... |
3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 |
case ISCSI_PARAM_MAX_RECV_DLENGTH: len = sprintf(buf, "%u ", conn->max_recv_dlength); break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: len = sprintf(buf, "%u ", conn->max_xmit_dlength); break; case ISCSI_PARAM_HDRDGST_EN: len = sprintf(buf, "%d ", conn->hdrdgst_en); break; case ISCSI_PARAM_DATADGST_EN: len = sprintf(buf, "%d ", conn->datadgst_en); break; case ISCSI_PARAM_IFMARKER_EN: len = sprintf(buf, "%d ", conn->ifmarker_en); break; case ISCSI_PARAM_OFMARKER_EN: len = sprintf(buf, "%d ", conn->ofmarker_en); break; case ISCSI_PARAM_EXP_STATSN: len = sprintf(buf, "%u ", conn->exp_statsn); break; case ISCSI_PARAM_PERSISTENT_PORT: len = sprintf(buf, "%d ", conn->persistent_port); break; case ISCSI_PARAM_PERSISTENT_ADDRESS: len = sprintf(buf, "%s ", conn->persistent_address); break; default: return -ENOSYS; } return len; } EXPORT_SYMBOL_GPL(iscsi_conn_get_param); |
0801c242a [SCSI] libiscsi, ... |
3378 3379 3380 |
int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf) { |
756135215 [SCSI] iscsi: rem... |
3381 |
struct iscsi_host *ihost = shost_priv(shost); |
0801c242a [SCSI] libiscsi, ... |
3382 3383 3384 |
int len; switch (param) { |
d8196ed21 [SCSI] iscsi clas... |
3385 |
case ISCSI_HOST_PARAM_NETDEV_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3386 3387 |
len = sprintf(buf, "%s ", ihost->netdev); |
d8196ed21 [SCSI] iscsi clas... |
3388 |
break; |
0801c242a [SCSI] libiscsi, ... |
3389 |
case ISCSI_HOST_PARAM_HWADDRESS: |
5700b1af9 [SCSI] libiscsi: ... |
3390 3391 |
len = sprintf(buf, "%s ", ihost->hwaddress); |
0801c242a [SCSI] libiscsi, ... |
3392 |
break; |
8ad5781ae [SCSI] iscsi clas... |
3393 |
case ISCSI_HOST_PARAM_INITIATOR_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3394 3395 |
len = sprintf(buf, "%s ", ihost->initiatorname); |
8ad5781ae [SCSI] iscsi clas... |
3396 |
break; |
0801c242a [SCSI] libiscsi, ... |
3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 |
default: return -ENOSYS; } return len; } EXPORT_SYMBOL_GPL(iscsi_host_get_param); int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf, int buflen) { |
756135215 [SCSI] iscsi: rem... |
3408 |
struct iscsi_host *ihost = shost_priv(shost); |
0801c242a [SCSI] libiscsi, ... |
3409 3410 |
switch (param) { |
d8196ed21 [SCSI] iscsi clas... |
3411 |
case ISCSI_HOST_PARAM_NETDEV_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3412 |
return iscsi_switch_str_param(&ihost->netdev, buf); |
0801c242a [SCSI] libiscsi, ... |
3413 |
case ISCSI_HOST_PARAM_HWADDRESS: |
5700b1af9 [SCSI] libiscsi: ... |
3414 |
return iscsi_switch_str_param(&ihost->hwaddress, buf); |
8ad5781ae [SCSI] iscsi clas... |
3415 |
case ISCSI_HOST_PARAM_INITIATOR_NAME: |
5700b1af9 [SCSI] libiscsi: ... |
3416 |
return iscsi_switch_str_param(&ihost->initiatorname, buf); |
0801c242a [SCSI] libiscsi, ... |
3417 3418 3419 3420 3421 3422 3423 |
default: return -ENOSYS; } return 0; } EXPORT_SYMBOL_GPL(iscsi_host_set_param); |
7996a778f [SCSI] iscsi: add... |
3424 3425 3426 |
MODULE_AUTHOR("Mike Christie"); MODULE_DESCRIPTION("iSCSI library functions"); MODULE_LICENSE("GPL"); |