📄 target_task_man
字号:
Walking thru a Task Management Request on the UNH target.State-----There are 2 components to the state of a command at any time, written as: [iscsi-state, target-msg-state]where iscsi-state names start with ISCSI_xxx and represents the state seen by the rx_thread and tx_thread in iscsi_target.c,and target-msg-state names the state seen by the target_thread in scsi_target.c.State Transitions-----------------State at the end of each step in the diagrams that follow.0. [<null>, <null>]1. [ISCSI_DEQUEUE, <null>]2. [ISCSI_MGT_FN_DONE, <null>]3. [ISCSI_DEQUEUE, <null>]4. [<null>, <null>]Thread Interactions------------------- rx_thread tx_thread target_thread midlevel | | | | 1 ----------------------------> <------------ 2 3 4Overview--------0. [<null>, <null>]1. rx_thread gets new TASK MANAGEMENT pdu from initiator, allocates iscsi command for it and adds this to iscsi queue, then calls-back rx_task_mgmt_fn in target to allocate target msg, add it to target msg queue, and then wake up target_thread. [ISCSI_NEW_CMND, ABORT_TASK]2. target_thread finds and removes msg in msg queue searches for matching command and sets its abort_code calls back device's task_mgmt_fn_done() entry to set state = ISCSI_MGT_FN_DONE and wake up tx_thread [ISCSI_MGT_FN_DONE, <null>]3. tx_thread creates and sends TM Response pdu finds related command and sets its state to ISCSI_DEQUEUE [ISCSI_DEQUEUE, <null>]4. tx_thread removes command from iscsi queue [<null>, <null>]Details-------1. rx_thread in iscsi_target.c -> main loop in iscsi_rx_thread() read TASK MANAGEMENT Request Header (opcode 0x02) read and check header crc if header digest is on dispatch on opcode to case ISCSI_INIT_TASK_MGMT_CMND which calls handle_task_mgt_command() -> handle_task_mgt_command() convert big-endian to host pdu fields IN PLACE call get_new_cmnd() to allocate clean struct iscsi_cmnd *cmnd cmnd->state = ISCSI_NEW_CMND fill in fields in cmnd from pdu fill in default response = FUNCTION_COMPLETE call check_cmd_sn() to check CmdSN of pdu for in-order cmnd if cmnd is out-of-order, cmnd->state = ISCSI_QUEUE_CMND else call do_task_mgt() -----------------> do_task_mgt() in iscsi_target.c if function == ABORT_TASK search for command refered to by RTT if found call-back rx_task_mgmt_fn() if this fails set cmnd->response to FUNCTION_REJECTED cmnd->state = ISCSI_MGT_FN_DONE else call get_abort_response() to set cmnd->response to TASK_DOES_NOT_EXIST or FUNCTION_COMPLETE, as appropriate cmnd->state = ISCSI_MGT_FN_DONE else we don't support this TM function yet! set cmnd->response to TASK_MANAGEMENT_FUNCTION_NOT_SUPPORTED cmnd->state = ISCSI_MGT_FN_DONE <-------- call ack_sent_cmnds() to add this cmnd to session->cmnd_list <-------- -> rx_task_mgmt_fn in scsi_target.c allocate Target_Scsi_Message fill in fields in msg add msg to end of target_data.msgq up target_data.target_sem to wake up target thread At this point: cmnd (state=ISCSI_NEW_CMND) is in session->cmnd_list, command (message=ABORT_TASK) is in target_data.msgq target must act next2. target_thread in scsi_target.c -> main loop in scsi_target_process_thread() wake up after blocking on target_data.target_sem look at each msg in target_data.msgq remove msg from msgq dispatch on msg->message == ABORT_TASK search target_data.cmd_queue for command with matching id and lun if found set command's abort_code = CMND_ABORTED call abort_notify() free msg <-------- -> abort_notify() in scsi_target.c search target_data.st_device_list to find device with id that matches cmnd->dev_id if found call-back device's task_mgmt_fn_done() entry (which is iscsi_task_mgt_fn_done) -> iscsi_task_mgt_fn_done() in iscsi_target.c call search_task_mgt_command() to find related command if found state = ISCSI_MGT_FN_DONE up conn->tx_sem At this point: cmnd (state=ISCSI_MGT_FN_DONE) is in session->cmnd_list, msg is free and is NOT in target_data.msgq tx_thread must act next3. tx_thread in iscsi_target.c -> main loop in iscsi_tx_thread() wake up after blocking on conn->tx_sem look at each command in session->cmnd_list dispatch on state to case ISCSI_MGT_FN_DONE which calls handle_iscsi_mgt_fn_done() repeat loop -> handle_iscsi_mgt_fn_done() fill in fields in TASK MANAGEMENT Response pdu cmnd->state = ISCSI_DEQUEUE call send_hdr_only() to send TASK MANAGEMENT Response pdu call search_tags() to find aborted command if found set its state = ISCSI_DEQUEUE up on conn->tx_sem to wake tx_thread At this point: cmnd (state=ISCSI_DEQUEUE) is in session->cmnd_list, msg is free and is NOT in target_data.msgq tx_thread must act next4. tx_thread in iscsi_target.c -> main loop in iscsi_tx_thread() wake up after blocking on conn->tx_sem look at each command in session->cmnd_list dispatch on state to case ISCSI_DEQUEUE which removes command from list & calls iscsi_dequeue() then restarts loop -> iscsi_dequeue() if pointer to SCSI cmnd is not NULL call-back scsi_target_done() in scsi_target.c ----------------> scsi_target_done() state = ST_DEQUEUE up target_data.target_sem if this was connection's text_in_progess command, mark it freed free up structures pointed to by command free up command structure itself At this point: cmnd is free and is NOT in session->cmnd_list, msg is free and is NOT in target_data.msgq no more action needed on target side
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -