2016年11月14日 星期一

scst 裡面的 iscsi 架構

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;
}



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

沒有留言:

張貼留言