From: <vl...@us...> - 2007-08-28 17:32:34
|
Revision: 173 http://scst.svn.sourceforge.net/scst/?rev=173&view=rev Author: vlnb Date: 2007-08-28 10:32:31 -0700 (Tue, 28 Aug 2007) Log Message: ----------- - Fixed several iSCSI RFC violations in TM area, added necessary support in the SCST core - Some minor TM handling improvements - Some cleanups Modified Paths: -------------- trunk/iscsi-scst/kernel/iscsi.c trunk/iscsi-scst/kernel/iscsi.h trunk/iscsi-scst/kernel/iscsi_hdr.h trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_main.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/iscsi-scst/kernel/iscsi.c =================================================================== --- trunk/iscsi-scst/kernel/iscsi.c 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/iscsi-scst/kernel/iscsi.c 2007-08-28 17:32:31 UTC (rev 173) @@ -937,7 +937,7 @@ rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs; rsp_hdr->opcode = ISCSI_OP_R2T; rsp_hdr->flags = ISCSI_FLG_FINAL; - memcpy(rsp_hdr->lun, cmnd_hdr(req)->lun, 8); + rsp_hdr->lun = cmnd_hdr(req)->lun; rsp_hdr->itt = cmnd_hdr(req)->itt; rsp_hdr->r2t_sn = cpu_to_be32(req->r2t_sn++); rsp_hdr->buffer_offset = cpu_to_be32(offset); @@ -1130,7 +1130,7 @@ TRACE_DBG("scsi command: %02x", req_hdr->scb[0]); scst_cmd = scst_rx_cmd(session->scst_sess, - (uint8_t*)req_hdr->lun, sizeof(req_hdr->lun), + (uint8_t*)&req_hdr->lun, sizeof(req_hdr->lun), req_hdr->scb, sizeof(req_hdr->scb), SCST_NON_ATOMIC); if (scst_cmd == NULL) { create_status_rsp(req, SAM_STAT_BUSY, NULL, 0); @@ -1176,6 +1176,9 @@ break; } + /* cmd_sn is already in CPU format converted in check_cmd_sn() */ + scst_cmd_set_tgt_sn(scst_cmd, req_hdr->cmd_sn); + TRACE_DBG("START Command (tag %d, queue_type %d)", req_hdr->itt, scst_cmd->queue_type); req->scst_state = ISCSI_CMD_STATE_RX_CMD; @@ -1411,27 +1414,57 @@ return res; } -static int cmnd_abort(struct iscsi_session *session, u32 itt) +static int cmnd_abort(struct iscsi_cmnd *req) { + struct iscsi_session *session = req->conn->session; + struct iscsi_task_mgt_hdr *req_hdr = + (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; struct iscsi_cmnd *cmnd; int err; - if ((cmnd = cmnd_find_hash_get(session, itt, ISCSI_RESERVED_TAG))) { + if ((cmnd = cmnd_find_hash_get(session, req_hdr->rtt, ISCSI_RESERVED_TAG))) { struct iscsi_conn *conn = cmnd->conn; + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + + if (req_hdr->lun != hdr->lun) { + PRINT_ERROR_PR("ABORT TASK: LUN mismatch: req LUN " + "%Lx, cmd LUN %Lx, rtt %u", req_hdr->lun, + hdr->lun, req_hdr->rtt); + err = ISCSI_RESPONSE_FUNCTION_REJECTED; + goto out_put; + } + + if (before(req_hdr->cmd_sn, hdr->cmd_sn) || + (req_hdr->cmd_sn == hdr->cmd_sn)) { + PRINT_ERROR_PR("ABORT TASK: SN mismatch: req SN %x, " + "cmd SN %x, rtt %u", req_hdr->cmd_sn, + hdr->cmd_sn, req_hdr->rtt); + err = ISCSI_RESPONSE_FUNCTION_REJECTED; + goto out_put; + } + spin_lock_bh(&conn->cmd_list_lock); __cmnd_abort(cmnd); spin_unlock_bh(&conn->cmd_list_lock); + cmnd_put(cmnd); err = 0; } else err = ISCSI_RESPONSE_UNKNOWN_TASK; +out: return err; + +out_put: + cmnd_put(cmnd); + goto out; } -static int target_abort(struct iscsi_cmnd *req, u16 *lun, int all) +static int target_abort(struct iscsi_cmnd *req, int all) { struct iscsi_target *target = req->conn->session->target; + struct iscsi_task_mgt_hdr *req_hdr = + (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_cmnd *cmnd; @@ -1448,8 +1481,7 @@ continue; if (all) again = __cmnd_abort(cmnd); - else if (memcmp(lun, &cmnd_hdr(cmnd)->lun, - sizeof(cmnd_hdr(cmnd)->lun)) == 0) + else if (req_hdr->lun == cmnd_hdr(cmnd)->lun) again = __cmnd_abort(cmnd); if (again) goto again; @@ -1465,6 +1497,8 @@ static void task_set_abort(struct iscsi_cmnd *req) { struct iscsi_session *session = req->conn->session; + struct iscsi_task_mgt_hdr *req_hdr = + (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; struct iscsi_target *target = session->target; struct iscsi_conn *conn; struct iscsi_cmnd *cmnd; @@ -1475,9 +1509,16 @@ spin_lock_bh(&conn->cmd_list_lock); again: list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) { - if (cmnd != req) - if (__cmnd_abort(cmnd)) - goto again; + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + if (cmnd == req) + continue; + if (req_hdr->lun != hdr->lun) + continue; + if (before(req_hdr->cmd_sn, hdr->cmd_sn) || + req_hdr->cmd_sn == hdr->cmd_sn) + continue; + if (__cmnd_abort(cmnd)) + goto again; } spin_unlock_bh(&conn->cmd_list_lock); } @@ -1504,61 +1545,91 @@ static void execute_task_management(struct iscsi_cmnd *req) { struct iscsi_conn *conn = req->conn; - struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; + struct iscsi_task_mgt_hdr *req_hdr = + (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; int err = 0, function = req_hdr->function & ISCSI_FUNCTION_MASK; + struct scst_rx_mgmt_params params; TRACE(TRACE_MGMT, "TM cmd: req %p, itt %x, fn %d, rtt %x", req, cmnd_itt(req), function, req_hdr->rtt); - /* - * ToDo: relevant TM functions shall affect only commands with - * CmdSN lower req_hdr->cmd_sn (see RFC 3720 section 10.5). - * - * I suppose, iscsi_session_push_cmnd() should be updated to keep - * commands with higher CmdSN in the session->pending_list until - * executing TM command finished. Although, if higher CmdSN commands - * might be already sent to SCST for execution, it could get much more - * complicated and should be implemented on SCST level. - */ + memset(¶ms, 0, sizeof(params)); + params.atomic = SCST_NON_ATOMIC; + params.tgt_priv = req; + + if ((function != ISCSI_FUNCTION_ABORT_TASK) && + (req_hdr->rtt != ISCSI_RESERVED_TAG)) { + PRINT_ERROR_PR("Invalid RTT %x (TM fn %x)", req_hdr->rtt, + function); + err = -1; + goto reject; + } + /* cmd_sn is already in CPU format converted in check_cmd_sn() */ + switch (function) { case ISCSI_FUNCTION_ABORT_TASK: - err = cmnd_abort(conn->session, req_hdr->rtt); + err = cmnd_abort(req); if (err == 0) { - err = scst_rx_mgmt_fn_tag(conn->session->scst_sess, - SCST_ABORT_TASK, req_hdr->rtt, SCST_NON_ATOMIC, - req); + params.fn = SCST_ABORT_TASK; + params.tag = req_hdr->rtt; + params.tag_set = 1; + params.lun = (uint8_t *)&req_hdr->lun; + params.lun_len = sizeof(req_hdr->lun); + params.lun_set = 1; + params.cmd_sn = req_hdr->cmd_sn; + params.cmd_sn_set = 1; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); } break; case ISCSI_FUNCTION_ABORT_TASK_SET: task_set_abort(req); - err = scst_rx_mgmt_fn_lun(conn->session->scst_sess, - SCST_ABORT_TASK_SET, (uint8_t *)req_hdr->lun, - sizeof(req_hdr->lun), SCST_NON_ATOMIC, req); + params.fn = SCST_ABORT_TASK_SET; + params.lun = (uint8_t *)&req_hdr->lun; + params.lun_len = sizeof(req_hdr->lun); + params.lun_set = 1; + params.cmd_sn = req_hdr->cmd_sn; + params.cmd_sn_set = 1; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); break; case ISCSI_FUNCTION_CLEAR_TASK_SET: task_set_abort(req); - err = scst_rx_mgmt_fn_lun(conn->session->scst_sess, - SCST_CLEAR_TASK_SET, (uint8_t *)req_hdr->lun, - sizeof(req_hdr->lun), SCST_NON_ATOMIC, req); + params.fn = SCST_CLEAR_TASK_SET; + params.lun = (uint8_t *)&req_hdr->lun; + params.lun_len = sizeof(req_hdr->lun); + params.lun_set = 1; + params.cmd_sn = req_hdr->cmd_sn; + params.cmd_sn_set = 1; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); break; case ISCSI_FUNCTION_CLEAR_ACA: - err = scst_rx_mgmt_fn_lun(conn->session->scst_sess, - SCST_CLEAR_ACA, (uint8_t *)req_hdr->lun, - sizeof(req_hdr->lun), SCST_NON_ATOMIC, req); + params.fn = SCST_CLEAR_ACA; + params.lun = (uint8_t *)&req_hdr->lun; + params.lun_len = sizeof(req_hdr->lun); + params.lun_set = 1; + params.cmd_sn = req_hdr->cmd_sn; + params.cmd_sn_set = 1; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); break; case ISCSI_FUNCTION_TARGET_COLD_RESET: case ISCSI_FUNCTION_TARGET_WARM_RESET: - target_abort(req, 0, 1); - err = scst_rx_mgmt_fn_lun(conn->session->scst_sess, - SCST_TARGET_RESET, (uint8_t *)req_hdr->lun, - sizeof(req_hdr->lun), SCST_NON_ATOMIC, req); + target_abort(req, 1); + params.fn = SCST_TARGET_RESET; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); break; case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: - target_abort(req, req_hdr->lun, 0); - err = scst_rx_mgmt_fn_lun(conn->session->scst_sess, - SCST_LUN_RESET, (uint8_t *)req_hdr->lun, - sizeof(req_hdr->lun), SCST_NON_ATOMIC, req); + target_abort(req, 0); + params.fn = SCST_LUN_RESET; + params.lun = (uint8_t *)&req_hdr->lun; + params.lun_len = sizeof(req_hdr->lun); + params.lun_set = 1; + err = scst_rx_mgmt_fn(conn->session->scst_sess, + ¶ms); break; case ISCSI_FUNCTION_TASK_REASSIGN: iscsi_send_task_mgmt_resp(req, @@ -1570,6 +1641,7 @@ break; } +reject: if (err != 0) { iscsi_send_task_mgmt_resp(req, ISCSI_RESPONSE_FUNCTION_REJECTED); Modified: trunk/iscsi-scst/kernel/iscsi.h =================================================================== --- trunk/iscsi-scst/kernel/iscsi.h 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/iscsi-scst/kernel/iscsi.h 2007-08-28 17:32:31 UTC (rev 173) @@ -407,12 +407,6 @@ #endif } -#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs))) -#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt) -#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt) -#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK) -#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0] - extern struct scst_tgt_template iscsi_template; static inline void cmnd_get(struct iscsi_cmnd *cmnd) Modified: trunk/iscsi-scst/kernel/iscsi_hdr.h =================================================================== --- trunk/iscsi-scst/kernel/iscsi_hdr.h 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/iscsi-scst/kernel/iscsi_hdr.h 2007-08-28 17:32:31 UTC (rev 173) @@ -38,7 +38,7 @@ #elif defined(__LITTLE_ENDIAN_BITFIELD) u32 length; /* 4 */ #endif - u16 lun[4]; /* 8 */ + u64 lun; /* 8 */ u32 itt; /* 16 */ u32 ttt; /* 20 */ u32 sn; /* 24 */ @@ -101,7 +101,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 data_length; u32 cmd_sn; @@ -170,7 +170,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 rtt; u32 cmd_sn; @@ -222,7 +222,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 ttt; u32 rsvd2; @@ -259,7 +259,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 ttt; u32 stat_sn; @@ -276,7 +276,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 ffffffff; u32 rsvd2; u32 stat_sn; @@ -491,7 +491,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 ttt; u32 cmd_sn; @@ -505,7 +505,7 @@ u16 rsvd1; u8 ahslength; u8 datalength[3]; - u16 lun[4]; + u64 lun; u32 itt; u32 ttt; u32 stat_sn; @@ -516,4 +516,11 @@ #define ISCSI_RESERVED_TAG (0xffffffffU) +#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs))) +#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt) +#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt) +#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK) +#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0] + + #endif /* __ISCSI_HDR_H__ */ Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/scst/include/scsi_tgt.h 2007-08-28 17:32:31 UTC (rev 173) @@ -1056,8 +1056,11 @@ * Set if inc expected_sn in cmd->scst_cmd_done() (to * save extra dereferences) */ - unsigned inc_expected_sn_on_done:1; + unsigned int inc_expected_sn_on_done:1; + /* Set if tgt_sn field is valid */ + unsigned int tgt_sn_set:1; + /**************************************************************/ unsigned long cmd_flags; /* cmd's async flags */ @@ -1095,6 +1098,8 @@ */ uint64_t tag; + uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */ + /* CDB and its len */ uint8_t cdb[SCST_MAX_CDB_SIZE]; int cdb_len; @@ -1167,6 +1172,20 @@ struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */ }; +struct scst_rx_mgmt_params +{ + int fn; + uint64_t tag; + const uint8_t *lun; + int lun_len; + uint32_t cmd_sn; + int atomic; + void *tgt_priv; + unsigned char tag_set; + unsigned char lun_set; + unsigned char cmd_sn_set; +}; + struct scst_mgmt_cmd { /* List entry for *_mgmt_cmd_list */ @@ -1181,6 +1200,10 @@ unsigned int completed:1; /* set, if the mcmd is completed */ unsigned int active:1; /* set, if the mcmd is active */ + /* Set if device(s) should be unblocked after mcmd's finish */ + unsigned int needs_unblocking:1; + unsigned int lun_set:1; /* set, if lun field is valid */ + unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */ /* * Number of commands to complete before sending response, @@ -1192,9 +1215,11 @@ int completed_cmd_count; lun_t lun; /* LUN for this mgmt cmd */ - /* or */ + /* or (and for iSCSI) */ uint64_t tag; /* tag of the corresponding cmd */ + uint32_t cmd_sn; /* affected command's highest SN */ + /* corresponding cmd (to be aborted, found by tag) */ struct scst_cmd *cmd_to_abort; @@ -1590,7 +1615,7 @@ /* * Creates and sends new command to SCST. - * Must not been called in parallel with scst_unregister_session() for the + * Must not be called in parallel with scst_unregister_session() for the * same sess. Returns the command on success or NULL otherwise */ struct scst_cmd *scst_rx_cmd(struct scst_session *sess, @@ -1662,24 +1687,62 @@ void scst_tgt_cmd_done(struct scst_cmd *cmd); /* + * Creates new management command sends it for execution. + * Must not be called in parallel with scst_unregister_session() for the + * same sess. Returns 0 for success, error code otherwise. + */ +int scst_rx_mgmt_fn(struct scst_session *sess, + const struct scst_rx_mgmt_params *params); + +/* * Creates new management command using tag and sends it for execution. * Can be used for SCST_ABORT_TASK only. - * Must not been called in parallel with scst_unregister_session() for the + * Must not be called in parallel with scst_unregister_session() for the * same sess. Returns 0 for success, error code otherwise. + * + * Obsolete in favor of scst_rx_mgmt_fn() */ -int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint64_t tag, - int atomic, void *tgt_priv); +static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, + uint64_t tag, int atomic, void *tgt_priv) +{ + struct scst_rx_mgmt_params params; + BUG_ON(fn != SCST_ABORT_TASK); + + memset(¶ms, 0, sizeof(params)); + params.fn = fn; + params.tag = tag; + params.tag_set = 1; + params.atomic = atomic; + params.tgt_priv = tgt_priv; + return scst_rx_mgmt_fn(sess, ¶ms); +} + /* * Creates new management command using LUN and sends it for execution. * Currently can be used for any fn, except SCST_ABORT_TASK. - * Must not been called in parallel with scst_unregister_session() for the + * Must not be called in parallel with scst_unregister_session() for the * same sess. Returns 0 for success, error code otherwise. + * + * Obsolete in favor of scst_rx_mgmt_fn() */ -int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn, - const uint8_t *lun, int lun_len, - int atomic, void *tgt_priv); +static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn, + const uint8_t *lun, int lun_len, int atomic, void *tgt_priv) +{ + struct scst_rx_mgmt_params params; + BUG_ON(fn == SCST_ABORT_TASK); + + memset(¶ms, 0, sizeof(params)); + params.fn = fn; + params.lun = lun; + params.lun_len = lun_len; + params.lun_set = 1; + params.atomic = atomic; + params.tgt_priv = tgt_priv; + return scst_rx_mgmt_fn(sess, ¶ms); +} + /* * Provides various CDB info * Parameters: @@ -1992,6 +2055,22 @@ } /* + * Get/Set functions for tgt_sn + */ +static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd) +{ + BUG_ON(!cmd->tgt_sn_set); + return cmd->tgt_sn; +} + +static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn) +{ + cmd->tgt_sn_set = 1; + cmd->tgt_sn = tgt_sn; +} + + +/* * Returns 1 if the cmd was aborted, so its status is invalid and no * reply shall be sent to the remote initiator. A target driver should * only clear internal resources, associated with cmd. Modified: trunk/scst/src/scst_main.c =================================================================== --- trunk/scst/src/scst_main.c 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/scst/src/scst_main.c 2007-08-28 17:32:31 UTC (rev 173) @@ -1633,8 +1633,7 @@ EXPORT_SYMBOL(scst_restart_cmd); EXPORT_SYMBOL(scst_rx_cmd); EXPORT_SYMBOL(scst_rx_data); -EXPORT_SYMBOL(scst_rx_mgmt_fn_tag); -EXPORT_SYMBOL(scst_rx_mgmt_fn_lun); +EXPORT_SYMBOL(scst_rx_mgmt_fn); EXPORT_SYMBOL(scst_find_cmd); EXPORT_SYMBOL(scst_find_cmd_by_tag); Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/scst/src/scst_priv.h 2007-08-28 17:32:31 UTC (rev 173) @@ -558,4 +558,13 @@ static inline void scst_check_debug_sn(struct scst_cmd *cmd) {} #endif +/* + * It deals with comparing 32 bit unsigned ints and worry about wraparound + * (automatic with unsigned arithmetic). Borrowed from net/tcp.h. + */ +static inline int scst_sn_before(__u32 seq1, __u32 seq2) +{ + return (__s32)(seq1-seq2) < 0; +} + #endif /* __SCST_PRIV_H */ Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-08-27 10:49:04 UTC (rev 172) +++ trunk/scst/src/scst_targ.c 2007-08-28 17:32:31 UTC (rev 173) @@ -49,7 +49,7 @@ } /* - * Must not been called in parallel with scst_unregister_session() for the + * Must not be called in parallel with scst_unregister_session() for the * same sess */ struct scst_cmd *scst_rx_cmd(struct scst_session *sess, @@ -3397,8 +3397,15 @@ search_cmd_list_entry) { if ((cmd->tgt_dev == tgt_dev) || ((cmd->tgt_dev == NULL) && - (cmd->lun == tgt_dev->lun))) + (cmd->lun == tgt_dev->lun))) { + if (mcmd->cmd_sn_set) { + sBUG_ON(!cmd->tgt_sn_set); + if (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) || + (mcmd->cmd_sn == cmd->tgt_sn)) + continue; + } scst_abort_cmd(cmd, mcmd, other_ini, 0); + } } spin_unlock_irq(&sess->sess_list_lock); @@ -3418,6 +3425,8 @@ TRACE(TRACE_MGMT, "Aborting task set (lun=%Ld, mcmd=%p)", tgt_dev->lun, mcmd); + mcmd->needs_unblocking = 1; + spin_lock_bh(&dev->dev_lock); __scst_block_dev(dev); spin_unlock_bh(&dev->dev_lock); @@ -3452,7 +3461,7 @@ * >0, if it should be requeued, <0 otherwise */ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd) { - int res = 0; + int res = 0, rc; TRACE_ENTRY(); @@ -3460,7 +3469,11 @@ if (res != 0) goto out; - if (mcmd->fn == SCST_ABORT_TASK) { + mcmd->state = SCST_MGMT_CMD_STATE_READY; + + switch (mcmd->fn) { + case SCST_ABORT_TASK: + { struct scst_session *sess = mcmd->sess; struct scst_cmd *cmd; @@ -3479,23 +3492,43 @@ TRACE(TRACE_MGMT, "Cmd %p for tag %llu (sn %ld) found, " "aborting it", cmd, mcmd->tag, cmd->sn); mcmd->cmd_to_abort = cmd; - scst_abort_cmd(cmd, mcmd, 0, 1); - scst_unblock_aborted_cmds(0); + if (mcmd->lun_set && (mcmd->lun != cmd->lun)) { + PRINT_ERROR_PR("ABORT TASK: LUN mismatch: mcmd LUN %Lx, " + "cmd LUN %Lx, cmd tag %Lu", mcmd->lun, cmd->lun, + mcmd->tag); + mcmd->status = SCST_MGMT_STATUS_REJECTED; + } else if (mcmd->cmd_sn_set && + (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) || + (mcmd->cmd_sn == cmd->tgt_sn))) { + PRINT_ERROR_PR("ABORT TASK: SN mismatch: mcmd SN %x, " + "cmd SN %x, cmd tag %Lu", mcmd->cmd_sn, + cmd->tgt_sn, mcmd->tag); + mcmd->status = SCST_MGMT_STATUS_REJECTED; + } else { + scst_abort_cmd(cmd, mcmd, 0, 1); + scst_unblock_aborted_cmds(0); + } res = scst_set_mcmd_next_state(mcmd); mcmd->cmd_to_abort = NULL; /* just in case */ scst_cmd_put(cmd); - } else { - int rc; + break; + } + + case SCST_TARGET_RESET: + case SCST_ABORT_ALL_TASKS: + case SCST_NEXUS_LOSS: + break; + + default: rc = scst_mgmt_translate_lun(mcmd); if (rc < 0) { PRINT_ERROR_PR("Corresponding device for lun %Ld not " "found", (uint64_t)mcmd->lun); mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST; mcmd->state = SCST_MGMT_CMD_STATE_DONE; - } else if (rc == 0) - mcmd->state = SCST_MGMT_CMD_STATE_READY; - else + } else if (rc != 0) res = rc; + break; } out: @@ -3517,6 +3550,8 @@ TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)", mcmd, atomic_read(&mcmd->sess->sess_cmd_count)); + mcmd->needs_unblocking = 1; + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { @@ -3603,6 +3638,8 @@ TRACE(TRACE_MGMT, "Resetting lun %Ld (mcmd %p)", tgt_dev->lun, mcmd); + mcmd->needs_unblocking = 1; + spin_lock_bh(&dev->dev_lock); __scst_block_dev(dev); scst_process_reset(dev, mcmd->sess, NULL, mcmd); @@ -3648,6 +3685,8 @@ mcmd); } + mcmd->needs_unblocking = 1; + mutex_lock(&scst_mutex); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = @@ -3699,6 +3738,8 @@ mcmd); } + mcmd->needs_unblocking = 1; + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { @@ -3828,7 +3869,7 @@ mcmd->sess->tgt->tgtt->name); } - if (mcmd->mcmd_tgt_dev != NULL) { + if (mcmd->needs_unblocking) { switch (mcmd->fn) { case SCST_ABORT_TASK_SET: case SCST_CLEAR_TASK_SET: @@ -3864,8 +3905,8 @@ break; } - case SCST_CLEAR_ACA: default: + sBUG(); break; } } @@ -4085,74 +4126,51 @@ } /* - * Must not been called in parallel with scst_unregister_session() for the + * Must not be called in parallel with scst_unregister_session() for the * same sess */ -int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn, - const uint8_t *lun, int lun_len, int atomic, - void *tgt_priv) +int scst_rx_mgmt_fn(struct scst_session *sess, + const struct scst_rx_mgmt_params *params) { int res = -EFAULT; struct scst_mgmt_cmd *mcmd = NULL; TRACE_ENTRY(); - if (unlikely(fn == SCST_ABORT_TASK)) { - PRINT_ERROR_PR("%s() for ABORT TASK called", __FUNCTION__); - res = -EINVAL; - goto out; + switch (params->fn) { + case SCST_ABORT_TASK: + sBUG_ON(!params->tag_set); + break; + case SCST_TARGET_RESET: + case SCST_ABORT_ALL_TASKS: + case SCST_NEXUS_LOSS: + break; + default: + sBUG_ON(!params->lun_set); } - mcmd = scst_pre_rx_mgmt_cmd(sess, fn, atomic, tgt_priv); + mcmd = scst_pre_rx_mgmt_cmd(sess, params->fn, params->atomic, + params->tgt_priv); if (mcmd == NULL) goto out; - mcmd->lun = scst_unpack_lun(lun, lun_len); - if (mcmd->lun == (lun_t)-1) - goto out_free; - - TRACE(TRACE_MGMT, "sess=%p, lun=%Ld", sess, (uint64_t)mcmd->lun); - - if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0) - goto out_free; - - res = 0; - -out: - TRACE_EXIT_RES(res); - return res; - -out_free: - scst_free_mgmt_cmd(mcmd); - mcmd = NULL; - goto out; -} - -/* - * Must not been called in parallel with scst_unregister_session() for the - * same sess - */ -int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint64_t tag, - int atomic, void *tgt_priv) -{ - int res = -EFAULT; - struct scst_mgmt_cmd *mcmd = NULL; - - TRACE_ENTRY(); - - if (unlikely(fn != SCST_ABORT_TASK)) { - PRINT_ERROR_PR("%s(%d) called", __FUNCTION__, fn); - res = -EINVAL; - goto out; + if (params->lun_set) { + mcmd->lun = scst_unpack_lun(params->lun, params->lun_len); + if (mcmd->lun == (lun_t)-1) + goto out_free; + mcmd->lun_set = 1; } - mcmd = scst_pre_rx_mgmt_cmd(sess, fn, atomic, tgt_priv); - if (mcmd == NULL) - goto out; + if (params->tag_set) + mcmd->tag = params->tag; - mcmd->tag = tag; + mcmd->cmd_sn_set = params->cmd_sn_set; + mcmd->cmd_sn = params->cmd_sn; - TRACE(TRACE_MGMT, "sess=%p, tag=%llu", sess, mcmd->tag); + TRACE(TRACE_MGMT, "sess=%p, fn %x, tag_set %d, tag %Ld, lun_set %d, " + "lun=%Ld, cmd_sn_set %d, cmd_sn %x", sess, params->fn, + params->tag_set, params->tag, params->lun_set, + (uint64_t)mcmd->lun, params->cmd_sn_set, params->cmd_sn); if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0) goto out_free; @@ -4354,7 +4372,7 @@ } /* - * Must not been called in parallel with scst_rx_cmd() or + * Must not be called in parallel with scst_rx_cmd() or * scst_rx_mgmt_fn_*() for the same sess */ void scst_unregister_session(struct scst_session *sess, int wait, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |