runsisi's

technical notes

Linux iSCSI

2019-10-30 runsisi#scsi

专职 iSCSI target 开发已经是四五年前的事情了,最近发现有些命令都有些生疏了。简单总结一下 Linux 下 iSCSI 的使用和 iSCSI initiator 内核态代码流程。

iscsi

环境为 CentOS 7.x,需要注意的是,Ubuntu 下的 targetcli 与 CentOS 下的 targetcli 使用的是不同的 fork。

target 配置

$ fallocate -l $((1024 * 1024 * 1024)) dat
$ ll -h dat
-rw-r--r--. 1 runsisi runsisi 1.0G Oct 28 14:01 dat
$ sudo targetcli
/> cd /backstores/fileio
/backstores/fileio> create file_or_dev=dat name=xxx
Created fileio xxx with size 1073741824
/backstores/fileio> cd /iscsi/
/iscsi> create
Created target iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.
/iscsi> cd iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1/tpg1/luns/
/iscsi/iqn.20...cd1/tpg1/luns> create /backstores/fileio/xxx
Created LUN 0.
/iscsi/iqn.20...cd1/tpg1/luns> cd /iscsi/
/iscsi> set discovery_auth enable=0
Parameter enable is now 'False'.
/iscsi> cd iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1/tpg1/
/iscsi/iqn.20...795b3cd1/tpg1> set attribute authentication=0
Parameter authentication is now '0'.
/iscsi/iqn.20...795b3cd1/tpg1> set parameter AuthMethod=None
Parameter AuthMethod is now 'None'.
/iscsi/iqn.20...795b3cd1/tpg1> cd acls/ 
/iscsi/iqn.20...cd1/tpg1/acls> create iqn.1994-05.com.redhat:6eff34aa8f8
Created Node ACL for iqn.1994-05.com.redhat:6eff34aa8f8
Created mapped LUN 0.
/iscsi/iqn.20...cd1/tpg1/acls> ls /
o- / ......................................................................................................................... [...]
  o- backstores .............................................................................................................. [...]
  | o- block .................................................................................................. [Storage Objects: 0]
  | o- fileio ................................................................................................. [Storage Objects: 1]
  | | o- xxx ................................................................................... [dat (1.0GiB) write-back activated]
  | |   o- alua ................................................................................................... [ALUA Groups: 1]
  | |     o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
  | o- pscsi .................................................................................................. [Storage Objects: 0]
  | o- ramdisk ................................................................................................ [Storage Objects: 0]
  o- iscsi ............................................................................................................ [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 .......................................................... [TPGs: 1]
  |   o- tpg1 ............................................................................................... [no-gen-acls, no-auth]
  |     o- acls .......................................................................................................... [ACLs: 1]
  |     | o- iqn.1994-05.com.redhat:6eff34aa8f8 ................................................................... [Mapped LUNs: 1]
  |     |   o- mapped_lun0 .................................................................................. [lun0 fileio/xxx (rw)]
  |     o- luns .......................................................................................................... [LUNs: 1]
  |     | o- lun0 ............................................................................ [fileio/xxx (dat) (default_tg_pt_gp)]
  |     o- portals .................................................................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 ..................................................................................................... [OK]
  o- loopback ......................................................................................................... [Targets: 0]
  o- qla2xxx .......................................................................................................... [Targets: 0]
/iscsi/iqn.20...cd1/tpg1/acls> cd /
/> saveconfig
Configuration saved to /etc/target/saveconfig.json
/> exit
Global pref auto_save_on_exit=true
Configuration saved to /etc/target/saveconfig.json
ISCSI-SPECIFIC
       discovery_auth
       /iscsi  configuration  node.  Set the normal and mutual authentication userid and password
       for discovery sessions, as well as enabling or disabling it. By default it is disabled  --
       no authentication is required for discovery.

       parameter
       /iscsi/<target_iqn>/tpgX configuration node. ISCSI-specific parameters such as AuthMethod,
       MaxBurstLength, IFMarker, DataDigest, and similar.

       attribute
       /iscsi/<target_iqn>/tpgX configuration node. Contains implementation-specific settings for
       the TPG, such as authentication, to enforce or disable authentication for the full-feature
       phase (i.e. non-discovery).

       auth
       /iscsi/<target_iqn>/tpgX/acls/<initiator_iqn>  configuration  node.  Set  the  userid  and
       password for full-feature phase for this ACL.
$ ss -ntpl | grep 3260 
LISTEN     0      256          *:3260                     *:*
# lsmod | grep iscsi
iscsi_target_mod      287476  7 
target_core_mod       342807  15 target_core_iblock,target_core_pscsi,iscsi_target_mod,target_core_file,target_core_user

initiator 配置

$ cat /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.1994-05.com.redhat:6eff34aa8f8
$ sudo vi /etc/iscsi/iscsid.conf 
# *************
# CHAP Settings
# *************

# To enable CHAP authentication set node.session.auth.authmethod
# to CHAP. The default is None.
#node.session.auth.authmethod = CHAP

# To set a CHAP username and password for initiator
# authentication by the target(s), uncomment the following lines:
#node.session.auth.username = username
#node.session.auth.password = password

# To set a CHAP username and password for target(s)
# authentication by the initiator, uncomment the following lines:
#node.session.auth.username_in = username_in
#node.session.auth.password_in = password_in

# To enable CHAP authentication for a discovery session to the target
# set discovery.sendtargets.auth.authmethod to CHAP. The default is None.
#discovery.sendtargets.auth.authmethod = CHAP

# To set a discovery session CHAP username and password for the initiator
# authentication by the target(s), uncomment the following lines:
#discovery.sendtargets.auth.username = username
#discovery.sendtargets.auth.password = password

# To set a discovery session CHAP username and password for target(s)
# authentication by the initiator, uncomment the following lines:
#discovery.sendtargets.auth.username_in = username_in
#discovery.sendtargets.auth.password_in = password_in
$ sudo iscsiadm -m discovery -t st -p 192.168.5.3
192.168.5.3:3260,1 iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1
$ sudo iscsiadm -m discovery -P 1
SENDTARGETS:
DiscoveryAddress: 192.168.5.3,3260
Target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1
        Portal: 192.168.5.3:3260,1
                Iface Name: default
$ sudo iscsiadm -m node -l
Logging in to [iface: default, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260] (multiple)
Login to [iface: default, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260] successful.
$ sudo iscsiadm -m session -P 3
iSCSI Transport Class version 2.0-870
version 6.2.0.874-7
Target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 (non-flash)
        Current Portal: 192.168.5.3:3260,1
        Persistent Portal: 192.168.5.3:3260,1
                **********
                Interface:
                **********
                Iface Name: default
                Iface Transport: tcp
                Iface Initiatorname: iqn.1994-05.com.redhat:6eff34aa8f8
                Iface IPaddress: 192.168.5.2
                Iface HWaddress: <empty>
                Iface Netdev: <empty>
                SID: 2
                iSCSI Connection State: LOGGED IN
                iSCSI Session State: LOGGED_IN
                Internal iscsid Session State: NO CHANGE
                *********
                Timeouts:
                *********
                Recovery Timeout: 120
                Target Reset Timeout: 30
                LUN Reset Timeout: 30
                Abort Timeout: 15
                *****
                CHAP:
                *****
                username: <empty>
                password: ********
                username_in: <empty>
                password_in: ********
                ************************
                Negotiated iSCSI params:
                ************************
                HeaderDigest: None
                DataDigest: None
                MaxRecvDataSegmentLength: 262144
                MaxXmitDataSegmentLength: 262144
                FirstBurstLength: 65536
                MaxBurstLength: 262144
                ImmediateData: Yes
                InitialR2T: Yes
                MaxOutstandingR2T: 1
                ************************
                Attached SCSI devices:
                ************************
                Host Number: 8  State: running
                scsi8 Channel 00 Id 0 Lun: 0
                        Attached scsi disk sdh          State: running
$ lsmod | grep iscsi | grep -v target
iscsi_tcp              18333  1 
libiscsi_tcp           25146  1 iscsi_tcp
libiscsi               57233  2 libiscsi_tcp,iscsi_tcp
scsi_transport_iscsi    99909  3 iscsi_tcp,libiscsi
$ ll /sys/block/sdh
lrwxrwxrwx. 1 root root 0 Oct 28 15:59 /sys/block/sdh -> ../devices/platform/host8/session2/target8:0:0/8:0:0:0/block/sdh
$ cd /sys/devices/platform/host8
$ ls
iscsi_host  power  scsi_host  session2  subsystem  uevent

增加 LUN 并 rescan

$ fallocate -l $((1024*1024*1024)) dat2
$ sudo targetcli
/> cd backstores/fileio/
/backstores/fileio> create file_or_dev=dat2 name=xxx2
Created fileio xxx2 with size 1073741824
/backstores/fileio> cd /iscsi/iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1/tpg1/luns/
/iscsi/iqn.20...cd1/tpg1/luns> create /backstores/fileio/xxx2
Created LUN 1.
Created LUN 1->1 mapping in node ACL iqn.1994-05.com.redhat:6eff34aa8f8
/iscsi/iqn.20...cd1/tpg1/luns> ls /
o- / ......................................................................................................................... [...]
  o- backstores .............................................................................................................. [...]
  | o- block .................................................................................................. [Storage Objects: 0]
  | o- fileio ................................................................................................. [Storage Objects: 2]
  | | o- xxx ................................................................................... [dat (1.0GiB) write-back activated]
  | | | o- alua ................................................................................................... [ALUA Groups: 1]
  | | |   o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
  | | o- xxx2 ................................................................................. [dat2 (1.0GiB) write-back activated]
  | |   o- alua ................................................................................................... [ALUA Groups: 1]
  | |     o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
  | o- pscsi .................................................................................................. [Storage Objects: 0]
  | o- ramdisk ................................................................................................ [Storage Objects: 0]
  o- iscsi ............................................................................................................ [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 .......................................................... [TPGs: 1]
  |   o- tpg1 ............................................................................................... [no-gen-acls, no-auth]
  |     o- acls .......................................................................................................... [ACLs: 1]
  |     | o- iqn.1994-05.com.redhat:6eff34aa8f8 ................................................................... [Mapped LUNs: 2]
  |     |   o- mapped_lun0 .................................................................................. [lun0 fileio/xxx (rw)]
  |     |   o- mapped_lun1 ................................................................................. [lun1 fileio/xxx2 (rw)]
  |     o- luns .......................................................................................................... [LUNs: 2]
  |     | o- lun0 ............................................................................ [fileio/xxx (dat) (default_tg_pt_gp)]
  |     | o- lun1 .......................................................................... [fileio/xxx2 (dat2) (default_tg_pt_gp)]
  |     o- portals .................................................................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 ..................................................................................................... [OK]
  o- loopback ......................................................................................................... [Targets: 0]
  o- qla2xxx .......................................................................................................... [Targets: 0]
/iscsi/iqn.20...cd1/tpg1/luns> cd /
/> saveconfig 
Configuration saved to /etc/target/saveconfig.json
/> exit 
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/target/backup/.
Configuration saved to /etc/target/saveconfig.json
$ sudo iscsiadm -m session -R
Rescanning session [sid: 2, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260]
$ sudo iscsiadm -m session -P 3
iSCSI Transport Class version 2.0-870
version 6.2.0.874-7
Target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 (non-flash)
        Current Portal: 192.168.5.3:3260,1
        Persistent Portal: 192.168.5.3:3260,1
                **********
                Interface:
                **********
                Iface Name: default
                Iface Transport: tcp
                Iface Initiatorname: iqn.1994-05.com.redhat:6eff34aa8f8
                Iface IPaddress: 192.168.5.2
                Iface HWaddress: <empty>
                Iface Netdev: <empty>
                SID: 2
                iSCSI Connection State: LOGGED IN
                iSCSI Session State: LOGGED_IN
                Internal iscsid Session State: NO CHANGE
                *********
                Timeouts:
                *********
                Recovery Timeout: 120
                Target Reset Timeout: 30
                LUN Reset Timeout: 30
                Abort Timeout: 15
                *****
                CHAP:
                *****
                username: <empty>
                password: ********
                username_in: <empty>
                password_in: ********
                ************************
                Negotiated iSCSI params:
                ************************
                HeaderDigest: None
                DataDigest: None
                MaxRecvDataSegmentLength: 262144
                MaxXmitDataSegmentLength: 262144
                FirstBurstLength: 65536
                MaxBurstLength: 262144
                ImmediateData: Yes
                InitialR2T: Yes
                MaxOutstandingR2T: 1
                ************************
                Attached SCSI devices:
                ************************
                Host Number: 8  State: running
                scsi8 Channel 00 Id 0 Lun: 0
                        Attached scsi disk sdh          State: running
                scsi8 Channel 00 Id 0 Lun: 1
                        Attached scsi disk sdi          State: running
$ ll /sys/block/sdh
lrwxrwxrwx. 1 root root 0 Oct 28 15:59 /sys/block/sdh -> ../devices/platform/host8/session2/target8:0:0/8:0:0:0/block/sdh
$ ll /sys/block/sdi
lrwxrwxrwx. 1 root root 0 Oct 28 16:32 /sys/block/sdi -> ../devices/platform/host8/session2/target8:0:0/8:0:0:1/block/sdi

增加 LUN 并手工 scan

$ sudo iscsiadm -m node -u
Logging out of session [sid: 2, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260]
Logout of [sid: 2, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260] successful.
$ sudo iscsiadm -m node -l
Logging in to [iface: default, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260] (multiple)
Login to [iface: default, target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1, portal: 192.168.5.3,3260] successful.
$ sudo iscsiadm -m session -P 3
iSCSI Transport Class version 2.0-870
version 6.2.0.874-7
Target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 (non-flash)
        Current Portal: 192.168.5.3:3260,1
        Persistent Portal: 192.168.5.3:3260,1
                **********
                Interface:
                **********
                Iface Name: default
                Iface Transport: tcp
                Iface Initiatorname: iqn.1994-05.com.redhat:6eff34aa8f8
                Iface IPaddress: 192.168.5.2
                Iface HWaddress: <empty>
                Iface Netdev: <empty>
                SID: 3
                iSCSI Connection State: LOGGED IN
                iSCSI Session State: LOGGED_IN
                Internal iscsid Session State: NO CHANGE
                *********
                Timeouts:
                *********
                Recovery Timeout: 120
                Target Reset Timeout: 30
                LUN Reset Timeout: 30
                Abort Timeout: 15
                *****
                CHAP:
                *****
                username: <empty>
                password: ********
                username_in: <empty>
                password_in: ********
                ************************
                Negotiated iSCSI params:
                ************************
                HeaderDigest: None
                DataDigest: None
                MaxRecvDataSegmentLength: 262144
                MaxXmitDataSegmentLength: 262144
                FirstBurstLength: 65536
                MaxBurstLength: 262144
                ImmediateData: Yes
                InitialR2T: Yes
                MaxOutstandingR2T: 1
                ************************
                Attached SCSI devices:
                ************************
                Host Number: 9  State: running
                scsi9 Channel 00 Id 0 Lun: 0
                        Attached scsi disk sdh          State: running
                scsi9 Channel 00 Id 0 Lun: 1
                        Attached scsi disk sdi          State: running
$ ll /sys/block/sdh
lrwxrwxrwx. 1 root root 0 Oct 28 16:35 /sys/block/sdh -> ../devices/platform/host9/session3/target9:0:0/9:0:0:0/block/sdh
$ ll /sys/block/sdi
lrwxrwxrwx. 1 root root 0 Oct 28 16:36 /sys/block/sdi -> ../devices/platform/host9/session3/target9:0:0/9:0:0:1/block/sdi
$ cd /sys/devices/platform/host9/scsi_host/host9/
$ sudo su
// channel id / target id / lun, scsi_sysfs.c/scsi_scan -> scsi_transport_iscsi.c/iscsi_user_scan
# echo '0 0 2' > scan
# iscsiadm -m session -P 3
iSCSI Transport Class version 2.0-870
version 6.2.0.874-7
Target: iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1 (non-flash)
        Current Portal: 192.168.5.3:3260,1
        Persistent Portal: 192.168.5.3:3260,1
                **********
                Interface:
                **********
                Iface Name: default
                Iface Transport: tcp
                Iface Initiatorname: iqn.1994-05.com.redhat:6eff34aa8f8
                Iface IPaddress: 192.168.5.2
                Iface HWaddress: <empty>
                Iface Netdev: <empty>
                SID: 3
                iSCSI Connection State: LOGGED IN
                iSCSI Session State: LOGGED_IN
                Internal iscsid Session State: NO CHANGE
                *********
                Timeouts:
                *********
                Recovery Timeout: 120
                Target Reset Timeout: 30
                LUN Reset Timeout: 30
                Abort Timeout: 15
                *****
                CHAP:
                *****
                username: <empty>
                password: ********
                username_in: <empty>
                password_in: ********
                ************************
                Negotiated iSCSI params:
                ************************
                HeaderDigest: None
                DataDigest: None
                MaxRecvDataSegmentLength: 262144
                MaxXmitDataSegmentLength: 262144
                FirstBurstLength: 65536
                MaxBurstLength: 262144
                ImmediateData: Yes
                InitialR2T: Yes
                MaxOutstandingR2T: 1
                ************************
                Attached SCSI devices:
                ************************
                Host Number: 9  State: running
                scsi9 Channel 00 Id 0 Lun: 0
                        Attached scsi disk sdh          State: running
                scsi9 Channel 00 Id 0 Lun: 1
                        Attached scsi disk sdi          State: running
                scsi9 Channel 00 Id 0 Lun: 2
                        Attached scsi disk sdj          State: running
$ tree /var/lib/iscsi/
/var/lib/iscsi/
├── ifaces
├── isns
├── nodes
│   ├── iqn.2003-01.org.linux-iscsi.ceph11.x8664:sn.43626b03664a
│   │   └── 192.168.5.2,3260,1
│   │       └── default
│   └── iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1
│       └── 192.168.5.3,3260,1
│           └── default
├── send_targets
│   ├── 192.168.5.2,3260
│   │   ├── iqn.2003-01.org.linux-iscsi.ceph11.x8664:sn.43626b03664a,192.168.5.2,3260,1,default -> /var/lib/iscsi/nodes/iqn.2003-01.org.linux-iscsi.ceph11.x8664:sn.43626b03664a/192.168.5.2,3260,1
│   │   └── st_config
│   └── 192.168.5.3,3260
│       ├── iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1,192.168.5.3,3260,1,default -> /var/lib/iscsi/nodes/iqn.2003-01.org.linux-iscsi.hust17.x8664:sn.6760795b3cd1/192.168.5.3,3260,1
│       └── st_config
├── slp
└── static

sysfs & procfs

$ ls /sys/class/ | grep ^iscsi
iscsi_connection
iscsi_endpoint
iscsi_host
iscsi_iface
iscsi_session
iscsi_transport
$ cat /proc/scsi/scsi
...
Host: scsi9 Channel: 00 Id: 00 Lun: 00
  Vendor: LIO-ORG  Model: xxx              Rev: 4.0 
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi9 Channel: 00 Id: 00 Lun: 01
  Vendor: LIO-ORG  Model: xxx2             Rev: 4.0 
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi9 Channel: 00 Id: 00 Lun: 02
  Vendor: LIO-ORG  Model: xxx3             Rev: 4.0 
  Type:   Direct-Access                    ANSI  SCSI revision: 05
$ ls /sys/class/ | grep ^scsi
scsi_device
scsi_disk
scsi_generic
scsi_host

initiator (kernel) 代码实现

scsi_transport_iscsi
iscsi_tcp
libiscsi
libiscsi_tcp

scsi_transport_iscsi.c
  iscsi_transport_init
    struct netlink_kernel_cfg cfg = {
      .groups = 1,
      .input  = iscsi_if_rx,
    };
    netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg)

  iscsi_if_rx
    iscsi_if_recv_msg(skb)
      struct iscsi_internal *priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle))
      transport = priv->iscsi_transport // iscsi_transport
      switch (nlh->nlmsg_type) {
        case ISCSI_UEVENT_CREATE_SESSION:
          iscsi_if_create_session(priv)
            session = transport->create_session
        case ISCSI_UEVENT_CREATE_CONN:
          iscsi_if_create_conn(transport)
            session = iscsi_session_lookup(ev->u.c_conn.sid)
            conn = transport->create_conn(session, ev->u.c_conn.cid)
        case ISCSI_UEVENT_BIND_CONN:
          session = iscsi_session_lookup(ev->u.b_conn.sid)
          conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid)
          transport->bind_conn(session, conn)

  iscsi_register_transport(struct iscsi_transport *tt)
    struct iscsi_internal *priv = kzalloc(sizeof(*priv), GFP_KERNEL)
    priv->iscsi_transport = tt // iscsi_transport, &iscsi_sw_tcp_transport
    priv->t.user_scan = iscsi_user_scan // /sys/devices/platform/hostX/scsi_host/hostX/scan
    priv->dev.class = &iscsi_transport_class // /sys/class/iscsi_transport
    dev_set_name(&priv->dev, "%s", tt->name)
    device_register(&priv->dev) // /sys/class/iscsi_transport/tcp
    transport_container_register(&priv->t.host_attrs) // /sys/class/iscsi_host
    transport_container_register(&priv->conn_cont) // /sys/class/iscsi_connection
    transport_container_register(&priv->session_cont) // /sys/class/iscsi_session

  iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *iscsit, int dd_size)
    session = kzalloc(sizeof(*session) + dd_size, GFP_KERNEL)
    session->transport = iscsit // iscsi_transport
    device_initialize(&session->dev)

  iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
    session->sid = atomic_add_return(1, &iscsi_session_nr)
    dev_set_name(&session->dev, "session%u", session->sid);
    device_add(&session->dev)

  iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
    iscsi_transport *transport = session->transport
    iscsi_cls_conn *conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL)
    conn->transport = transport;
    conn->cid = cid;
    dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid)
    device_register(&conn->dev)
      device_initialize(dev)
      device_add(dev)
    transport_register_device(&conn->dev)

hosts.c
  scsi_host_alloc(struct scsi_host_template *sht, int privsize)
    shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask)
    shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1
    shost->hostt = sht
    device_initialize(&shost->shost_gendev)
    dev_set_name(&shost->shost_gendev, "host%d", shost->host_no)
    device_initialize(&shost->shost_dev)
    dev_set_name(&shost->shost_dev, "host%d", shost->host_no)
    shost->ehandler = kthread_run(scsi_error_handler, shost)
    scsi_proc_hostdir_add(shost->hostt)

iscsi_tcp.c
  iscsi_sw_tcp_init
    iscsi_sw_tcp_scsi_transport = iscsi_register_transport(iscsi_sw_tcp_transport)

  iscsi_sw_tcp_session_create
    shost = iscsi_host_alloc(&iscsi_sw_tcp_sht)
    shost->transportt = iscsi_sw_tcp_scsi_transport // scsi_transport_template
    iscsi_host_add(shost, NULL)
    iscsi_session_setup(&iscsi_sw_tcp_transport, shost)

  iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
    struct iscsi_cls_conn *cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*tcp_sw_conn), conn_idx)

  static struct scsi_host_template iscsi_sw_tcp_sht = {
    .module     = THIS_MODULE,
    .name     = "iSCSI Initiator over TCP/IP",
    .queuecommand           = iscsi_queuecommand,
    .change_queue_depth = iscsi_change_queue_depth,
    .can_queue    = ISCSI_DEF_XMIT_CMDS_MAX - 1,
    .sg_tablesize   = 4096,
    .max_sectors    = 0xFFFF,
    .cmd_per_lun    = ISCSI_DEF_CMD_PER_LUN,
    .eh_abort_handler       = iscsi_eh_abort,
    .eh_device_reset_handler= iscsi_eh_device_reset,
    .eh_target_reset_handler = iscsi_eh_recover_target,
    .use_clustering         = DISABLE_CLUSTERING,
    .slave_alloc            = iscsi_sw_tcp_slave_alloc,
    .slave_configure        = iscsi_sw_tcp_slave_configure,
    .target_alloc   = iscsi_target_alloc,
    .proc_name    = "iscsi_tcp",
    .this_id    = -1,
  };

  static struct iscsi_transport iscsi_sw_tcp_transport = {
    .owner    = THIS_MODULE,
    .name     = "tcp",
    .caps     = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST,
    /* session management */
    .create_session   = iscsi_sw_tcp_session_create,
    .destroy_session  = iscsi_sw_tcp_session_destroy,
    /* connection management */
    .create_conn    = iscsi_sw_tcp_conn_create,
    .bind_conn    = iscsi_sw_tcp_conn_bind,
    .destroy_conn   = iscsi_sw_tcp_conn_destroy,
    .attr_is_visible  = iscsi_sw_tcp_attr_is_visible,
    .set_param    = iscsi_sw_tcp_conn_set_param,
    .get_conn_param   = iscsi_sw_tcp_conn_get_param,
    .get_session_param  = iscsi_session_get_param,
    .start_conn   = iscsi_conn_start,
    .stop_conn    = iscsi_sw_tcp_conn_stop,
    /* iscsi host params */
    .get_host_param   = iscsi_sw_tcp_host_get_param,
    .set_host_param   = iscsi_host_set_param,
    /* IO */
    .send_pdu   = iscsi_conn_send_pdu,
    .get_stats    = iscsi_sw_tcp_conn_get_stats,
    /* iscsi task/cmd helpers */
    .init_task    = iscsi_tcp_task_init,
    .xmit_task    = iscsi_tcp_task_xmit,
    .cleanup_task   = iscsi_tcp_cleanup_task,
    /* low level pdu helpers */
    .xmit_pdu   = iscsi_sw_tcp_pdu_xmit,
    .init_pdu   = iscsi_sw_tcp_pdu_init,
    .alloc_pdu    = iscsi_sw_tcp_pdu_alloc,
    /* recovery */
    .session_recovery_timedout = iscsi_session_recovery_timedout,
  };

libiscsi.c
  iscsi_host_alloc(struct scsi_host_template *sht)
    shost = scsi_host_alloc(sht)

  iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
    scsi_add_host(shost, pdev)
      scsi_add_host_with_dma(host, dev, dev)
        device_add(&shost->shost_gendev)
        device_add(&shost->shost_dev)
        scsi_sysfs_add_host(shost)
        scsi_proc_host_add(shost)

  iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost)
    cls_session = iscsi_alloc_session(shost, iscsit)
    iscsi_add_session(cls_session, 0)

  iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, uint32_t conn_idx)
    iscsi_session *session = cls_session->dd_data
    cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size, conn_idx)
    conn = cls_conn->dd_data;
    conn->session = session;
    conn->cls_conn = cls_conn;

libiscsi_tcp.c
  iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size, uint32_t conn_idx)
    cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn) + dd_data_size, conn_idx)

参考资料

targetcli - administration shell for storage targets

http://manpages.ubuntu.com/manpages/bionic/man8/targetcli.8.html