scst-iscsi程式架構
(1)static int __init iscsi_init(void)
可以先看到的是iscsit_reg_transport(&iscsi_tcp_transport);註冊
這個部分的使用會是在scst那邊. 所以你不會看到類似while,while的使用會是在scst
可以看到預設使用iSCSI-TCP
iscsi_conn_alloc: 主要是建立連線的部分
TRACE(TRACE_MGMT, "Creating connection %p for sid %#Lx, cid %u "
"(initiator %s)", conn, (unsigned long long int)session->sid,
info->cid, session->scst_sess->initiator_name);
一開始的讀寫狀態為
conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
讀寫狀態
#define ISCSI_CONN_RD_STATE_IDLE 0
#define ISCSI_CONN_RD_STATE_IN_LIST 1
#define ISCSI_CONN_RD_STATE_PROCESSING 2
#define ISCSI_CONN_WR_STATE_IDLE 0
#define ISCSI_CONN_WR_STATE_IN_LIST 1
#define ISCSI_CONN_WR_STATE_SPACE_WAIT 2
#define ISCSI_CONN_WR_STATE_PROCESSING 3
conn_rsp_timer_fn這個函數裡面,有決定連線timeout的參數
PRINT_ERROR("Timeout %ld sec sending data/waiting "
"for reply to/from initiator "
"%s (SID %llx), closing connection %p",
iscsi_get_timeout(cmnd)/HZ,
conn->session->initiator_name,
(unsigned long long int) conn->session->sid,
conn);
iscsi_tcp_send_data_rsp 這個我理解成response
因為#define ISCSI_OP_SCSI_DATA_IN 0x25
/* Server to Client Message Opcode values */ <---有註解
static inline void cmd_add_on_write_list(struct iscsi_conn *conn,
struct iscsi_cmnd *cmnd) 似乎將寫的命令放在buffer list
iscsi_make_conn_wr_active <---只是放在list上 , active?
if (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE) {
list_add_tail(&conn->wr_list_entry, &p->wr_list);
conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
wake_up(&p->wr_waitQ);
}
iscsi_tcp_get_initiator_ip: 取得使用者的ip
因為一部分寫在doc,之後有空再補
https://drive.google.com/file/d/0B8hm-I2M8BD7MVRmLXRCeklhX0E/view?usp=sharing
隨手記:
static int write_data(struct iscsi_conn *conn){
timer相關部分是使用 add_timer(&timer);
}
int iscsi_init_conn(struct iscsi_session *session,
static void iscsi_data_ready(struct sock *sk) socket帶資料
unsigned long timeout_time = j + ISCSI_TM_DATA_WAIT_TIMEOUT +
ISCSI_ADD_SCHED_TIME;
static inline unsigned long iscsi_get_timeout(struct iscsi_cmnd *req)
{
unsigned long res;
res = (cmnd_opcode(req) == ISCSI_OP_NOP_OUT) ?
req->conn->nop_in_timeout : req->conn->data_rsp_timeout;
if (unlikely(test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags)))
res = min_t(unsigned long, res, ISCSI_TM_DATA_WAIT_TIMEOUT);
return res;
}
{
unsigned long res;
res = (cmnd_opcode(req) == ISCSI_OP_NOP_OUT) ?
req->conn->nop_in_timeout : req->conn->data_rsp_timeout;
if (unlikely(test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags)))
res = min_t(unsigned long, res, ISCSI_TM_DATA_WAIT_TIMEOUT);
return res;
}
static inline void
iscsi_cmnd_set_length(struct iscsi_pdu *pdu)
{
#if defined(__BIG_ENDIAN)
pdu->bhs.length.ahslength
= pdu->ahssize / 4;
pdu->bhs.length.datalength = pdu->datasize;
#elif defined(__LITTLE_ENDIAN)
pdu->bhs.length
= cpu_to_be32(pdu->datasize) | (__force __be32)(pdu->ahssize / 4);
#else
#error
#endif
}
int iscsi_send(struct iscsi_conn *conn)
在這段函數裡面可以看到
switch (conn->write_state){
case TX_INIT::
break;
case TX_BHS_DATA
case TX_INIT_PADDING
case TX_PADDING
case TX_INIT_DDIGEST
case TX_DDIGEST
}
static int write_data(struct iscsi_conn *conn) <----這邊有做file system write
res = vfs_writev(file,
(struct iovec __force __user *)iop,
count, &off);
static void set_cork(struct socket *sock, int on)
{
sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, <----很明顯socket設定
(void __force __user *)&opt, sizeof(opt));
}
static int write_data(struct iscsi_conn *conn){
req_add_to_write_timeout_list(write_cmnd->parent_req); <---這邊做timeout
}
void cmnd_tx_start(struct iscsi_cmnd *cmnd)
可以看到 cmnd_set_sn
{
cmnd->pdu.bhs.sn = (__force u32)cpu_to_be32(conn->stat_sn++);
cmnd->pdu.bhs.exp_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn);
cmnd->pdu.bhs.max_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn +
}
感覺是做資料編隊的
在這邊struct iscsi_conn
struct iovec *write_iop;
int write_iop_used;.
感覺跟iops有關.
abort機制scst_abort_cmd
timer:
static void conn_rsp_timer_fn(unsigned long arg)
time out 之後會跑到 static void close_conn(struct iscsi_conn *conn)
開啟 conn_abort(conn);
所以abort其中一個情形是,write_data太久會造成abort
函數追蹤順序為
static int write_data->req_add_to_write_timeout_list->add_timer(&conn->rsp_timer);->
setup_timer(&conn->rsp_timer, conn_rsp_timer_fn, (unsigned long)conn);->
mark_conn_closed-> conn->closing = 1; -> static void close_conn(struct iscsi_conn *conn)
iscsi的一些參數調整
param.c session_keys 可以調整MaxRecvDataSegmentLength MaxXmitDataSegmentLength
沒有留言:
張貼留言