├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── conf
├── Makefile
├── examples
│ ├── targets.conf.example
│ ├── targets.conf.vtl.L700
│ └── targets.conf.vtl.MSL2024
└── targets.conf
├── doc
├── Makefile
├── README.curve
├── README.dvdjukebox
├── README.glfs
├── README.iscsi
├── README.iser
├── README.lu_configuration
├── README.mmc
├── README.passthrough
├── README.rbd
├── README.sbcjukebox
├── README.sheepdog
├── README.ssc
├── README.vtl
├── targets.conf.5.xml
├── tgt-admin.8.xml
├── tgt-setup-lun.8.xml
├── tgtadm.8.xml
├── tgtd.8.xml
├── tgtimg.8.xml
└── tmf.txt
├── images
├── fio_old.png
└── fio_opt.png
├── scripts
├── Makefile
├── build-pkg.sh
├── checkarch.sh
├── checkpatch.pl
├── deb
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── init
│ ├── patches
│ │ └── 0001-Use-local-docbook-for-generating-docs.patch
│ ├── rules
│ ├── source
│ │ └── format
│ ├── tgt.bash-completion
│ └── tgt.service
├── initd.sample
├── tgt-admin
├── tgt-core-test
├── tgt-setup-lun
├── tgt.bashcomp.sh
├── tgt.service
├── tgtd.service
└── tgtd.spec
└── usr
├── Makefile
├── be_byteshift.h
├── bs.c
├── bs_aio.c
├── bs_aio.h
├── bs_curve.cc
├── bs_glfs.c
├── bs_null.c
├── bs_rbd.c
├── bs_rdwr.c
├── bs_sg.c
├── bs_sheepdog.c
├── bs_ssc.c
├── bs_ssc.h
├── bs_thread.h
├── bsg.h
├── concat_buf.c
├── crc32c.h
├── driver.c
├── driver.h
├── iscsi
├── chap.c
├── conn.c
├── iscsi_if.h
├── iscsi_proto.h
├── iscsi_tcp.c
├── iscsid.c
├── iscsid.h
├── iser.c
├── iser.h
├── iser_text.c
├── isns.c
├── isns_proto.h
├── md5.c
├── md5.h
├── param.c
├── param.h
├── session.c
├── sha1.c
├── sha1.h
├── target.c
├── transport.c
└── transport.h
├── lib
└── tree.h
├── libcrc32c.c
├── libssc.c
├── libssc.h
├── list.h
├── log.c
├── log.h
├── media.h
├── mgmt.c
├── mmc.c
├── mutex.c
├── mutex.h
├── osd.c
├── parser.c
├── parser.h
├── sbc.c
├── scc.c
├── scsi.c
├── scsi.h
├── scsi_cmnd.h
├── smc.c
├── smc.h
├── spc.c
├── spc.h
├── ssc.c
├── ssc.h
├── target.c
├── target.h
├── tgtadm.c
├── tgtadm.h
├── tgtadm_error.h
├── tgtd.c
├── tgtd.h
├── tgtimg.c
├── util.c
├── util.h
├── work.c
└── work.h
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on: [pull_request]
4 |
5 | jobs:
6 | build:
7 | name: build
8 | runs-on: ubuntu-22.04
9 | steps:
10 | - name: checking out
11 | uses: actions/checkout@v3
12 | with:
13 | path: tgt
14 | - name: build
15 | working-directory: tgt
16 | run: |
17 | make
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 | # Normal rules
3 | #
4 | .*
5 | *.o
6 | *.o.*
7 | *.a
8 | *.s
9 | *.ko
10 | *.so
11 | *.mod.c
12 | *.i
13 | *.lst
14 | *.symtypes
15 | *.d
16 | *.orig
17 | *.rej
18 |
19 | #
20 | # for GLOBAL
21 | #
22 | GTAGS
23 | GRTAGS
24 | GPATH
25 | GSYMS
26 |
27 | #
28 | # programs
29 | #
30 | usr/tgtd
31 | usr/tgtadm
32 | usr/tgtimg
33 |
34 | # cscope files
35 | cscope.*
36 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | VERSION ?= 1.0.86
2 |
3 | CHECK_CC = cgcc
4 | CHECK_CC_FLAGS = '$(CHECK_CC) -Wbitwise -Wno-return-void -no-compile $(ARCH)'
5 |
6 | # Define a common prefix where binaries and docs install
7 | PREFIX ?= /usr
8 |
9 | # Export VERSION and PREFIX so sub-make knows about them
10 | export VERSION PREFIX
11 |
12 | # Export the feature switches so sub-make knows about them
13 | export CURVE_CBD=1
14 | #export ISCSI_RDMA
15 | #export CEPH_RBD
16 | #export GLFS_BD
17 | #export SD_NOTIFY
18 |
19 | .PHONY: all
20 | all: programs doc conf scripts
21 |
22 | # Targets for the /usr/sbin utilities
23 | .PHONY: programs install-programs clean-programs
24 | programs:
25 | $(MAKE) -C usr
26 |
27 | install-programs:
28 | $(MAKE) -C usr install
29 |
30 | clean-programs:
31 | $(MAKE) -C usr clean
32 |
33 | # Targets for man pages and other documentation
34 | .PHONY: doc install-doc clean-doc
35 | doc:
36 | $(MAKE) -C doc
37 |
38 | install-doc:
39 | $(MAKE) -C doc install
40 |
41 | clean-doc:
42 | $(MAKE) -C doc clean
43 |
44 | # Targets for scripts
45 | .PHONY: scripts install-scripts clean-scripts
46 | scripts:
47 | $(MAKE) -C scripts
48 |
49 | install-scripts:
50 | $(MAKE) -C scripts install
51 |
52 | clean-scripts:
53 | $(MAKE) -C scripts clean
54 |
55 |
56 | # Targets for configuration stubs
57 | .PHONY: conf install-conf clean-conf
58 | conf:
59 | $(MAKE) -C conf
60 |
61 | install-conf:
62 | $(MAKE) -C conf install
63 |
64 | clean-conf:
65 | $(MAKE) -C conf clean
66 |
67 | .PHONY: install
68 | install: install-programs install-doc install-conf install-scripts
69 |
70 | .PHONY: rpm
71 | rpm:
72 | @./scripts/build-pkg.sh rpm
73 |
74 | .PHONY: deb
75 | deb:
76 | @./scripts/build-pkg.sh deb
77 |
78 | .PHONY: clean
79 | clean-pkg:
80 | rm -fr pkg
81 |
82 | .PHONY: clean
83 | clean: clean-programs clean-doc clean-conf clean-scripts clean-pkg
84 |
85 | .PHONY:check
86 | check: ARCH=$(shell sh scripts/checkarch.sh)
87 | check:
88 | CC=$(CHECK_CC_FLAGS) $(MAKE) all
89 |
90 | .PHONY:check32
91 | check32: override ARCH=-m32
92 | check32:
93 | CC=$(CHECK_CC_FLAGS) $(MAKE) all
94 |
95 | .PHONY:check64
96 | check64: override ARCH=-m64
97 | check64:
98 | CC=$(CHECK_CC_FLAGS) $(MAKE) all
99 |
100 | cscope:
101 | find -name '*.[ch]' > cscope.files
102 | cscope -bq
103 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 网易高性能版本tgt
3 | ================
4 | ## 1. tgt是什么
5 |
6 | tgt是一个开源iscsi服务器,详情请见 https://github.com/fujita/tgt。我们在开发Curve块设备服务器时,想让更多的系统能够使用Curve块设备,而不仅仅是Linux系统,iscsi协议是一个广泛使用的块设备协议,我们想修改tgt以便让Curve提供scsi服务。
7 |
8 | ## 2. 使用tgt中碰到的问题
9 |
10 | 我们观察到原版tgt使用单一主线程epoll来处理iscsi命令,还包括管理平面的unix domian socket也在这个主线程里。在10 Gbit/s网络上甚至更快的网络上,单线程(也即单cpu)处理iscsi命令的速度已经跟不上需要了,一个线程对付多个target的情况下,多个ISCSI Initiator的请求速度稍微高一点,这个单线程的cpu使用率就100%忙碌。
11 |
12 | ## 3. 修改策略
13 |
14 | ### 3.1 使用多个线程做epoll
15 |
16 | 实现多个event loop线程,每个线程负责一定数量的socket connection上的iscsi命令处理。 这样就能发挥多cpu的处理能力。
17 |
18 | ### 3.2 为每个target创建一个epoll线程
19 |
20 | 为了避免多个target共享一个epoll时依然可能出现超过单个cpu处理能力的问题,当前我们的解决方法是为每一个target设置了一个epoll线程。target epoll的cpu使用由OS负责调度,这样在各target上可以实现公平的cpu使用。
21 |
22 | ### 3.3 管理平面
23 |
24 | 管理平面保持了与原始tgt的兼容性。从命令行使用方面来说,没有任何区别,没有任何修改。管理平面在程序的主线程上提供服务,主线程也是一个epoll loop线程,这与原始的tgt没有区别,它负责target, lun, login/logout,discover,session, connection等的管理。当Intiator连接到ISCSI服务器时,总是先被管理平面线程所服务,如果该connection最后需要创建session去访问某个target,那么该connection会被迁移到对应的target的epoll线程上去。
25 |
26 | ### 3.4 数据结构的锁
27 |
28 | 为每一个target提供一个mutex,当target epoll线程在运行时,这把锁是被该线程锁住的,这样该线程可以任意结束一个sesssion或connection,当线程进入epoll_wait时,这把锁是释放了的,epoll_wait返回时又会锁住这把锁。我们修改了相关代码,让这个epoll线程不用遍历target list,只存取它服务的target相关结构,这样我们不需要target列表锁。管理面也会增加、删除一个session或者connection时,也需要锁住这把target锁。所以管理面和target epoll线程使用这个mutex来互斥,这样就可以安全地访问对应target上的session和connection了。
29 |
30 | ### 3.5 connection建立session
31 |
32 | 当login_finish成功时,login_finish有时候会创建session(如果没有session存在)。login_finish在connection结构的字段migrate_to里设置目标iscsi target。
33 |
34 | ### 3.6. connection加入到session
35 |
36 | 通常一个新的连接产生一个新的session,就如上面讲的login_finish一样。但是有一种情况,iscsi允许一个session里有多个连接,这样connection直接加入到这个session里,这是由login_security_done做的。
37 |
38 | ### 3.7 什么时候做connection迁移
39 |
40 | 当调用返回到iscsi_tcp_event_handler时,因为login_finish设置了migrate_to目标target, iscsi_tcp_event_handler就锁住目标iscsi target结构,并把该connection的fd插入到目标target的evloop 里面,完成迁移。
41 |
42 | ### 3.8 设置pthread name
43 |
44 | 设置各target event loop的线程在top中的名为tgt/n, n为target id,这样容易用top之类的工具观察哪一个target占用的cpu高。
45 |
46 | ### 3.9 一个实现例子
47 |
48 | 假如MGMT要删除一个target,下面的代码说明了流程:
49 |
50 | ```
51 | /* called by mgmt */
52 | tgtadm_err tgt_target_destroy(int lld_no, int tid, int force)
53 | {
54 | struct target *target;
55 | struct acl_entry *acl, *tmp;
56 | struct iqn_acl_entry *iqn_acl, *tmp1;
57 | struct scsi_lu *lu;
58 | tgtadm_err adm_err;
59 |
60 | eprintf("target destroy\n");
61 |
62 | /*
63 | * 这里因为控制面是单线程的,而且SCSI IO线程不会删除target,
64 | * 所以我们找target的时候并不需要锁
65 | */
66 |
67 | target = target_lookup(tid);
68 | if (!target)
69 | return TGTADM_NO_TARGET;
70 |
71 | /*
72 | * 这里要锁住target,因为我们要删除数据结构,所以不能和iscsi io
73 | * 线程一起共享,必须在scsi 线程释放了锁时进行
74 | */
75 |
76 | target_lock(target);
77 | if (!force && !list_empty(&target->it_nexus_list)) {
78 | eprintf("target %d still has it nexus\n", tid);
79 | target_unlock(target);
80 | return TGTADM_TARGET_ACTIVE;
81 | }
82 | …
83 | /* 以上步骤删除了所有资源 ,可以释放锁了 */
84 | target_unlock(target);
85 | if (target->evloop != main_evloop) {
86 | /* 通知target上的evloop停止,并等待evloop 线程退出 */
87 | tgt_event_stop(target->evloop);
88 | if (target->ev_td != 0)
89 | pthread_join(target->ev_td, NULL);
90 | /* 下面把evloop的资源删除干净 */
91 | work_timer_stop(target->evloop);
92 | lld_fini_evloop(target->evloop);
93 | tgt_destroy_evloop(target->evloop);
94 | }
95 | ```
96 |
97 | ## 4. tgt与curve
98 |
99 | 为tgt提供了访问curve的驱动,详见doc/README.curve, 这样用户就可以在任何支持iscsi的操作系统上使用curve块设备存储,例如Windows。
100 |
101 | ## 5. 关于iser
102 |
103 | iser target服务目前依然归属于主线程服务,因为我们还不具备测试RDMA的条件,所以这部分代码 还没有修改。
104 |
105 | ## 6. 性能对比
106 |
107 | 我们为tgt配置了3块盘,一块curvebs卷,两块本地盘,配置文件:
108 | /etc/tgt/targets.conf
109 |
110 | ```
111 |
112 |
113 | backing-store cbd:pool//iscsi_test_
114 | bs-type curve
115 |
116 |
117 |
118 | backing-store /dev/sde
119 |
120 |
121 |
122 | backing-store /dev/sdc
123 |
124 | ```
125 |
126 | 使用本机登录iscsi
127 | iscsiadm --mode node --portal 127.0.0.1:3260 --login
128 |
129 | 为fio设置存取这些iscsi的块设备,使用
130 |
131 |
132 | ```
133 | [global]
134 | rw=randread
135 | direct=1
136 | iodepth=128
137 | ioengine=aio
138 | bsrange=16k-16k
139 | runtime=60
140 | group_reporting
141 |
142 | [disk01]
143 | filename=/dev/sdx
144 |
145 | [disk02]
146 | filename=/dev/sdy
147 | size=10G
148 |
149 | [disk03]
150 | filename=/dev/sdz
151 | size=10G
152 | ```
153 |
154 | 测试成绩如下:
155 |
156 | 下面是未经优化的fio成绩,IOPS 38.8K
157 | 
158 |
159 | 下面是经过多线程优化的fio成绩,IOPS 60.9K
160 | 
161 |
162 | ## 8. Windows测试
163 |
164 | 本系统对Windows经过初步测试,工作良好。具体怎么在Windows上配置iscsi客户端,可以参照:https://jingyan.baidu.com/article/e4511cf37feade2b845eaff8.html
165 |
166 | ## 9. CHAP
167 |
168 | 在Windows上设置CHAP认证时,请注意机密必须包含12到16个字符,要在tgt和Windows上保持一致。
169 |
--------------------------------------------------------------------------------
/conf/Makefile:
--------------------------------------------------------------------------------
1 | sysconfdir ?= /etc
2 |
3 | EXAMPLES = targets.conf.example targets.conf.vtl.L700 targets.conf.vtl.MSL2024
4 |
5 | .PHONY: all
6 | all:
7 |
8 | .PHONY: install
9 | install:
10 | install -d -m 755 $(DESTDIR)$(sysconfdir)/tgt
11 | if [ ! -f $(DESTDIR)$(sysconfdir)/tgt/targets.conf ] ; then \
12 | install -m 644 targets.conf $(DESTDIR)$(sysconfdir)/tgt ; \
13 | fi
14 | install -d -m 755 $(DESTDIR)$(sysconfdir)/tgt/examples
15 | for f in $(EXAMPLES) ; do \
16 | install -m 644 examples/$$f $(DESTDIR)$(sysconfdir)/tgt/examples ;\
17 | done
18 | install -d $(DESTDIR)$(sysconfdir)/tgt/conf.d
19 |
20 | .PHONY: clean
21 | clean:
22 |
23 |
--------------------------------------------------------------------------------
/conf/examples/targets.conf.vtl.L700:
--------------------------------------------------------------------------------
1 | # Virtual tape library example for a STK L700 tape library
2 | #
3 | # In this case, tapes are stored in the directory /root/tapes
4 | # size is in MB (1 GB in this case)
5 | # using the command "tgtimg --op=new --device-type=tape --barcode="A00000001" --size=10240 --type=data --file=A00000001"
6 | #
7 | # The tapes can be added after startup with
8 | # "tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 4 --params element_type=2,address=1000,barcode=A0000001,sides=1"
9 | # for slot 0 (is nr 1000)
10 | #
11 |
12 | include /etc/tgt/temp/*.conf
13 |
14 | default-driver iscsi
15 |
16 |
17 | allow-in-use yes
18 | #
19 | # For every drive We need a backing store, although the tape drive will be empty,
20 | # so we create a dummy tape "notape" in directory /root/tapes
21 | # with the command "tgtimg --op=new --device-type=tape --barcode="" --size=1 --type=clean --file=notape"
22 | # and create symbolic links for every drive (limitation of tgt)
23 | # link -s /root/tapes/notape /root/tapes/notape1
24 | # link -s /root/tapes/notape /root/tapes/notape2
25 | # link -s /root/tapes/notape /root/tapes/notape2
26 | #
27 |
28 | lun 1
29 | device-type tape
30 | removable 1
31 | vendor_id "HP"
32 | product_id "LTO3 ULTRIUM"
33 | product_rev "0001"
34 | scsi_sn "HUM1A00001"
35 | scsi_id "HP LTO3 ULTRIUM"
36 |
37 |
38 | lun 2
39 | device-type tape
40 | removable 1
41 | vendor_id "HP"
42 | product_id "LTO3 ULTRIUM"
43 | product_rev "0001"
44 | scsi_sn "HUM1A00002"
45 | scsi_id "HP LTO3 ULTRIUM"
46 |
47 |
48 | lun 3
49 | device-type tape
50 | removable 1
51 | vendor_id "HP"
52 | product_id "LTO3 ULTRIUM"
53 | product_rev "0001"
54 | scsi_sn "HUM1A00003"
55 | scsi_id "HP LTO3 ULTRIUM"
56 |
57 |
58 | lun 4
59 | device-type changer
60 | removable 1
61 | vendor_id "STK"
62 | product_id "L700"
63 | product_rev "0001"
64 | scsi_sn "123:456:789:000"
65 | # Dummy 'page 0'
66 | mode_page "0:0:0"
67 | # Page 0x02: Disconnect/Reconnect SPC-3
68 | mode_page "0x02:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0"
69 | # Page 0x1a: Power Condition SPC-3
70 | mode_page "0x1a:0:18:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
71 | # Page 0x1c: Informational Exceptions Control SPC-3
72 | mode_page "0x1c:0:10:8:0:0:0:0:0:0:0:0:0"
73 | # Page 0x1d: Element Address Assignment SMC-3 7.3.4
74 | mode_page "0x1d:0:0x12:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
75 | # Page 0x1e: Transport Geometry Parameters SMC-3 7.3.5
76 | mode_page "0x1e:0:2:0:0"
77 | # Page 0x1f: Device Capabilities SMC-3 7.3.2
78 | # Page 0x1f/Subpage 0x41: Extended Device Capabilities SMC-3 7.3.3
79 | mode_page "0x1f:0:0x12:0x0f:7:0x0f:0x0f:0x0f:0x0f:0:0:0:0:0x0f:0x0f:0x0f:0x0f:0:0:0:0"
80 | # Type 1: Medium Transport Elements (robot arm/picker)
81 | params element_type=1,start_address=1,quantity=1,media_home=/root/tapes
82 | # Type 2: Storage Elements (tape slots)
83 | params element_type=2,start_address=1000,quantity=216,media_home=/root/tapes
84 | # Type 3: Import/Export Elements (CAP)
85 | params element_type=3,start_address=10,quantity=20,media_home=/root/tapes
86 | # Type 4: Add Data Transfer devices (drives)
87 | params element_type=4,start_address=500,quantity=3,media_home=/root/tapes
88 | params element_type=4,address=500,tid=1,lun=1
89 | params element_type=4,address=500,tid=1,lun=2
90 | params element_type=4,address=500,tid=1,lun=3
91 |
92 |
93 |
--------------------------------------------------------------------------------
/conf/examples/targets.conf.vtl.MSL2024:
--------------------------------------------------------------------------------
1 | # Virtual tape library example for an HP MSL-2024 tape library
2 | #
3 | # In this case, tapes are stored in the directory /root/tapes
4 | # size is in MB (1 GB in this case)
5 | # using the command "tgtimg --op=new --device-type=tape --barcode="A00000001" --size=10240 --type=data --file=A00000001"
6 | #
7 | # The tapes can be added after startup with
8 | # "tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 4 --params element_type=2,address=1000,barcode=A0000001,sides=1"
9 | # for slot 0 (is nr 1000)
10 | #
11 | # Please note that an MSL-2024 has no IMPORT/EXPORT elements (type 3)
12 |
13 | include /etc/tgt/temp/*.conf
14 |
15 | default-driver iscsi
16 |
17 |
18 | allow-in-use yes
19 | #
20 | # We need a backing store, although the tape drive will be empty,
21 | # so we create a dummy tape "notape" in directory /root/tapes
22 | # with the command "tgtimg --op=new --device-type=tape --barcode="" --size=1 --type=clean --file=notape"
23 | #
24 |
25 | lun 1
26 | device-type tape
27 | removable 1
28 | vendor_id "HP "
29 | product_id "Ultrium 3-SCSI"
30 | product_rev "D21W"
31 | scsi_sn "HU012345AB"
32 | scsi_id "HP LTO3 ULTRIUM"
33 |
34 | #
35 | # For the tape changer we need also a backing store, this can be a file containing zeros, like this:
36 | # "dd if=/dev/zero of=$HOME/smc bs=1k count=1"
37 | #
38 |
39 | lun 4
40 | device-type changer
41 | removable 1
42 | vendor_id "HP "
43 | product_id "MSL G3 Series "
44 | product_rev "3.00"
45 | scsi_sn "ABC01234G3"
46 | # Dummy 'page 0'
47 | mode_page "0:0:0"
48 | # Page 0x02: Disconnect/Reconnect SPC-3
49 | mode_page "0x02:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0"
50 | # Page 0x1a: Power Condition SPC-3
51 | mode_page "0x1a:0:18:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
52 | # Page 0x1c: Informational Exceptions Control SPC-3
53 | mode_page "0x1c:0:10:8:0:0:0:0:0:0:0:0:0"
54 | # Page 0x1d: Element Address Assignment SMC-3 7.3.4
55 | mode_page "0x1d:0:0x12:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
56 | # Page 0x1e: Transport Geometry Parameters SMC-3 7.3.5
57 | mode_page "0x1e:0:2:0:0"
58 | # Page 0x1f: Device Capabilities SMC-3 7.3.2
59 | # Page 0x1f/Subpage 0x41: Extended Device Capabilities SMC-3 7.3.3
60 | mode_page "0x1f:0:0x12:0x0f:7:0x0f:0x0f:0x0f:0x0f:0:0:0:0:0x0f:0x0f:0x0f:0x0f:0:0:0:0"
61 | # Type 1: Medium Transport Elements (robot arm/picker)
62 | params element_type=1,start_address=1,quantity=1,media_home=/root/tapes
63 | # Type 2: Storage Elements (tape slots)
64 | params element_type=2,start_address=1000,quantity=24,media_home=/root/tapes
65 | # Type 4: Add Data Transfer devices (drives)
66 | params element_type=4,start_address=2,quantity=1,media_home=/root/tapes
67 | params element_type=4,address=2,tid=1,lun=1
68 |
69 |
70 |
--------------------------------------------------------------------------------
/conf/targets.conf:
--------------------------------------------------------------------------------
1 | # Empty targets configuration file -- please see the package
2 | # documentation directory for an example.
3 | #
4 | # You can drop individual config snippets into /etc/tgt/conf.d
5 | include /etc/tgt/conf.d/*.conf
6 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | mandir ?= $(PREFIX)/share/man
2 | docdir ?= $(PREFIX)/share/doc/tgt
3 |
4 | MANPAGES = manpages/tgtadm.8 manpages/tgt-admin.8 manpages/tgtimg.8 \
5 | manpages/tgt-setup-lun.8 manpages/tgtd.8 \
6 | manpages/targets.conf.5
7 |
8 | DOCS = README.iscsi README.iser \
9 | README.lu_configuration README.mmc tmf.txt \
10 | README.rbd
11 |
12 | XSLTPROC = /usr/bin/xsltproc
13 | XMLMAN = manpages/tgtd.8 manpages/tgtadm.8 manpages/tgtimg.8 \
14 | manpages/tgt-admin.8 manpages/targets.conf.5 \
15 | manpages/tgt-setup-lun.8
16 | XMLHTML = htmlpages/tgtd.8.html htmlpages/tgtadm.8.html \
17 | htmlpages/tgtimg.8.html htmlpages/tgt-admin.8.html \
18 | htmlpages/targets.conf.5.html htmlpages/tgt-setup-lun.8.html
19 |
20 | .PHONY:all
21 | all: xmlman xmlhtml
22 |
23 | .PHONY: install
24 | install: $(MANPAGES) $(DOCS)
25 | install -d -m 755 $(DESTDIR)$(mandir)/man8 $(DESTDIR)$(mandir)/man5
26 | install -m 644 $(filter %.8,$(MANPAGES)) $(DESTDIR)$(mandir)/man8
27 | install -m 644 $(filter %.5,$(MANPAGES)) $(DESTDIR)$(mandir)/man5
28 | install -d -m 755 $(DESTDIR)$(docdir)
29 | install -m 644 $(DOCS) $(DESTDIR)$(docdir)
30 | install -d -m 755 $(DESTDIR)$(docdir)/html
31 | install -m 644 $(XMLHTML) $(DESTDIR)$(docdir)/html
32 |
33 | .PHONY: clean
34 | clean:
35 | rm -f $(XMLMAN) $(XMLHTML)
36 | -rm -f manpages htmlpages
37 |
38 | manpages/tgtd.8: tgtd.8.xml
39 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
40 |
41 | htmlpages/tgtd.8.html: tgtd.8.xml
42 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
43 |
44 | manpages/tgtadm.8: tgtadm.8.xml
45 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
46 |
47 | htmlpages/tgtadm.8.html: tgtadm.8.xml
48 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
49 |
50 | manpages/tgt-admin.8: tgt-admin.8.xml
51 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
52 |
53 | htmlpages/tgt-admin.8.html: tgt-admin.8.xml
54 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
55 |
56 | manpages/tgtimg.8: tgtimg.8.xml
57 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
58 |
59 | htmlpages/tgtimg.8.html: tgtimg.8.xml
60 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
61 |
62 | manpages/targets.conf.5: targets.conf.5.xml
63 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
64 |
65 | htmlpages/targets.conf.5.html: targets.conf.5.xml
66 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
67 |
68 | manpages/tgt-setup-lun.8: tgt-setup-lun.8.xml
69 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
70 |
71 | htmlpages/tgt-setup-lun.8.html: tgt-setup-lun.8.xml
72 | -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
73 |
74 | xmlman: $(XMLMAN)
75 |
76 | xmlhtml: $(XMLHTML)
77 |
78 |
--------------------------------------------------------------------------------
/doc/README.curve:
--------------------------------------------------------------------------------
1 | Curve is a distributed storage system for QEMU, iSCSI clients.
2 | It provides highly available block level storage volumes that
3 | can be attached to QEMU-based virtual machines. The volumes can
4 | also be attached to other virtual machines and operating
5 | systems run on baremetal hardware if they support iSCSI
6 | protocol. Curve scales to several hundreds nodes, and supports
7 | advanced volume management features such as snapshot, cloning.
8 |
9 | With tgt, Curve volume can be used by iSCSI initiators.
10 | Below is a brief description of setup.
11 |
12 | 1. Install and launch tgt
13 |
14 | $ git clone https://github.com/opencurve/curve-tgt.git
15 | $ cd tgt
16 | $ git checkout master
17 | $ make
18 | # make install
19 |
20 | 2. Setup iSCSI target provided by tgt
21 |
22 | One logical unit corresponds to one Curve volume. In this step, we
23 | create iSCSI target and logical unit which can be seen by iSCSI
24 | initiator.
25 |
26 | # tgtd
27 | # tgtadm --op new --mode target --tid 1 --lld iscsi --targetname iqn.2022-01.org.opencurve_io
28 | # tgtadm --op new --mode lu --tid 1 --lun 2 --bstype curve --backing-store cbd:pool//iscsi_test_
29 | # tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
30 |
31 | The parameter --bstype and --backing-store which are required by tgtadm
32 | when we create the logical unit in the target (the third line
33 | of the above commands). With these parameters, we tell the tgtd
34 | process how to connect to the Curve server, which Curve volume we
35 | use as the logical unit.
36 |
37 | 3. Setup iSCSI session (example of the open-iscsi initiator on Linux)
38 |
39 | After setting up iSCSI target, you can use the Curve volume from any virtual
40 | machines and operating systems which supports iSCSI initiator. Many of
41 | popular hypervisors and operating systems support it (e.g. VMware ESX
42 | Family, Linux, Windows, etc). In this example, the way of Linux +
43 | open-iscsi is described.
44 |
45 | At first, you have to install open-iscsi ( http://www.open-iscsi.org/
46 | ) and launch it. Major linux distros provide their open-iscsi
47 | package. Below is a way of installation in Debian and Ubuntu based
48 | systems.
49 |
50 | # apt-get install open-iscsi
51 | # /etc/init.d/open-iscsi start
52 |
53 | Next, we need to let iscsid discover and login to the target we've
54 | already created in the above sequence. If the initiator is running
55 | on different host from the target, you have to change the IP
56 | addresses in the below commands.
57 |
58 | # iscsiadm -m discovery -t st -p 127.0.0.1
59 | # iscsiadm -m node --portal 127.0.0.1:3260 --login
60 |
61 | New device files, e.g. /dev/sdz, will be created on your system after
62 | login completion. you can check the new devices by 'ls /dev/disk/by-path'.
63 | Now your system can use the Curve volume like ordinal HDDs.
64 |
65 | 4. Update iSCSI disk size
66 |
67 | Assume you have created iscsi target (tid 1) and logical unit (lun 1),
68 | you may want to resize the Curve volume and let iscsi user know the change,
69 | you can use the following steps to do so:
70 |
71 | a) Use `curve extent' command to resize the volume
72 | b) Update tgt by using the following command:
73 | tgtadm --mode logicalunit --op update --tid 1 --lun 1 --params disksize=auto
74 | c) On linux client you execute the following command to refresh device:
75 | iscsiadm --mode node -R
76 | d) On windows client, run 'Computer management', goto 'Storage', right click on
77 | 'Disk management', select 'refresh' on the menu, you will find extent
78 | not used in the disk.
79 |
80 | 5. Tuning open-iscsi
81 |
82 | Tuning open-iscsi is required for heavy disk usage application, edit config
83 | file /etc/iscsi/iscsid.conf, change following options for example:
84 | node.session.cmds_max = 512
85 | node.session.queue_depth = 512
86 | Then restart iscsid and open-iscsi:
87 | # /etc/init.d/iscsid restart
88 | # /etc/init.d/open-iscsi restart
89 | Also, you need to logout and login tgt again:
90 | # iscsiadm -m node --portal 127.0.0.1:3260 --logout
91 | # iscsiadm -m node --portal 127.0.0.1:3260 --login
92 |
93 |
--------------------------------------------------------------------------------
/doc/README.dvdjukebox:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # This is a script to set up a SCSI DVD JUKEBOX for all your ISO images.
4 | #
5 | # This script should be run from a directory that contains ISO images
6 | # with the extension .iso .
7 | # When run, the script will create an iSCSI target containing one DVD drive
8 | # and one media changer. The DVD drive will not have a disk mounted but
9 | # the medium changer will have one slot for each ISO image found.
10 | # Use the 'mtx' tool to load/unload media.
11 | #
12 | # By default, any ISO images found will be populated with a barcode of the
13 | # form DVD_%04d and a volume_tag based on the filename.
14 | #
15 | # CON: This is the connection index for TGTD. This is needed if you run
16 | # multiple instances of TGTD on the same host. Each instance must use a unique
17 | # CON value.
18 | #
19 | # TARGETNAME: The iSCSI name to use for the target.
20 | #
21 | # TARGETPORT: The TCP port that this target will be hosted from.
22 |
23 | CON=1
24 | TARGETNAME=iqn.ronnie.iso:distros
25 | TARGETPORT=3261
26 |
27 | nc -z 127.0.0.1 $TARGETPORT || {
28 | echo "Starting iSCSI target on port $TARGETPORT"
29 | tgtd -C $CON --iscsi portal=0.0.0.0:$TARGETPORT
30 | sleep 3
31 | }
32 |
33 | tgtadm -C $CON --op delete --mode target --tid 1 --force 2>/dev/null
34 | tgtadm -C $CON --op new --mode target --tid 1 -T $TARGETNAME
35 |
36 | # Create a DVD drive
37 | tgtadm -C $CON --op new --mode logicalunit --tid 1 --lun 1 -Y cd
38 | tgtadm -C $CON --op update --mode logicalunit --tid 1 --lun 1 --params vendor_id=STGT_DVD,product_id=DVD101,product_rev=0010,scsi_sn=STGTDVD01,removable=1
39 |
40 | # We need a backend store file for the media changer
41 | SMC=`pwd`/smc-$CON
42 | if [ ! -f $SMC ]; then
43 | dd if=/dev/zero of=$SMC bs=1k count=1
44 | fi
45 |
46 | # Create the SMC device and give it a nice name
47 | tgtadm -C $CON --mode logicalunit --op new --tid 1 --lun 2 -b $SMC --device-type=changer
48 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params vendor_id=STK,product_id=L700,product_rev=0010,scsi_sn=XYZZY_0,removable=1
49 |
50 | # Add a Data Transfer devices (1 drive)
51 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params element_type=4,start_address=1,quantity=1
52 |
53 | # Specify that the DVD above (LUN 1) is the data transfer device we created
54 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params element_type=4,address=1,tid=1,lun=1
55 |
56 | # Medium Transport Elements (robot arm / picker)
57 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params element_type=1,start_address=16,quantity=1
58 |
59 |
60 | # define path to virtual media
61 | VTL=`pwd`/vtl
62 | mkdir -p ${VTL} 2>/dev/null
63 | rm ${VTL}/*
64 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params media_home=${VTL}
65 |
66 | NUM_ELEM=`ls *.iso | wc -l`
67 | echo "Creating $NUM_ELEM storage elements for media"
68 |
69 | # Storage Elements - starting at addr 1024
70 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params element_type=2,start_address=1024,quantity=$NUM_ELEM
71 |
72 | # Populate the slots
73 | SLOT=0
74 | ls *.iso | sed -e "s/.iso$//" | while read ISO; do
75 | BARCODE=`echo $SLOT | awk '{printf "DVD_%04d", $1}'`
76 | ln `pwd`/${ISO}.iso ${VTL}/${BARCODE}
77 | tgtadm -C $CON --mode logicalunit --op update --tid 1 --lun 2 --params element_type=2,address=`expr "1024" "+" "$SLOT"`,barcode="${BARCODE}",volume_tag="${ISO}",sides=1
78 |
79 | SLOT=`expr "$SLOT" "+" "1"`
80 | done
81 |
82 | tgtadm -C $CON --op bind --mode target --tid 1 -I ALL
83 | tgtadm -C $CON --op show --mode target
84 |
--------------------------------------------------------------------------------
/doc/README.glfs:
--------------------------------------------------------------------------------
1 | The 'glfs' backing-store driver provides block access to a file within the
2 | gluster distributed file system (www.gluster.org). The file represents a
3 | LUN visible to the initiator (the file may be a regular file in gluster's
4 | underlying XFS filesystem, or a gluster "block device"). This configuration
5 | gives gluster support for any access method supported by the target driver,
6 | such as iSCSI.
7 |
8 | The backing-store driver uses the interfaces to gluster in libgfapi.so.
9 | This file is part of the glusterfs-api package which can be downloaded from
10 | www.gluster.org.
11 |
12 | To build the glfs backing store driver, set the GLFS_BS environment
13 | variable (export GLFS_BD=1) before running Make.
14 |
15 | When a LUN on a target is created with backing store of type glfs (--bstype
16 | glfs), a handle to gluster is created. The handle is destroyed when the
17 | target is closed. The handle represents a particular volume on a gluster
18 | server and a particular file representing the LUN.
19 |
20 | To set the gluster volume and file, --backing-store takes the form:
21 | volume@hostname:filename
22 |
23 | For example, if the volume name was vol1 , and the host gprfs010, and file
24 | name was "disk1", you would set --backing-store to:
25 |
26 | --backing-store="vol1@gprfs010:disk1"
27 |
28 | For each CDB, the driver issues an appropriate gluster api call against the
29 | handle. For example, WRITE_16 becomes glfs_pwrite(), SYNCHRONIZE_CACHE
30 | becomes glfs_fdatasync() and UNMAP becomes glfs_discard().
31 |
32 | Each call is synchronous, meaning the thread will wait for a response from
33 | gluster before returning to the caller. The libgfapi interfaces support
34 | asynchronous calls, and an asynchronous version of the driver has been
35 | tested. For more information on the asynchronous version please contact
36 | dlambrig@redhat.com.
37 |
38 | If the backing store driver was not used, the linux target driver could
39 | still write data to gluster by loopback mounting the gluster file system.
40 | The backing-store would be a file within the file system. Gluster uses FUSE
41 | to forward I/O from the kernel to it's user space daemon. The overhead
42 | incured by FUSE and the kernel is removed when the backing store driver and
43 | libgfapi package is used.
44 |
45 | The libgfapi interfaces supports logs. You can use the --bsopts option to
46 | set the logfile and loglevel.
47 |
48 | --bsops="logfile=glfs.log;loglevel=3"
49 |
50 |
51 |
--------------------------------------------------------------------------------
/doc/README.lu_configuration:
--------------------------------------------------------------------------------
1 | Preface
2 | --------------
3 | This show a simple example to set up some logical units (lu).
4 | Please refer to README.iscsi on instructions to create logical unit(s).
5 |
6 | tgtadm options
7 | --------------
8 | You are able to modify some logical unit parameters as well as
9 | modify behaviour of SCSI Sense op code.
10 |
11 | NOTE: It is not recommended to change these parameters after the
12 | target/logical unit has been enabled to accept initiators.
13 |
14 | It is currently possible to change/modify the following:
15 |
16 | Vendor Identification
17 | Product Identification
18 | Product Revision
19 | Format of returned 'sense data'
20 | Define if the lu is capable of supporting removable media
21 | Define/set if the lu is online / offline.
22 | Params are passed using the 'tgtadm' utility:
23 |
24 | Format of options are:
25 | vendor_id="string"
26 | product_id="string"
27 | product_rev="string"
28 | removable=<0|1> - 0 = non-removable, 1 = removable media
29 | sense_format=<0|1> - 0 = Clasic sense format, 1 = Support descriptor format
30 | online=<0|1> - 0 == Unit offline, 1 == Unit Online
31 |
32 | The options are passed to the logical unit via the "--params" switch to tgtadm
33 |
34 | e.g.
35 | tgtadm --lld iscsi --mode logicalunit --op update --tid --lun \
36 | --params vendor_id=QUANTUM,product_id=HD100,product_rev=0010
37 | tgtadm --lld iscsi --mode logicalunit --op update --tid --lun \
38 | --params removable=1,sense_format=1,online=1
39 |
40 | Or it can be performed in one go:
41 | tgtadm --lld iscsi --mode logicalunit --op update --tid --lun \
42 | --params vendor_id=QUANTUM,product_id=HD100,product_rev=0010,scsi_sn=FRED00,removable=1,sense_format=0,online=1
43 |
44 |
45 | # sg_inq -v /dev/sg5
46 | inquiry cdb: 12 00 00 00 24 00
47 | standard INQUIRY:
48 | inquiry cdb: 12 00 00 00 42 00
49 | PQual=0 Device_type=0 RMB=1 version=0x05 [SPC-3]
50 | [AERC=0] [TrmTsk=1] NormACA=0 HiSUP=0 Resp_data_format=2
51 | SCCS=0 ACC=0 TGPS=0 3PC=0 Protect=0 BQue=0
52 | EncServ=0 MultiP=0 [MChngr=0] [ACKREQQ=0] Addr16=0
53 | [RelAdr=0] WBus16=0 Sync=0 Linked=0 [TranDis=0] CmdQue=1
54 | Clocking=0x0 QAS=0 IUS=0
55 | length=66 (0x42) Peripheral device type: disk
56 | Vendor identification: QUANTUM
57 | Product identification: HD100
58 | Product revision level: 0010
59 | inquiry cdb: 12 01 00 00 fc 00
60 | inquiry: requested 252 bytes but got 7 bytes
61 | inquiry cdb: 12 01 80 00 fc 00
62 | inquiry: requested 252 bytes but got 12 bytes
63 | Unit serial number: FRED00
64 |
65 | As can be seen from above 'sg_inq' output, the RMB (removable) bit is set to 1.
66 | The Unit serial number page updated with 'FRED00'
67 |
68 | Mode Page Creation
69 | ------------------
70 | Create mode page '2', subpage 0 and 14 bytes of data.
71 | tgtadm --mode logicalunit --op update --tid 1 --lun 2 \
72 | --params mode_page=2:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0
73 |
74 | Create mode page '3', subpage 0 and 22 bytes of data.
75 | tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
76 | --params mode_page=3:0:22:0:0:0:0:0:0:0:0:1:0:2:0:0:0:0:0:0:0:0:13:0:0
77 |
78 | Create mode page '10', subpage 0 and 10 bytes of data.
79 | tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
80 | --params mode_page=10:0:10:2:0:0:0:0:0:0:0:2:0
81 |
82 | Create mode page '0x1c', subpage 0 and 10 bytes of data.
83 | tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
84 | --params mode_page=0x1c:0:10:8:0:0:0:0:0:0:0:0:0
85 |
86 |
87 | SMC unique options
88 | ------------------
89 |
90 | --params have several unique key=value pairs ontop of all other modules.
91 | - element_type=<1|2|3|4>
92 | - start_address=Number between 1 & 65535
93 | - quantity=Number between 1 & 65535
94 | - sides=1|2
95 | - address=Number between 1 & 65535
96 | - barcode="Char string up to 10 chars"
97 | - tid=
98 | - lun=
99 | - media_home=/path/to/virtual/media
100 | The 'barcode' of media is appended to this path specified in media_home and
101 | it is this file which is used for the backing store when reading/writing to
102 | DATA TRANSFER DEVICE at address 'tid=x lun=x'
103 |
104 | Several of these parameters 'work together'
105 |
106 | e.g. To add 'quantity' slots as 'element_type' starting at 'start_address'
107 | - element_type=<1|2|3|4>
108 | - start_address=Number between 1 & 65535
109 | - quantity=Number between 1 & 65535
110 |
111 | Note: start_address + quantity should not overlap with any other slots..
112 |
113 |
114 | While 'configuring slot 'address' of 'element_type':
115 | - Set barcode of meda (occupy slot)
116 | - If element type is DATA TRANSFER DEVICE, then define TID & LUN of device.
117 |
118 | - element_type=<1|2|3|4>
119 | - address=Number between 1 & 65535
120 | - barcode="String up to 10 chars"
121 | - sides=<1|2>
122 | - tid=
123 | - lun=
124 |
125 |
126 | It is the responsibility of the user not to configure overlapping slots
127 | of differing types.
128 |
129 | Slot types:
130 | 1 -> Medium Transport (picker arm)
131 | 2 -> Storage Element
132 | 3 -> Import/Export Element
133 | 4 -> Data Transfer device (CD drive, tape drive, MO drive etc)
134 |
135 | Please refer to scripts/tgt-core-test for a working example.
136 |
137 |
--------------------------------------------------------------------------------
/doc/README.passthrough:
--------------------------------------------------------------------------------
1 | Preface
2 | -------------
3 | This documents an example to set up tgt targets utilising existing SCSI
4 | targets on the host utilizing tgt passthrough module and /dev/sg paths.
5 |
6 | The hardware to be 'exported' via the SCSI target framework is an
7 | IBM 3573-TL library with a single LTO4 drive.
8 |
9 | Physical tape library connected and configured to host:
10 | # lsscsi -g
11 | [0:0:0:0] disk MAXTOR ATLAS10K4_36SCA DFM0 /dev/sda /dev/sg0
12 | [0:0:6:0] process PE/PV 1x3 SCSI BP 1.1 - /dev/sg1
13 | [2:0:1:0] tape IBM ULT3580-TD4 8192 /dev/st1 /dev/sg4
14 | [2:0:1:1] mediumx IBM 3573-TL 6.50 - /dev/sg5
15 |
16 | Please refer to the README.iscsi or README.iser for instructions
17 | specific to setting up the transport layer specific section.
18 |
19 | Many of the examples below are using the iSCSI lld (low Level) transport.
20 |
21 |
22 | Starting the daemon
23 | -------------
24 | Please refer to 'Starting the daemon' in the README.iscsi or README.iser.
25 | on instructions for correctly starting the daemon for your transport of choice.
26 |
27 |
28 | Configuration
29 | -------------
30 | Everyting is configured via the tgtadm management tool.
31 |
32 | Please refer to "Configuration" in README.iscsi or README.iser on how
33 | to configure your target for the transport of choice.
34 |
35 | Return to here for further instructions on setting up each logical unit using the
36 | passthrough module.
37 |
38 | An example to setup the target (target ID 1) for iSCSI
39 | host:~/tgt# ./usr/tgtadm --lld iscsi --op new --mode target --tid 1 \
40 | -T iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz
41 |
42 | To display your target configuration:
43 | host:~/tgt# ./usr/tgtadm --lld iscsi --op show --mode target
44 | Target 1: iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz
45 | System information:
46 | Driver: iscsi
47 | Status: running
48 | I_T nexus information:
49 | LUN information:
50 | LUN: 0
51 | Type: controller
52 | SCSI ID: deadbeaf1:0
53 | SCSI SN: beaf10
54 | Size: 0
55 | Backing store: No backing store
56 | Account information:
57 | ACL information:
58 |
59 | The controller device for management with lun 0 was created
60 | automatically. You can't remove it.
61 |
62 | Now it's time to add a logical unit to the target:
63 | (The tape drive connected via /dev/sg4 - refer to 'lsscsi' output above)
64 | The important flags are:
65 | - Specify device type as passthruough
66 | "--device-type=pt"
67 | - Backing store type is the '/dev/sg' paths
68 | "--bstype=sg"
69 | - Backing store path to use
70 | "-b /dev/sg4"
71 |
72 | host:~/tgt# ./usr/tgtadm --lld iscsi --op new --mode logicalunit \
73 | --tid 1 --lun 1 --bstype=sg --device-type=pt -b /dev/sg4
74 |
75 | To display the current configuration:
76 |
77 | host:~/tgt# ./usr/tgtadm --lld iscsi --op show --mode target
78 | Target 1: iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz
79 | System information:
80 | Driver: iscsi
81 | Status: running
82 | I_T nexus information:
83 | LUN information:
84 | LUN: 0
85 | Type: controller
86 | SCSI ID: deadbeaf1:0
87 | SCSI SN: beaf10
88 | Size: 0
89 | Backing store: No backing store
90 | LUN: 1
91 | Type: (null)
92 | SCSI ID: IET 00010002
93 | SCSI SN: beaf12
94 | Size: 0 MB
95 | Online: Yes
96 | Removable media: No
97 | Backing store type: sg
98 | Backing store path: /dev/sg4
99 | Backing store flags:
100 | Account information:
101 | ACL information:
102 |
103 | To add another logical unit to this target:
104 | host:~/tgt# ./usr/tgtadm --lld iscsi --op new --mode logicalunit \
105 | --tid 1 --lun 2 --bstype=sg --device-type=pt -b /dev/sg5
106 |
107 |
108 | If you don't need to configure this target any more, enable the target
109 | to accept any initiators:
110 |
111 | host:~/tgt# ./usr/tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
112 |
113 | Note "ACL information" section. "ALL" means that this target accepts
114 | any initiators. The ACL feature also provides the access control based
115 | on initiators' addresses.
116 |
117 | For further instructions on ACL and account setup, please refer to the README.iscsi
118 |
119 | As above, use the '--op show' option to display your current setup.
120 | host:~/tgt# ./usr/tgtadm --lld iscsi --op show --mode target
121 | Target 1: iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz
122 | System information:
123 | Driver: iscsi
124 | Status: running
125 | I_T nexus information:
126 | LUN information:
127 | LUN: 0
128 | Type: controller
129 | SCSI ID: deadbeaf1:0
130 | SCSI SN: beaf10
131 | Size: 0
132 | Backing store: No backing store
133 | LUN: 1
134 | Type: (null)
135 | SCSI ID: IET 00010002
136 | SCSI SN: beaf12
137 | Size: 0 MB
138 | Online: Yes
139 | Removable media: No
140 | Backing store type: sg
141 | Backing store path: /dev/sg4
142 | Backing store flags:
143 | LUN: 2
144 | Type: (null)
145 | SCSI ID: IET 00010002
146 | SCSI SN: beaf12
147 | Size: 0 MB
148 | Online: Yes
149 | Removable media: No
150 | Backing store type: sg
151 | Backing store path: /dev/sg5
152 | Backing store flags:
153 | Account information:
154 | ACL information:
155 | ALL
156 |
157 |
158 |
159 | iSCSI Initiator Information
160 | -------------
161 | After the target accepts initiators, the system information would be
162 | something like the following:
163 |
164 | Linux open-iscsi initiator
165 | hostb:~ # iscsiadm -m discovery -t sendtargets -p 10.251.60.20
166 | 10.251.60.20:3260,1 iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz
167 |
168 | hostb:~ # iscsiadm -m node -T iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz \
169 | -p 10.251.60.20 --login
170 | Logging in to [iface: default, target: iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz, portal: 10.251.60.20,3260]
171 | Login to [iface: default, target: iqn.2001-04.com.example:storage.vtl.amiens.sys1.xyz, portal: 10.251.60.20,3260]: successful
172 |
173 | hostb:~ # lsscsi -g
174 | [0:0:0:0] cd/dvd TSSTcorp DVD-ROM TS-L333A D100 /dev/sr0 /dev/sg0
175 | [2:0:0:0] disk SEAGATE ST3400755SS NS25 /dev/sda /dev/sg1
176 | [2:0:1:0] disk SEAGATE ST3400755SS NS25 /dev/sdb /dev/sg2
177 | [3:0:0:0] disk DGC DISK 0429 /dev/sdc /dev/sg3
178 | [3:0:1:0] disk DGC DISK 0429 /dev/sdd /dev/sg4
179 | [11:0:0:0] storage IET Controller 0001 - /dev/sg5
180 | [11:0:0:1] tape IBM ULT3580-TD4 8192 /dev/st0 /dev/sg6
181 | [11:0:0:2] mediumx IBM 3573-TL 6.50 - /dev/sg7
182 |
183 |
184 | Shutdown the target cleanly
185 | ---------------------------
186 | host:~/tgt# tgtadm --op unbind --mode target --tid 1 -I ALL
187 | host:~/tgt# tgtadm --op delete --mode conn --tid 1
188 | host:~/tgt# tgtadm --op delete --mode target --tid 1
189 | host:~/tgt# tgtadm --op delete --mode system
190 |
191 |
--------------------------------------------------------------------------------
/doc/README.rbd:
--------------------------------------------------------------------------------
1 | The 'rbd' backing-store driver provides access to Ceph (http://ceph.com)
2 | 'RADOS block devices (rbd)" through tgtd.
3 |
4 | Ceph is a distributed storage system that provides clustered redundant
5 | object storage; one of the ways to use such storage is through the
6 | abstraction of a "block device". rbd devices can be mapped through a
7 | kernel driver and show up as block devices directly, or they can be used
8 | through userland libraries to provide backing store for things like QEMU
9 | virtual disks.
10 |
11 | The bs_rbd backing-store driver allows tgtd to use rbd images as backing
12 | storage without requiring the 'rbd' kernel block device driver, and so
13 | avoids kernel version dependencies and the extra context switching between
14 | kernel and userland. It also allows for userland caching of block images,
15 | managed by librbd.
16 |
17 | To use bs_rbd, select --bstype rbd, and set --backing-store to an rbd
18 | image specifier. This is of the form
19 |
20 | [poolname/]imagename[@snapname]
21 |
22 | where poolname is the RADOS pool containing the rbd image (defaults to
23 | "rbd"), imagename is the image you want to export, and snapname is the
24 | optional (readonly) snapshot of the image imagename. (Obviously when
25 | a snapshot is exported, writes are not supported.)
26 |
27 | You may also want to use the --bsopts parameter to pass Ceph-specific
28 | parameters to bs_rbd. Accepted keywords are
29 |
30 | conf=
31 |
32 | This sets the path to the ceph.conf file for the cluster that
33 | stgt should connect to for this target/lun creation (luns may
34 | use different cluster connections).
35 |
36 | id=
37 |
38 | This sets the id portion of the ceph "client name" (which is
39 | "type.id"). Type is fixed at "client", and the default name is
40 | "client.admin", but you probably want this to set id to
41 | something like "tgt" so that the name of the ceph client is
42 | "client.tgt". This lets you control permissions differently
43 | for the tgt client compared to others, and sets the default log path, etc.
44 | See the Ceph documentation regarding client names.
45 |
46 | cluster=
47 |
48 | This sets the Ceph cluster name, if you have multiple clusters or
49 | if your cluster name is anything other than "ceph".
50 | This is in turn used by librados to find the conf file and key files.
51 |
52 | To specify multiple options, separate them with ';', and since you are,
53 | make sure to quote the option string to protect the semicolon from
54 | the shell:
55 |
56 | --bsopts "conf=/usr/local/ceph/ceph.conf;id=tgt"
57 |
58 |
--------------------------------------------------------------------------------
/doc/README.sbcjukebox:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # EXAMPLE of sbc jukebox
3 | #
4 | # This is a simple script to create and drive a sbcjukebox that contains
5 | # the $NUMSLOT most recent snapshots of a production SBC LUN.
6 | # It requires that you store the LUN files on a filesystem that can create
7 | # file level cow snapshots using "cp --reflink".
8 | # On linux this is supported on BTRFS and possibly other filesystems too.
9 | #
10 | # It creates a new target with one SBC decice and a mediachanger.
11 | #
12 | #
13 | # TID is the target id to use
14 | # TNAME is the target iqn name to use
15 | # FILE is the backing store file for a production LUN. This file must reside on
16 | # a cow snapshot capable filesystem.
17 | # SNAPDIR is where we keep the SMC media file as well as where all snapshots are
18 | # kept. This must be the same filesystem as FILE
19 | # NUMSLOTS is how many old snapshots we want to keep.
20 | # READONLYSNAPS is whether or not the snapshot device is readonly or not
21 |
22 | # sbcjukebox.sh start
23 | # to create the target and populate the storage elements.
24 | #
25 | # sbcjukebox.sh list
26 | # to show which snapshots are available
27 | #
28 | # sbcjukebox.sh snapshot
29 | # to take a new snapshot of the production LUN
30 | #
31 |
32 |
33 |
34 | TID=2
35 | TNAME="iqn.ronnie.test-snapshot"
36 | FILE="/data/RHEL6/RHEL6-1.img"
37 | SNAPDIR="${FILE}.snapshots"
38 | NUMSLOTS=8
39 | READONLYSNAPS="yes"
40 |
41 |
42 | [ -d "$SNAPDIR" ] || mkdir "$SNAPDIR"
43 |
44 | usage() {
45 | echo "sbcjukebox {start|list|snapshot|usage}"
46 | }
47 |
48 | prune_old_snapshots() {
49 | ls $SNAPDIR | egrep -v "^smc$" | sort -n -r | tail -n +${NUMSLOTS} | while read OLD; do
50 | echo "Deleting old snapshot $OLD"
51 | rm -f ${SNAPDIR}/${OLD}
52 | done
53 | }
54 |
55 | populate_elements() {
56 | ELEMENT=1024
57 | SNAPSHOTS=`ls $SNAPDIR | egrep -v "^smc$" | sort -n | head -n ${NUMSLOTS}`
58 | for SNAP in $SNAPSHOTS; do
59 | tgtadm --mode logicalunit --op update --tid $TID --lun 2 --params element_type=2,address=$ELEMENT,barcode=$SNAP,sides=1
60 | ELEMENT=`expr "$ELEMENT" "+" "1"`
61 | done
62 |
63 | LAST=`expr "1024" "+" "$NUMSLOTS"`
64 | while [ $ELEMENT -lt $LAST ]; do
65 | tgtadm --mode logicalunit --op update --tid $TID --lun 2 --params element_type=2,address=$ELEMENT,clear_slot=1
66 | ELEMENT=`expr "$ELEMENT" "+" "1"`
67 | done
68 |
69 | tgtadm --mode logicalunit --op update --tid $TID --lun 2 --params element_type=2,address=`expr "$LAST" "-" "1"`,clear_slot=1
70 | }
71 |
72 | snapshot() {
73 | SNAP=`date +"%y%m%d%H%M"`
74 |
75 | echo Create snapshot $SNAP
76 | cp --reflink $FILE $SNAPDIR/$SNAP
77 |
78 | prune_old_snapshots
79 | populate_elements
80 | }
81 |
82 | list() {
83 | echo Snapshots:
84 | ls $SNAPDIR | egrep -v "^smc$"
85 | }
86 |
87 | start() {
88 | #create a target
89 | tgtadm --lld iscsi --op new --mode target --tid $TID -T $TNAME
90 |
91 | # create the data transfer device
92 | tgtadm --op new --mode logicalunit --tid $TID --lun 1 -Y disk
93 | tgtadm --op update --mode logicalunit --tid $TID --lun 1 --params vendor_id=STGT,product_id=SNAPSHOT_SBC,product_rev=0010
94 |
95 | [ "$READONLYSNAPS" != "yes" ] || {
96 | tgtadm --op update --mode logicalunit --tid $TID --lun 1 --params readonly=1
97 | }
98 |
99 | # create backing store for SMC
100 | [ -f "${SNAPDIR}/smc" ] || dd if=/dev/zero of="${SNAPDIR}/smc" bs=1k count=1
101 |
102 | # create the media changer
103 | tgtadm --op new --mode logicalunit --tid $TID --lun 2 -b "${SNAPDIR}/smc" --device-type=changer
104 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params vendor_id=STGT,product_id=SNAPSHOT_SMC,product_rev=0010,removable=1
105 |
106 | # Add a Data Transfer devices (1 drive)
107 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params element_type=4,start_address=1,quantity=1
108 |
109 | # Specify that the DISK above (LUN 1) is the data transfer device
110 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params element_type=4,address=1,tid=$TID,lun=1
111 |
112 | # Medium Transport Elements (robot arm / picker)
113 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params element_type=1,start_address=16,quantity=1
114 |
115 | # define path to virtual media
116 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params media_home=${SNAPDIR}
117 |
118 | # create the storage elements
119 | tgtadm --op update --mode logicalunit --tid $TID --lun 2 --params element_type=2,start_address=1024,quantity=$NUMSLOTS
120 |
121 | prune_old_snapshots
122 | populate_elements
123 |
124 | tgtadm --lld iscsi --op bind --mode target --tid $TID -I ALL
125 | tgtadm --lld iscsi --op show --mode target
126 | }
127 |
128 | case "$1" in
129 | start)
130 | start
131 | ;;
132 | snapshot)
133 | snapshot
134 | ;;
135 | list)
136 | list
137 | ;;
138 | *)
139 | usage
140 | ;;
141 | esac
142 |
143 |
--------------------------------------------------------------------------------
/doc/README.sheepdog:
--------------------------------------------------------------------------------
1 | Sheepdog is a distributed storage system for QEMU, iSCSI clients and
2 | RESTful services. It provides highly available block level storage
3 | volumes that can be attached to QEMU-based virtual machines. The
4 | volumes can also be attached to other virtual machines and operating
5 | systems run on baremetal hardware if they support iSCSI
6 | protocol. Sheepdog scales to several hundreds nodes, and supports
7 | advanced volume management features such as snapshot, cloning, and
8 | thin provisioning. Stuff like volumes, snapshots, QEMU's vm-state
9 | (from live snapshot), even ISO files can be stored in the Sheepdog
10 | cluster.
11 |
12 | With tgt, sheepdog's virtual disks can be used by iSCSI
13 | initiators. Below is a brief description of setup.
14 |
15 | 1. Install and launch tgt
16 |
17 | $ git clone https://github.com/fujita/tgt.git
18 | $ cd tgt
19 | $ make
20 | # make install
21 | 2. Create a sheepdog VDI
22 |
23 | There is no special procedures in this step.
24 |
25 | $ dog vdi create tgt0 100G
26 | Of course you can use existing VDIs as iSCSI logical units.
27 |
28 | 3. Setup iSCSI target provided by tgt
29 |
30 | One logical unit corresponds to one VDI of sheepdog. In this step, we
31 | create iSCSI target and logical unit which can be seen by iSCSI
32 | initiator.
33 |
34 | # tgtd
35 | # tgtadm --op new --mode target --tid 1 --lld iscsi --targetname iqn.2013-10.org.sheepdog-project
36 | # tgtadm --op new --mode lu --tid 1 --lun 2 --bstype sheepdog --backing-store unix:/sheep_store/sock:tgt0
37 | # tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
38 |
39 | The most important parameter is --backing-store which is required by
40 | tgtadm when we create the logical unit in the target (the third line
41 | of the above commands). With this parameter, we tell the tgtd
42 | process how to connect to the sheep process, which VDI we use as the
43 | logical unit, which snapshot ID of the VDI we use. The form of the
44 | --backing-store option is like this:
45 |
46 | unix:path_of_unix_domain_socket:vdi
47 | unix:path_of_unix_domain_socket:vdi:tag
48 | unix:path_of_unix_domain_socket:vdi:snapid
49 | tcp:host:port:vdi
50 | tcp:host:port:vdi:tag
51 | tcp:host:port:vdi:snapid
52 |
53 | We use a special case of the first one in the above command
54 | sequence. It means "connect to sheep process via unix domain socket
55 | protocol, path of unix domain socket is /sheep_store/sock, use VDI
56 | named tgt0 as a backing store of newly created logical unit".
57 |
58 | You can also specify sheep which is running on remote host via
59 | TCP. But if tgtd process is running on a same host of sheep process,
60 | there is no benefit of using TCP. Unix domain socket can provide
61 | faster connection than TCP.
62 |
63 | You can also specify tag or ID of snapshots via suffix of the
64 | --backing-store option.
65 |
66 | 4. Setup iSCSI session (example of the open-iscsi initiator on Linux)
67 |
68 | After setting up iSCSI target, you can use the VDIs from any virtual
69 | machines and operating systems which supports iSCSI initiator. Many of
70 | popular hypervisors and operating systems support it (e.g. VMware ESX
71 | Family, Linux, Windows, etc). In this example, the way of Linux +
72 | open-iscsi is described.
73 |
74 | At first, you have to install open-iscsi ( http://www.open-iscsi.org/
75 | ) and launch it. Major linux distros provide their open-iscsi
76 | package. Below is a way of installation in Debian and Ubuntu based
77 | systems.
78 |
79 | # apt-get install open-iscsi
80 | # /etc/init.d/open-iscsi start
81 |
82 | Next, we need to let iscsid discover and login to the target we've
83 | already created in the above sequence. If the initiator is running
84 | on different host from the target, you have to change the IP
85 | addresses in the below commands.
86 |
87 | # iscsiadm -m discovery -t st -p 127.0.0.1
88 | # iscsiadm -m node --targetname iqn.2013-10.org.sheepdog-project --portal 127.0.0.1:3260 --login
89 |
90 | New device files, e.g. /dev/sdb, will be created on your system after
91 | login completion. Now your system can use the speepdog VDIs like
92 | ordinal HDDs.
93 |
94 | ToDo
95 |
96 | Currently, iSCSI multipath is not supported by sheepdog. It will be
97 | implemented in v0.9.0.
98 |
99 | The latest version of this guide can be found here:
100 | https://github.com/sheepdog/sheepdog/wiki/General-protocol-support-%28iSCSI-and-NBD%29
101 |
--------------------------------------------------------------------------------
/doc/README.ssc:
--------------------------------------------------------------------------------
1 | Introduction
2 | -------------
3 | The SSC emulation in TGTD can emulate tape drives by using files. This
4 | virtualization technology is known as a virtual tape library (VTL).
5 |
6 |
7 | Solaris tips
8 | -------------
9 | If one wants to get VTL working on a Solaris initiator (and this
10 | target of course under Linux) then it is rather simple to get a tape
11 | drive working. Getting the changer device working under Solaris
12 | (OpenSolaris) take a bit more effort. This file describes the way to
13 | do it.
14 |
15 | Although most of it is probably well know to Solaris fans, it took me
16 | a bit of time to figure out to get the VTL target working fine under
17 | OpenSolaris. For those who want to give it a try, here are the
18 | commands:
19 |
20 | For normal disk and cd targets no files have to be changed. All you
21 | need is the following:
22 |
23 | # svcadm enable iscsi_initiator
24 |
25 | and check if it is online:
26 |
27 | # svcs iscsi_initiator
28 |
29 | the state should be online.
30 |
31 | Now we add the discovery address to the initiator:
32 |
33 | # iscsiadm add discovery-address
34 |
35 | Now we configure the discovery mode to sendtargets:
36 |
37 | # iscsiadm modify discovery -t enable
38 |
39 | Check the target:
40 |
41 | # iscsiadm list target -S
42 |
43 | And create the device files:
44 |
45 | # devfsadm -i iscsi
46 |
47 |
48 | Tape devices will be shown properly, but not the changer device, this
49 | takes a bit more work. Two files need to be changed, and a reboot is
50 | needed to set things up properly.
51 |
52 | In the file /etc/driver_aliases the two lines
53 |
54 | sgen "scsa,08.bfcp"
55 | sgen "scsa,08.bvhci"
56 |
57 | need to be replaced with
58 |
59 | sgen "scsiclass,08"
60 |
61 |
62 | The file /kernel/drv/sgen.conf, which is basically all commented out
63 | needs to have the following lines:
64 |
65 | device-type-config-list="changer","sequential";
66 | inquiry-config-list= "*", "*";
67 |
68 | name="sgen" class="scsi" target=0 lun=4;
69 | name="sgen" class="scsi" target=1 lun=4;
70 | name="sgen" class="scsi" target=2 lun=4;
71 | name="sgen" class="scsi" target=3 lun=4;
72 | name="sgen" class="scsi" target=4 lun=4;
73 | name="sgen" class="scsi" target=5 lun=4;
74 | name="sgen" class="scsi" target=6 lun=4;
75 | name="sgen" class="scsi" target=7 lun=4;
76 | name="sgen" class="scsi" target=8 lun=4;
77 | name="sgen" class="scsi" target=9 lun=4;
78 | name="sgen" class="scsi" target=10 lun=4;
79 | name="sgen" class="scsi" target=11 lun=4;
80 | name="sgen" class="scsi" target=12 lun=4;
81 | name="sgen" class="scsi" target=13 lun=4;
82 | name="sgen" class="scsi" target=14 lun=4;
83 | name="sgen" class="scsi" target=15 lun=4;
84 |
85 |
86 | For the last bit it should be noted that my changer was set to lun 4,
87 | and since I don't know which target I put all target numbers in (0-15).
88 |
89 | After these modifications the best is to reboot the machine, and do
90 | the iscsi commands above, and he presto it works:
91 |
92 | In my case, three tape drives and one changer:
93 |
94 | root@solar:/kernel/drv# iscsiadm list target -S
95 | Target: iqn.2008-09.com.example:server.tape
96 | Alias: -
97 | TPGT: 1
98 | ISID: 4000002a0000
99 | Connections: 1
100 | LUN: 4
101 | Vendor: STK
102 | Product: L700
103 | OS Device Name: /dev/scsi/changer/c0t0d0
104 | LUN: 3
105 | Vendor: HP
106 | Product: LTO3 ULTRIUM
107 | OS Device Name: /dev/rmt/2n
108 | LUN: 2
109 | Vendor: HP
110 | Product: LTO3 ULTRIUM
111 | OS Device Name: /dev/rmt/1n
112 | LUN: 1
113 | Vendor: HP
114 | Product: LTO3 ULTRIUM
115 | OS Device Name: /dev/rmt/0n
116 |
117 |
118 |
119 | root@solar:/kernel/drv# mtx -f /dev/scsi/changer/c0t0d0 status
120 | Storage Changer /dev/scsi/changer/c0t0d0:3 Drives, 29 Slots ( 5 Import/Export )
121 | Data Transfer Element 0:Empty
122 | Data Transfer Element 1:Empty
123 | Data Transfer Element 2:Empty
124 | Storage Element 1:Full :VolumeTag=A0000001
125 | Storage Element 2:Full :VolumeTag=A0000002
126 | Storage Element 3:Full :VolumeTag=A0000003
127 | Storage Element 4:Full :VolumeTag=A0000004
128 | Storage Element 5:Full :VolumeTag=A0000005
129 | Storage Element 6:Full :VolumeTag=A0000006
130 | Storage Element 7:Full :VolumeTag=A0000007
131 | Storage Element 8:Full :VolumeTag=A0000008
132 | Storage Element 9:Empty:VolumeTag=
133 | Storage Element 10:Empty:VolumeTag=
134 | Storage Element 11:Empty:VolumeTag=
135 | Storage Element 12:Empty:VolumeTag=
136 | Storage Element 13:Empty:VolumeTag=
137 | Storage Element 14:Empty:VolumeTag=
138 | Storage Element 15:Empty:VolumeTag=
139 | Storage Element 16:Empty:VolumeTag=
140 | Storage Element 17:Empty:VolumeTag=
141 | Storage Element 18:Empty:VolumeTag=
142 | Storage Element 19:Empty:VolumeTag=
143 | Storage Element 20:Empty:VolumeTag=
144 | Storage Element 21:Empty:VolumeTag=
145 | Storage Element 22:Empty:VolumeTag=
146 | Storage Element 23:Empty:VolumeTag=
147 | Storage Element 24:Full :VolumeTag=CLN00001
148 | Storage Element 25 IMPORT/EXPORT:Empty:VolumeTag=
149 | Storage Element 26 IMPORT/EXPORT:Empty:VolumeTag=
150 | Storage Element 27 IMPORT/EXPORT:Empty:VolumeTag=
151 | Storage Element 28 IMPORT/EXPORT:Empty:VolumeTag=
152 | Storage Element 29 IMPORT/EXPORT:Empty:VolumeTag=
153 |
--------------------------------------------------------------------------------
/doc/README.vtl:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a simple script to aid in setting up a virtual tape library
3 | # (VTL) using STGT
4 | #
5 | # You can tweak the settings for how many tape drives and how many
6 | # and how big tapes the library should have using the variables below
7 |
8 |
9 | # Connection number. You can use multiple concurrent TGTD instances as
10 | # long as you give them unique CN numbers and they listen on different
11 | # portals
12 | CN=1
13 | # Listen to port 3260 on wildcard for both ipv4 and ipv6
14 | PORTAL=:3260
15 | # iSCSI name for this target
16 | TARGET=iqn.2012-08.ronnie.vtl
17 | # Number of TAPE Drives for this virtual tape library
18 | NUM_DRIVES=2
19 | # Number of tapes
20 | NUM_TAPES=8
21 | # Tape size in MB
22 | TAPE_SIZE=1024
23 | # Directory where the tape library state and media will be stored
24 | VTLDIR=$HOME/vtl
25 |
26 |
27 |
28 | # Create the directory to store the tapes
29 | if [ ! -d $VTLDIR ]; then
30 | echo Creating directory for VTL : $VTLDIR
31 | mkdir -p $VTLDIR
32 | fi
33 |
34 | # make sure we have a backing store for the media changer
35 | if [ ! -f $VTLDIR/smc ]; then
36 | echo Creating a backing store for the media changer : $VTLDIR/smc
37 | dd if=/dev/zero of=$VTLDIR/smc bs=1k count=1 2>/dev/null
38 | fi
39 |
40 | # Create the tapes
41 | seq 1 $NUM_TAPES | while read IDX; do
42 | TAPE=`echo $IDX | awk '{printf "%08d", $1}'`
43 | if [ ! -f $VTLDIR/$TAPE ]; then
44 | echo Creating blank tape : $TAPE
45 | tgtimg --op new --device-type tape --barcode $TAPE --size $TAPE_SIZE --type data --file $VTLDIR/$TAPE
46 | fi
47 | done
48 |
49 |
50 | # Restart tgtd
51 | echo Restart TGTD
52 | tgt-admin -C $CN --update ALL -c /dev/null -f
53 | tgtadm -C $CN --op delete --mode system
54 | tgtd -C $CN --iscsi portal=$PORTAL
55 | sleep 1
56 |
57 |
58 | echo Create target
59 | tgtadm -C $CN --lld iscsi --op new --mode target --tid 1 -T $TARGET
60 |
61 | # Create the tape drives
62 | echo Create tape drives
63 | seq 1 $NUM_DRIVES | while read IDX; do
64 | TAPE=`echo $IDX | awk '{printf "%08d", $1}'`
65 | echo Create tape drive $IDX
66 | tgtadm -C $CN --lld iscsi --mode logicalunit --op new --tid 1 --lun $IDX -b $VTLDIR/$TAPE --device-type=tape
67 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $IDX --params online=0
68 | done
69 |
70 | # Create the changer
71 | echo Create media changer device
72 | LUN=`expr "$NUM_DRIVES" "+" "1"`
73 | tgtadm -C $CN --lld iscsi --mode logicalunit --op new --tid 1 --lun $LUN -b $VTLDIR/smc --device-type=changer
74 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params media_home=$VTLDIR
75 |
76 | # Add data transfer devices (one for each tape drive)
77 | echo Adding data transfer devices
78 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params element_type=4,start_address=1,quantity=$NUM_DRIVES
79 |
80 | seq 1 $NUM_DRIVES | while read IDX; do
81 | echo Adding data transfer device for drive $IDX
82 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params element_type=4,address=$IDX,tid=1,lun=$IDX
83 | done
84 |
85 | # Add medium transport elements (robot arm / picker)
86 | echo Adding medium transport elements
87 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params element_type=1,start_address=$LUN,quantity=1
88 |
89 |
90 | # Storage elements
91 | echo Adding storage elements
92 | STORAGE=`expr "$LUN" "+" "1"`
93 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params element_type=2,start_address=$STORAGE,quantity=$NUM_TAPES
94 |
95 | # Add media to the storage slots
96 | seq 1 $NUM_TAPES | while read IDX; do
97 | TAPE=`echo $IDX | awk '{printf "%08d", $1}'`
98 | echo Loading $TAPE into storage slot $STORAGE
99 | tgtadm -C $CN --lld iscsi --mode logicalunit --op update --tid 1 --lun $LUN --params element_type=2,address=$STORAGE,barcode=$TAPE,sides=1
100 | STORAGE=`expr "$STORAGE" "+" "1"`
101 | done
102 |
103 |
104 | # Allow anyone to access this target and the VTL
105 | tgtadm -C $CN --lld iscsi --op bind --mode target --tid 1 -I ALL
106 |
107 | # show all our good work
108 | tgtadm -C $CN --lld iscsi --op show --mode target
109 |
110 |
--------------------------------------------------------------------------------
/doc/tgt-setup-lun.8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tgt-setup-lun
6 | 8
7 |
8 |
9 |
10 | tgt-setup-lun
11 |
12 | Helper script that creates a target, adds a device to the target, and defines
13 | initiators that can connect to the target
14 |
15 |
16 |
17 |
18 |
19 | tgt-setup-lun
20 | -d <device>
21 | -n <targetname>
22 | -b <bsname>
23 | -t <transport>
24 | -C <control_port>
25 | initiator_IP
26 | -h
27 |
28 |
29 |
30 | DESCRIPTION
31 |
32 | Creates a target according to the supplied target_name. tgtd must
33 | be running. The format of the default IQN generated from the target name is:
34 | "iqn.2001-04.com.<hostname>-<target_name>", or a
35 | complete IQN may be given.
36 | The target name must be unique.
37 |
38 |
39 | The script then adds the requested device to the target. If specific IP
40 | addresses are defined, it adds them to the list of allowed initiators
41 | for that target. If no IP addresses is defined, it defines that the
42 | target accepts any initiator.
43 |
44 |
45 |
46 |
47 | EXAMPLES
48 |
49 |
50 |
51 | Create a target that uses /dev/sdb1 and allows connections only from
52 | 192.168.10.81:
53 |
54 |
55 | tgt-setup-lun -d /dev/sdb1 -n my_target 192.168.10.81
56 |
57 |
58 |
59 |
60 |
61 | Create a target that uses /dev/sdb1 and allows connections only from
62 | 192.168.10.81 and 192.168.10.82:
63 |
64 |
65 | tgt-setup-lun -d /dev/sdb1 -n my_target 192.168.10.81 192.168.10.82
66 |
67 |
68 |
69 |
70 |
71 | Create a target that uses /dev/sdb1 and allows connections from any
72 | initiator:
73 |
74 |
75 | tgt-setup-lun -d /dev/sdb1 -n my_target
76 |
77 |
78 |
79 |
80 |
81 | Display help:
82 |
83 |
84 | tgt-setup-lun -h
85 |
86 |
87 |
88 |
89 |
90 | AUTHOR
91 |
92 | Written by Erez Zilber
93 |
94 |
95 |
96 | SEE ALSO
97 |
98 | targets.conf(5), tgtd(8), tgtadm(8), tgtimg(8), tgt-admin(8).
99 |
100 |
101 |
102 |
103 | REPORTING BUGS
104 |
105 | Report bugs to <stgt@vger.kernel.org>
106 |
107 |
108 |
109 | COPYRIGHT
110 |
111 | Copyright � Voltaire Ltd. 2008.
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/doc/tgtd.8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tgtd
6 | 8
7 |
8 |
9 |
10 |
11 | tgtd
12 | The SCSI Target Daemon
13 |
14 |
15 |
16 |
17 | tgtd
18 |
19 |
20 |
21 | tgtd
22 | -C --control-port <INTEGER>
23 | -d --debug <INTEGER>
24 | -f --foregound
25 | -h --help
26 | --iscsi <...>
27 |
28 |
29 |
30 |
31 | DESCRIPTION
32 |
33 | Tgtd is a SCSI Target daemon. It can be used to provide SCSI target
34 | service to a network. The most common service is iSCSI but other services are also
35 | supported.
36 |
37 |
38 |
39 |
40 | Device types
41 |
42 | Tgtd provides support for both emulated and passthrough of real devices.
43 |
44 |
45 |
46 | Tgtd can emulate the following types of devices:
47 |
48 | disk : Normal disk device. Emulates a SCSI harddisk.
49 | tape : Tape device. Emulates a SCSI tape drive.
50 | cd : CD device. Emulates a SCSI DVD burner.
51 | changer : Media changer. Emulate the changer device for a virtual tape library or DVD jukebox.
52 |
53 |
54 |
55 | OPTIONS
56 |
57 |
58 | -d --debug <INTEGER>
59 |
60 |
61 | Set to non-zero value to activate additional debugging messages to
62 | be logged.
63 |
64 |
65 |
66 |
67 | -f --foreground
68 |
69 |
70 | Run the daemon in the foreground.
71 |
72 |
73 |
74 |
75 | -h --help
76 |
77 |
78 | Print help text to the screen.
79 |
80 |
81 |
82 |
83 | -C --control-port <INTEGER>
84 |
85 |
86 | This comamnd is used to specify the control port to use for
87 | this instance of tgtd. This allows to run multiple instances of
88 | TGTD on a host.
89 |
90 |
91 | TGTADM has a matching argument to control which instance to connect
92 | to.
93 |
94 |
95 |
96 |
97 | --iscsi <...>
98 |
99 |
100 | ISCSI specific options.
101 | See the ISCSI section below for options specific to this frontend.
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | ISCSI options
110 |
111 | These parameters apply only to the iSCSI frontend.
112 |
113 |
114 | portal=<ip-address[:port]>
115 |
116 | This option is used to bind tgtd to a specific ip-address/portal and/or
117 | port. By default tgtd will bind to port 3260 on the wildcard address.
118 | The ip-address part (before the ":") can be missing to designate the
119 | wildcard address with a none-default port.
120 |
121 |
122 | Example: to bind tgtd to a specific address and port
123 |
124 | tgtd --iscsi portal=192.0.2.1:3260
125 |
126 | Example: to bind tgtd to any address but a none-default port
127 |
128 | tgtd --iscsi portal=:3251
129 |
130 |
131 |
132 | nop_interval=<integer>
133 |
134 | This sets the default interval for sending NOP-OUT to probe for
135 | connected initiators.
136 | This parameter only controls the default value for targets.
137 | Individual targets can be controlled using tgtadm.
138 |
139 |
140 | The default value is 0 which means that the feature is disabled
141 | TGTD will not send any NOP-OUT probes.
142 |
143 |
144 | nop_count=<integer>
145 |
146 | This sets the default value for after how many failed probes TGTD
147 | will consider the initiator dead and tear down the session.
148 | This parameter only controls the default value for targets.
149 | Individual targets can be controlled using tgtadm.
150 |
151 |
152 | The default value is 0.
153 |
154 |
155 | Example: send NOP-OUT every 5 seconds and abort the session after
156 | 6 failures.
157 |
158 | tgtd --iscsi portal=192.0.2.1:3260,nop_interval=5,nop_count=6
159 |
160 |
161 |
162 |
163 |
164 |
165 | ENVIRONMENT VARIABLES
166 | TGT_IPC_SOCKET=<path>
167 |
168 | When set tgtd and tgtadm will use the specified path as the
169 | IPC socket instead of the default '/var/run/tgtd/socket.0'
170 |
171 |
172 |
173 |
174 | SEE ALSO
175 |
176 | targets.conf(5), tgtadm(8), tgt-admin(8), tgtimg(8), tgt-setup-lun(8).
177 |
178 |
179 |
180 |
181 | COPYRIGHT/LICENSE
182 |
183 | This program is free software; you can redistribute it and/or modify
184 | it under the terms of the GNU General Public License as published by
185 | the Free Software Foundation; either version 2 of the License, or (at
186 | your option) any later version.
187 |
188 | This program is distributed in the hope that it will be useful, but
189 | WITHOUT ANY WARRANTY; without even the implied warranty of
190 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
191 | General Public License for more details.
192 |
193 | You should have received a copy of the GNU General Public License
194 | along with this program; if not, see http://www.gnu.org/licenses/.
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/doc/tgtimg.8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tgtimg
6 | 8
7 |
8 |
9 |
10 |
11 | tgtimg
12 | Linux SCSI Target Framework Image File Utility
13 |
14 |
15 |
16 |
17 | tgtimg
18 | -o --op <operation>
19 | -Y --device-type <device-type>
20 | -b --barcode <barcode>
21 | -s --size <size>
22 | -t --type <media-type>
23 | -f --file <path>
24 | -T --thin-provisioning
25 |
26 |
27 | tgtimg --help
28 |
29 |
30 |
31 |
32 | DESCRIPTION
33 |
34 | Tgtimg is a utility to create and manage the image files used by the
35 | TGTD device emulation.
36 |
37 |
38 | This command is used to initialize device image files with the additional
39 | metadata, such as barcode, list of blocks, total size, etc that
40 | the TGTD emulation needs.
41 |
42 |
43 |
44 |
45 |
46 | OPTIONS
47 |
48 |
49 |
50 |
51 |
52 | Show a help screen and exit.
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | Operation. Is either new to create a new image file or show to
61 | show the content of an existing image file.
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | This specifies the type of image file.
70 |
71 |
72 |
73 |
74 | Supported device types are :
75 | cd : to create media for a dvd device
76 | disk : to create media for a disk device
77 | tape : to create media for a tape device
78 |
79 |
80 |
81 |
82 |
83 | When creating a new image, this specifies the type of media to
84 | emulate. The available mediatypes depend on the type of the
85 | device.
86 |
87 |
88 |
89 |
90 | Supported media types for cd devices are :
91 | dvd+r : create a blank writeable DVD+R disk
92 |
93 | Supported media types for disk devices are :
94 | disk : create an empty disk
95 |
96 | Supported media types for tape devices are :
97 | data : create a normal data tape
98 | clean : create a cleaning tape
99 | worm : create a worm
100 |
101 |
102 |
103 |
104 |
105 | When creating a new image, this argument specifies the barcode
106 | to use with this image file. Backup application software often
107 | uses barcodes to identify specific tapes. When emulating a VTL,
108 | make sure that all tape images use unique barcodes.
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | When creating a new image, this specifies the size in megabytes
117 | for the virtual tape image.
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | The filename of the image file.
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | This argument makes the allocation of the image format use
134 | thin-provisioning. This means that the file created will be a
135 | sparse file that will allocate blocks from the filesystem on demand.
136 |
137 |
138 | Be careful when using thin-provisioning. If the filesystem
139 | fills up a iSCSI write to a thin-provisioned LUN
140 | can fail. Initiators generally do not handle "out of space" errors
141 | gracefully.
142 |
143 |
144 | Thin-provisioning uses FALLOC_FL_PUNCH_HOLE which is only available
145 | on some linux filesystems. Thin-provisioning can only be used for
146 | DISK images.
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | EXAMPLES
155 |
156 | To create a new 100MByte disk
157 |
158 |
159 | tgtimg --op new --device-type disk --type disk --size 100 --file /data/hd001.raw
160 |
161 |
162 |
163 | To create a new tape image
164 |
165 |
166 | tgtimg --op new --device-type tape --barcode 12345 --size 100 --type data --file /data/tape001.img
167 |
168 |
169 |
170 | To view the content of an existing image
171 |
172 |
173 | tgtimg --op show --device-type tape --file /data/tape001.img
174 |
175 |
176 |
177 | To create a new blank DVD+R image
178 |
179 |
180 | tgtimg --op new --device-type cd --type dvd+r --file /data/dvd001.iso
181 |
182 |
183 |
184 |
185 |
186 | SEE ALSO
187 |
188 | tgtd(8), tgtadm(8), tgt-admin(8), tgt-setup-lun(8).
189 |
190 |
191 |
192 |
193 | REPORTING BUGS
194 |
195 | Report bugs to <stgt@vger.kernel.org>
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/doc/tmf.txt:
--------------------------------------------------------------------------------
1 | The tgt Task Management Functions (TMF) works in the followings:
2 |
3 | - When LLDs queue scsi commands to tgt (scsi_tgt_queue_command), they
4 | need to specify unique 'tag' for each command.
5 |
6 | - LLDs call 'int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *host, int,
7 | u64 tag, struct scsi_lun *lun, void *data)'.
8 |
9 | - int (* tsk_mgmt_response)(u64 data, int result) is added to
10 | scsi_host_template.
11 |
12 | The tag arg in scsi_tgt_queue_command is used only for ABORT_TASK to
13 | identify a single command. Initiators send a command with a unique
14 | tag so LLDs simply call scsi_tgt_queue_command() with it.
15 |
16 | With FCP and iSCSI, tag is 32-bit, however, unfortunately, SRP uses
17 | 64-bit tag. So we need 64-bit for it.
18 |
19 | When an initiator sends a task management request, the LLD calls
20 | scsi_tgt_tsk_mgmt_request. the LLD can use whatever it wants for the
21 | data arg. The data arg is used later as the arg in the
22 | tsk_mgmt_response callback.
23 |
24 | tgt core just sends the task management request to user space
25 | (by using TGT_KEVENT_TSK_MGMT_REQ).
26 |
27 | In the case of ABORT_TASK, tgtd finds a single command to abort and
28 | sends TGT_UEVENT_CMD_RSP and TGT_UEVENT_TSK_MGMT_RSP events.
29 |
30 | tgt core calls eh_abort_handler for TGT_UEVENT_CMD_RSP and then
31 | tsk_mgmt_response for TGT_UEVENT_TSK_MGMT_RSP.
32 |
33 | If tgtd fails to find a command to abort, it sends only
34 | TGT_UEVENT_TSK_MGMT_RSP event (no TGT_UEVENT_CMD_RSP event).
35 |
36 | In the case of the rests task management functions (like
37 | ABORT_TASK_SET), tgt needs to abort multiple commands. Thus, tgtd
38 | finds multiple commands to abort and sends multiple TGT_UEVENT_CMD_RSP
39 | events and a single TGT_UEVENT_TSK_MGMT_RSP event. tgt core calls
40 | eh_abort_handler multiple times and tsk_mgmt_response once.
41 |
42 | eh_abort_handler enables LLDs to safely free resource related with a
43 | command to abort.
44 |
45 | Note that when tgtd finds that a TGT_KEVENT_TSK_MGMT_REQ event tries
46 | to abort commands between in TGT_UEVENT_CMD_RSP and
47 | TGT_KEVENT_CMD_DONE states (that is, tgt calls something like
48 | bio_map_user for the commands), tgtd gives up. After all, we cannot
49 | abort such commands. For example, possibly, The commands already touch
50 | page cache. In this case, tgtd waits for the completion of the commands
51 | (TGT_KEVENT_CMD_DONE) and sends TGT_UEVENT_TSK_MGMT_RSP event with an
52 | appropriate result value.
53 |
--------------------------------------------------------------------------------
/images/fio_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opencurve/curve-tgt/c6475beb51b9f5a2e4047730a40be0db26f09a27/images/fio_old.png
--------------------------------------------------------------------------------
/images/fio_opt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opencurve/curve-tgt/c6475beb51b9f5a2e4047730a40be0db26f09a27/images/fio_opt.png
--------------------------------------------------------------------------------
/scripts/Makefile:
--------------------------------------------------------------------------------
1 | sbindir ?= $(PREFIX)/sbin
2 |
3 | SCRIPTS += tgt-setup-lun tgt-admin
4 |
5 | .PHONY: all
6 | all:
7 |
8 | .PHONY: install
9 | install: $(SCRIPTS)
10 | install -d -m 755 $(DESTDIR)$(sbindir)
11 | install -m 755 $(SCRIPTS) $(DESTDIR)$(sbindir)
12 |
13 | .PHONY: clean
14 | clean:
15 |
16 |
--------------------------------------------------------------------------------
/scripts/build-pkg.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright (C) 2012 Roi Dayan
4 | #
5 |
6 | TARGET=$1
7 |
8 | usage() {
9 | echo "Usage: `basename $0` [rpm|deb]"
10 | exit 1
11 | }
12 |
13 | if [ "$TARGET" != "rpm" -a "$TARGET" != "deb" ]; then
14 | usage
15 | fi
16 |
17 | DIR=$(cd `dirname $0`; pwd)
18 | BASE=`cd $DIR/.. ; pwd`
19 | _TOP="$BASE/pkg"
20 | SPEC="tgtd.spec"
21 | LOG=/tmp/`basename $0`-$$.log
22 |
23 | # get branch name
24 | branch=`git branch | grep '^*' | sed 's/^..\(.*\)/\1/'`
25 | # get version tag
26 | version=`git describe --tags --abbrev=0 | sed "s/^v//g"`
27 | # release is number of commits since the version tag
28 | release=`git describe --tags | cut -d- -f2 | tr - _`
29 |
30 | if [ "$version" = "$release" ]; then
31 | # no commits and release can't be empty
32 | release=0
33 | fi
34 |
35 | if [ "$branch" != "master" ]; then
36 | # if not under master branch include hash tag
37 | hash=`git rev-parse HEAD | cut -c 1-6`
38 | release="$release.$hash"
39 | fi
40 |
41 | echo "Building version: $version-$release"
42 |
43 |
44 | cp_src() {
45 | local dest=$1
46 | cp -a conf $dest
47 | cp -a doc $dest
48 | cp -a scripts $dest
49 | cp -a usr $dest
50 | cp -a README $dest
51 | cp -a Makefile $dest
52 | }
53 |
54 | check() {
55 | local rc=$?
56 | local msg="$1"
57 | if (( rc )) ; then
58 | echo $msg
59 | exit 1
60 | fi
61 | }
62 |
63 | build_rpm() {
64 | name=scsi-target-utils-$version-$release
65 | TARBALL=$name.tgz
66 | SRPM=$_TOP/SRPMS/$name.src.rpm
67 |
68 | echo "Creating rpm build dirs under $_TOP"
69 | mkdir -p $_TOP/{RPMS,SRPMS,SOURCES,BUILD,SPECS,tmp}
70 | mkdir -p $_TOP/tmp/$name
71 |
72 | cp_src $_TOP/tmp/$name
73 |
74 | echo "Creating tgz $TARBALL"
75 | tar -czf $_TOP/SOURCES/$TARBALL -C $_TOP/tmp $name
76 |
77 | echo "Creating rpm"
78 | sed -r "s/^Version:(\s*).*/Version:\1$version/;s/^Release:(\s*).*/Release:\1$release/" scripts/$SPEC > $_TOP/SPECS/$SPEC
79 | rpmbuild -bs --define="_topdir $_TOP" $_TOP/SPECS/$SPEC
80 | check "Failed to create source rpm."
81 |
82 | rpmbuild -bb --define="_topdir $_TOP" $_TOP/SPECS/$SPEC > $LOG 2>&1
83 | check "Failed to build rpm. LOG: $LOG"
84 | # display created rpm files
85 | grep ^Wrote $LOG
86 |
87 | rm -fr $LOG
88 | }
89 |
90 | build_deb() {
91 | if ! which debuild >/dev/null 2>&1 ; then
92 | echo "Missing debuild. Please install devscripts package."
93 | exit 1
94 | fi
95 | name=tgt_$version
96 | TARBALL=$name.orig.tar.gz
97 |
98 | echo "Building under $_TOP/$name"
99 | mkdir -p $_TOP/$name
100 | cp_src $_TOP/$name
101 | tar -czf $_TOP/$TARBALL -C $_TOP $name
102 |
103 | mkdir -p $_TOP/$name/debian
104 | cp -a scripts/deb/* $_TOP/$name/debian
105 | cd $_TOP/$name
106 | sed -i -r "s/^tgt \(([0-9.-]+)\) (.*)/tgt \($version-$release\) \2/" debian/changelog
107 | debuild -uc -us
108 | check "Failed building deb package."
109 | cd ../..
110 | ls -l $_TOP/$name*.deb
111 | }
112 |
113 | cd $BASE
114 | build_$TARGET
115 | echo "Done."
116 |
--------------------------------------------------------------------------------
/scripts/checkarch.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | arch=`gcc -dumpmachine`
3 |
4 | case $arch in
5 | `echo $arch | grep x86_64`)
6 | echo -m64
7 | ;;
8 | `echo $arch | grep "i[3-6]86"`)
9 | echo -m32
10 | ;;
11 | *)
12 | echo '
13 | Failed to parse your architecture.
14 | Please run
15 |
16 | $ make check32
17 |
18 | or
19 |
20 | $ make check64
21 |
22 | manually.
23 | '
24 | exit 1
25 | ;;
26 | esac
27 |
--------------------------------------------------------------------------------
/scripts/deb/changelog:
--------------------------------------------------------------------------------
1 | tgt (1.0.37-1) UNRELEASED; urgency=low
2 | * Non-maintainer upload.
3 | *
4 | * Initial release. (Closes: #XXXXXX)
5 |
6 | -- Roi Dayan Thu, 18 Jul 2013 09:31:00 +0300
7 |
--------------------------------------------------------------------------------
/scripts/deb/compat:
--------------------------------------------------------------------------------
1 | 8
2 |
--------------------------------------------------------------------------------
/scripts/deb/control:
--------------------------------------------------------------------------------
1 | Source: tgt
2 | Maintainer: FUJITA Tomonori
3 | Section: net
4 | Priority: optional
5 | Standards-Version: 3.9.1
6 | Build-Depends: debhelper (>= 8), dpkg-dev (>= 1.13.19), bash-completion,
7 | librdmacm-dev, libibverbs-dev, xsltproc, docbook-xsl
8 | Homepage: http://stgt.berlios.de/
9 |
10 | Package: tgt
11 | Architecture: any
12 | Depends: ${shlibs:Depends}, ${misc:Depends}, librdmacm1, libconfig-general-perl
13 | Description: The SCSI target daemon and utility programs
14 | The SCSI target package contains the daemon and tools to setup a SCSI targets.
15 | Currently, software iSCSI targets are supported.
16 |
--------------------------------------------------------------------------------
/scripts/deb/copyright:
--------------------------------------------------------------------------------
1 | License:
2 |
3 | This program is free software; you can redistribute it and/or modify
4 | it under the terms of the GNU General Public License as published by
5 | the Free Software Foundation; either version 2 of the License, or (at
6 | your option) any later version.
7 |
8 | This program is distributed in the hope that it will be useful, but
9 | WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 | General Public License for more details.
12 |
13 | You should have received a copy of the GNU General Public License
14 | along with this program; if not, see http://www.gnu.org/licenses/.
15 |
--------------------------------------------------------------------------------
/scripts/deb/init:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is an example init.d script for stopping/starting/reconfiguring tgtd.
3 |
4 | ### BEGIN INIT INFO
5 | # Provides: tgtd
6 | # Required-Start: $network
7 | # Required-Stop: $network
8 | # Default-Start: 2 3 4 5
9 | # Default-Stop: 0 1 6
10 | # Short-Description: Starts and stops the generic storage target daemon
11 | # Description: tgtd provides the SCSI and software transport target state machine daemon.
12 | ### END INIT INFO
13 |
14 | TGTD_CONFIG=/etc/tgt/targets.conf
15 |
16 | TASK=$1
17 |
18 | start()
19 | {
20 | echo "Starting target framework daemon"
21 | # Start tgtd first.
22 | tgtd &>/dev/null
23 | RETVAL=$?
24 | if [ "$RETVAL" -ne 0 ] ; then
25 | echo "Could not start tgtd (is tgtd already running?)"
26 | exit 1
27 | fi
28 | sleep 1
29 | # Put tgtd into "offline" state until all the targets are configured.
30 | # We don't want initiators to (re)connect and fail the connection
31 | # if it's not ready.
32 | tgtadm --op update --mode sys --name State -v offline
33 | # Configure the targets.
34 | tgt-admin -e -c $TGTD_CONFIG
35 | # Put tgtd into "ready" state.
36 | tgtadm --op update --mode sys --name State -v ready
37 | }
38 |
39 | stop()
40 | {
41 | if [ -n "$RUNLEVEL" ] && [ "$RUNLEVEL" -eq 0 -o "$RUNLEVEL" -eq 6 ] ; then
42 | forcedstop
43 | fi
44 | echo "Stopping target framework daemon"
45 | # Remove all targets. It only removes targets which are not in use.
46 | tgt-admin --update ALL -c /dev/null &>/dev/null
47 | # tgtd will exit if all targets were removed
48 | tgtadm --op delete --mode system &>/dev/null
49 | RETVAL=$?
50 | if [ "$RETVAL" -eq 107 ] ; then
51 | echo "tgtd is not running"
52 | [ "$TASK" != "restart" ] && exit 1
53 | elif [ "$RETVAL" -ne 0 ] ; then
54 | echo "Some initiators are still connected - could not stop tgtd"
55 | exit 2
56 | fi
57 | echo -n
58 | }
59 |
60 | forcedstop()
61 | {
62 | # NOTE: Forced shutdown of the iscsi target may cause data corruption
63 | # for initiators that are connected.
64 | echo "Force-stopping target framework daemon"
65 | # Offline everything first. May be needed if we're rebooting, but
66 | # expect the initiators to reconnect cleanly when we boot again
67 | # (i.e. we don't want them to reconnect to a tgtd which is still
68 | # working, but the target is gone).
69 | tgtadm --op update --mode sys --name State -v offline &>/dev/null
70 | RETVAL=$?
71 | if [ "$RETVAL" -eq 107 ] ; then
72 | echo "tgtd is not running"
73 | [ "$TASK" != "restart" ] && exit 1
74 | else
75 | tgt-admin --offline ALL
76 | # Remove all targets, even if they are still in use.
77 | tgt-admin --update ALL -c /dev/null -f
78 | # It will shut down tgtd only after all targets were removed.
79 | tgtadm --op delete --mode system
80 | RETVAL=$?
81 | if [ "$RETVAL" -ne 0 ] ; then
82 | echo "Failed to shutdown tgtd"
83 | exit 1
84 | fi
85 | fi
86 | echo -n
87 | }
88 |
89 | reload()
90 | {
91 | echo "Updating target framework daemon configuration"
92 | # Update configuration for targets. Only targets which
93 | # are not in use will be updated.
94 | tgt-admin --update ALL -c $TGTD_CONFIG &>/dev/null
95 | RETVAL=$?
96 | if [ "$RETVAL" -eq 107 ] ; then
97 | echo "tgtd is not running"
98 | exit 1
99 | fi
100 | }
101 |
102 | forcedreload()
103 | {
104 | echo "Force-updating target framework daemon configuration"
105 | # Update configuration for targets, even those in use.
106 | tgt-admin --update ALL -f -c $TGTD_CONFIG &>/dev/null
107 | RETVAL=$?
108 | if [ "$RETVAL" -eq 107 ] ; then
109 | echo "tgtd is not running"
110 | exit 1
111 | fi
112 | }
113 |
114 | status()
115 | {
116 | # Don't name this script "tgtd"...
117 | TGTD_PROC=$(ps -C tgtd | grep -c tgtd)
118 | if [ "$TGTD_PROC" -eq 2 ] ; then
119 | echo "tgtd is running. Run 'tgt-admin -s' to see detailed target info."
120 | else
121 | echo "tgtd is NOT running."
122 | fi
123 | }
124 |
125 | case $1 in
126 | start)
127 | start
128 | ;;
129 | stop)
130 | stop
131 | ;;
132 | forcedstop)
133 | forcedstop
134 | ;;
135 | restart)
136 | TASK=restart
137 | stop && start
138 | ;;
139 | forcedrestart)
140 | TASK=restart
141 | forcedstop && start
142 | ;;
143 | reload)
144 | reload
145 | ;;
146 | force-reload)
147 | forcedreload
148 | ;;
149 | status)
150 | status
151 | ;;
152 | *)
153 | echo "Usage: $0 {start|stop|forcedstop|restart|forcedrestart|reload|forcedreload|status}"
154 | exit 2
155 | ;;
156 | esac
157 |
158 |
--------------------------------------------------------------------------------
/scripts/deb/patches/0001-Use-local-docbook-for-generating-docs.patch:
--------------------------------------------------------------------------------
1 | From 1edc4f6428dfdbd86a2d47177148e12fd617c3b1 Mon Sep 17 00:00:00 2001
2 | From: Roi Dayan
3 | Date: Thu, 10 Apr 2014 17:36:45 +0300
4 | Subject: [PATCH] Use local docbook for generating docs
5 |
6 | Signed-off-by: Roi Dayan
7 | ---
8 | doc/Makefile | 24 ++++++++++++------------
9 | 1 file changed, 12 insertions(+), 12 deletions(-)
10 |
11 | diff --git a/doc/Makefile b/doc/Makefile
12 | index 0516dc8..e56695d 100644
13 | --- a/doc/Makefile
14 | +++ b/doc/Makefile
15 | @@ -34,40 +34,40 @@ clean:
16 | -rm -f manpages htmlpages
17 |
18 | manpages/tgtd.8: tgtd.8.xml
19 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
20 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
21 |
22 | htmlpages/tgtd.8.html: tgtd.8.xml
23 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
24 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
25 |
26 | manpages/tgtadm.8: tgtadm.8.xml
27 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
28 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
29 |
30 | htmlpages/tgtadm.8.html: tgtadm.8.xml
31 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
32 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
33 |
34 | manpages/tgt-admin.8: tgt-admin.8.xml
35 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
36 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
37 |
38 | htmlpages/tgt-admin.8.html: tgt-admin.8.xml
39 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
40 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
41 |
42 | manpages/tgtimg.8: tgtimg.8.xml
43 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
44 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
45 |
46 | htmlpages/tgtimg.8.html: tgtimg.8.xml
47 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
48 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
49 |
50 | manpages/targets.conf.5: targets.conf.5.xml
51 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
52 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
53 |
54 | htmlpages/targets.conf.5.html: targets.conf.5.xml
55 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
56 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
57 |
58 | manpages/tgt-setup-lun.8: tgt-setup-lun.8.xml
59 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
60 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl $<
61 |
62 | htmlpages/tgt-setup-lun.8.html: tgt-setup-lun.8.xml
63 | - -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
64 | + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl $<
65 |
66 | xmlman: $(XMLMAN)
67 |
68 | --
69 | 1.8.1.2
70 |
71 |
--------------------------------------------------------------------------------
/scripts/deb/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | DEB_MAKE_ENVVARS += ISCSI_RDMA=1
4 |
5 | %:
6 | dh $@ --with bash-completion --with systemd
7 |
8 | override_dh_auto_build:
9 | dh_auto_build -- $(DEB_MAKE_ENVVARS)
10 |
11 | override_dh_auto_install:
12 | dh_auto_install -- $(DEB_MAKE_ENVVARS)
13 |
--------------------------------------------------------------------------------
/scripts/deb/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (quilt)
2 |
--------------------------------------------------------------------------------
/scripts/deb/tgt.bash-completion:
--------------------------------------------------------------------------------
1 | scripts/tgt.bashcomp.sh tgt
--------------------------------------------------------------------------------
/scripts/deb/tgt.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=(i)SCSI target daemon
3 | Documentation=man:tgtd(8)
4 | After=network.target
5 |
6 | [Service]
7 | Type=forking
8 | TasksMax=infinity
9 | ExecStart=/usr/sbin/tgtd
10 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
11 | ExecStartPost=/usr/sbin/tgt-admin -e -c /etc/tgt/targets.conf
12 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v ready
13 |
14 | ExecStop=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
15 | ExecStop=/usr/sbin/tgt-admin --offline ALL
16 | ExecStop=/usr/sbin/tgt-admin --update ALL -c /dev/null -f
17 | ExecStop=/usr/sbin/tgtadm --op delete --mode system
18 |
19 | ExecReload=/usr/sbin/tgt-admin --update ALL -c /etc/tgt/targets.conf
20 | Restart=on-failure
21 |
22 | [Install]
23 | WantedBy=multi-user.target
24 |
--------------------------------------------------------------------------------
/scripts/initd.sample:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is an example init.d script for stopping/starting/reconfiguring tgtd.
3 |
4 | # chkconfig: 345 20 80
5 | #
6 | ### BEGIN INIT INFO
7 | # Provides: tgtd
8 | # Required-Start: $network
9 | # Required-Stop: $network
10 | # Default-Start: 3 4 5
11 | # Default-Stop: 0 1 2 6
12 | # Short-Description: Starts and stops the generic storage target daemon
13 | # Description: tgtd provides the SCSI and software transport target state machine daemon.
14 | ### END INIT INFO
15 |
16 | TGTD_CONFIG=/etc/tgt/targets.conf
17 |
18 | TASK=$1
19 |
20 | start()
21 | {
22 | echo "Starting target framework daemon"
23 | # Start tgtd first.
24 | tgtd &>/dev/null
25 | RETVAL=$?
26 | if [ "$RETVAL" -ne 0 ] ; then
27 | echo "Could not start tgtd (is tgtd already running?)"
28 | exit 1
29 | fi
30 | # Put tgtd into "offline" state until all the targets are configured.
31 | # We don't want initiators to (re)connect and fail the connection
32 | # if it's not ready.
33 | tgtadm --op update --mode sys --name State -v offline
34 | # Configure the targets.
35 | tgt-admin -e -c $TGTD_CONFIG
36 | # Put tgtd into "ready" state.
37 | tgtadm --op update --mode sys --name State -v ready
38 | }
39 |
40 | stop()
41 | {
42 | if [ "$RUNLEVEL" == 0 -o "$RUNLEVEL" == 6 ] ; then
43 | forcedstop
44 | fi
45 | echo "Stopping target framework daemon"
46 | # Remove all targets. It only removes targets which are not in use.
47 | tgt-admin --update ALL -c /dev/null &>/dev/null
48 | # tgtd will exit if all targets were removed
49 | tgtadm --op delete --mode system &>/dev/null
50 | RETVAL=$?
51 | if [ "$RETVAL" -eq 107 ] ; then
52 | echo "tgtd is not running"
53 | [ "$TASK" != "restart" ] && exit 1
54 | elif [ "$RETVAL" -ne 0 ] ; then
55 | echo "Some initiators are still connected - could not stop tgtd"
56 | exit 2
57 | fi
58 | echo -n
59 | }
60 |
61 | forcedstop()
62 | {
63 | # NOTE: Forced shutdown of the iscsi target may cause data corruption
64 | # for initiators that are connected.
65 | echo "Force-stopping target framework daemon"
66 | # Offline everything first. May be needed if we're rebooting, but
67 | # expect the initiators to reconnect cleanly when we boot again
68 | # (i.e. we don't want them to reconnect to a tgtd which is still
69 | # working, but the target is gone).
70 | tgtadm --op update --mode sys --name State -v offline &>/dev/null
71 | RETVAL=$?
72 | if [ "$RETVAL" -eq 107 ] ; then
73 | echo "tgtd is not running"
74 | [ "$TASK" != "restart" ] && exit 1
75 | else
76 | tgt-admin --offline ALL
77 | # Remove all targets, even if they are still in use.
78 | tgt-admin --update ALL -c /dev/null -f
79 | # It will shut down tgtd only after all targets were removed.
80 | tgtadm --op delete --mode system
81 | RETVAL=$?
82 | if [ "$RETVAL" -ne 0 ] ; then
83 | echo "Failed to shutdown tgtd"
84 | exit 1
85 | fi
86 | fi
87 | echo -n
88 | }
89 |
90 | reload()
91 | {
92 | echo "Updating target framework daemon configuration"
93 | # Update configuration for targets. Only targets which
94 | # are not in use will be updated.
95 | tgt-admin --update ALL -c $TGTD_CONFIG &>/dev/null
96 | RETVAL=$?
97 | if [ "$RETVAL" -eq 107 ] ; then
98 | echo "tgtd is not running"
99 | exit 1
100 | fi
101 | }
102 |
103 | forcedreload()
104 | {
105 | echo "Force-updating target framework daemon configuration"
106 | # Update configuration for targets, even those in use.
107 | tgt-admin --update ALL -f -c $TGTD_CONFIG &>/dev/null
108 | RETVAL=$?
109 | if [ "$RETVAL" -eq 107 ] ; then
110 | echo "tgtd is not running"
111 | exit 1
112 | fi
113 | }
114 |
115 | status()
116 | {
117 | # Don't name this script "tgtd"...
118 | TGTD_PROC=$(ps -C tgtd | grep -c tgtd)
119 | if [ "$TGTD_PROC" -eq 2 ] ; then
120 | echo "tgtd is running. Run 'tgt-admin -s' to see detailed target info."
121 | else
122 | echo "tgtd is NOT running."
123 | fi
124 | }
125 |
126 | case $1 in
127 | start)
128 | start
129 | ;;
130 | stop)
131 | stop
132 | ;;
133 | forcedstop)
134 | forcedstop
135 | ;;
136 | restart)
137 | TASK=restart
138 | stop && start
139 | ;;
140 | forcedrestart)
141 | TASK=restart
142 | forcedstop && start
143 | ;;
144 | reload)
145 | reload
146 | ;;
147 | forcedreload)
148 | forcedreload
149 | ;;
150 | status)
151 | status
152 | ;;
153 | *)
154 | echo "Usage: $0 {start|stop|forcedstop|restart|forcedrestart|reload|forcedreload|status}"
155 | exit 2
156 | ;;
157 | esac
158 |
159 |
--------------------------------------------------------------------------------
/scripts/tgt.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=(i)SCSI target daemon
3 | Documentation=man:tgtd(8)
4 | After=network.target
5 |
6 | [Service]
7 | Type=forking
8 | TasksMax=infinity
9 | ExecStart=/usr/sbin/tgtd
10 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
11 | ExecStartPost=/usr/sbin/tgt-admin -e -c /etc/tgt/targets.conf
12 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v ready
13 |
14 | ExecStop=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
15 | ExecStop=/usr/sbin/tgt-admin --offline ALL
16 | ExecStop=/usr/sbin/tgt-admin --update ALL -c /dev/null -f
17 | ExecStop=/usr/sbin/tgtadm --op delete --mode system
18 |
19 | ExecReload=/usr/sbin/tgt-admin --update ALL -c /etc/tgt/targets.conf
20 | Restart=on-failure
21 |
22 | [Install]
23 | WantedBy=multi-user.target
24 |
--------------------------------------------------------------------------------
/scripts/tgtd.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=iSCSI target framework daemon
3 | Documentation=man:tgtd(8)
4 | After=network.target
5 |
6 | # On systems without virtual consoles, don't start any getty. Note
7 | # that serial gettys are covered by serial-getty@.service, not this
8 | # unit.
9 | ConditionPathExists=/etc/tgt/targets.conf
10 |
11 | [Service]
12 | Type=forking
13 | Environment=TGTD_CONFIG=/etc/tgt/targets.conf
14 |
15 | ExecStart=/usr/sbin/tgtd
16 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
17 | ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v ready
18 | ExecStartPost=/usr/sbin/tgt-admin -e -c ${TGTD_CONFIG}
19 |
20 | ExecReload=/usr/sbin/tgt-admin --update ALL -f -c ${TGTD_CONFIG}
21 |
22 | ExecStop=/usr/sbin/tgtadm --op update --mode sys --name State -v offline
23 | ExecStop=/usr/sbin/tgt-admin --offline ALL
24 | ExecStop=/usr/sbin/tgt-admin --update ALL -c /dev/null -f
25 | ExecStop=/usr/sbin/tgtadm --op delete --mode system
26 |
27 | # Exit code: 107 tgtd not running
28 |
29 |
30 | [Install]
31 | WantedBy=multi-user.target
32 |
--------------------------------------------------------------------------------
/scripts/tgtd.spec:
--------------------------------------------------------------------------------
1 | Name: scsi-target-utils
2 | Version: 1.0.24
3 | Release: 2%{?dist}
4 | Summary: The SCSI target daemon and utility programs
5 | Packager: Roi Dayan
6 | Group: System Environment/Daemons
7 | License: GPLv2
8 | URL: http://stgt.sourceforge.net/
9 | Source0: %{name}-%{version}-%{release}.tgz
10 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
11 | BuildRequires: pkgconfig libibverbs-devel librdmacm-devel libxslt libaio-devel
12 | %if %{defined suse_version}
13 | BuildRequires: docbook-xsl-stylesheets
14 | Requires: aaa_base
15 | %else
16 | BuildRequires: docbook-style-xsl
17 | Requires(post): chkconfig
18 | Requires(preun): chkconfig
19 | Requires(preun): initscripts
20 | %endif
21 | Requires: lsof sg3_utils
22 | ExcludeArch: s390 s390x
23 |
24 | %description
25 | The SCSI target package contains the daemon and tools to setup a SCSI targets.
26 | Currently, software iSCSI targets are supported.
27 |
28 |
29 | %prep
30 | %setup -q -n %{name}-%{version}-%{release}
31 |
32 |
33 | %build
34 | %{__make} %{?_smp_mflags} ISCSI_RDMA=1
35 |
36 |
37 | %install
38 | %{__rm} -rf %{buildroot}
39 | %{__install} -d %{buildroot}%{_sbindir}
40 | %{__install} -d %{buildroot}%{_mandir}/man5
41 | %{__install} -d %{buildroot}%{_mandir}/man8
42 | %{__install} -d %{buildroot}%{_initrddir}
43 | %{__install} -d %{buildroot}/etc/bash_completion.d
44 | %{__install} -d %{buildroot}/etc/tgt
45 | %{__install} -d %{buildroot}/lib/systemd/system
46 |
47 | %{__install} -p -m 0755 scripts/tgt-setup-lun %{buildroot}%{_sbindir}
48 | %{__install} -p -m 0755 scripts/initd.sample %{buildroot}%{_initrddir}/tgtd
49 | %{__install} -p -m 0755 scripts/tgt-admin %{buildroot}/%{_sbindir}/tgt-admin
50 | %{__install} -p -m 0644 scripts/tgt.bashcomp.sh %{buildroot}/etc/bash_completion.d/tgt
51 | %{__install} -p -m 0644 doc/manpages/targets.conf.5 %{buildroot}/%{_mandir}/man5
52 | %{__install} -p -m 0644 doc/manpages/tgtadm.8 %{buildroot}/%{_mandir}/man8
53 | %{__install} -p -m 0644 doc/manpages/tgt-admin.8 %{buildroot}/%{_mandir}/man8
54 | %{__install} -p -m 0644 doc/manpages/tgt-setup-lun.8 %{buildroot}/%{_mandir}/man8
55 | %{__install} -p -m 0644 doc/manpages/tgtimg.8 %{buildroot}/%{_mandir}/man8
56 | %{__install} -p -m 0600 conf/targets.conf %{buildroot}/etc/tgt
57 | %{__install} -p -m 0644 scripts/tgt.service %{buildroot}/lib/systemd/system/
58 |
59 | pushd usr
60 | %{__make} install DESTDIR=%{buildroot} sbindir=%{_sbindir}
61 |
62 |
63 | %post
64 | /sbin/chkconfig --add tgtd
65 |
66 | %postun
67 | if [ "$1" = "1" ] ; then
68 | /sbin/service tgtd condrestart > /dev/null 2>&1 || :
69 | fi
70 |
71 | %preun
72 | if [ "$1" = "0" ] ; then
73 | /sbin/chkconfig tgtd stop > /dev/null 2>&1
74 | /sbin/chkconfig --del tgtd
75 | fi
76 |
77 |
78 | %clean
79 | %{__rm} -rf %{buildroot}
80 |
81 |
82 | %files
83 | %defattr(-, root, root, -)
84 | %doc README doc/README.iscsi doc/README.iser doc/README.lu_configuration doc/README.mmc
85 | %{_sbindir}/tgtd
86 | %{_sbindir}/tgtadm
87 | %{_sbindir}/tgt-setup-lun
88 | %{_sbindir}/tgt-admin
89 | %{_sbindir}/tgtimg
90 | %{_mandir}/man5/*
91 | %{_mandir}/man8/*
92 | %{_initrddir}/tgtd
93 | /etc/bash_completion.d/tgt
94 | /lib/systemd/system/tgt.service
95 | %attr(0600,root,root) %config(noreplace) /etc/tgt/targets.conf
96 |
--------------------------------------------------------------------------------
/usr/Makefile:
--------------------------------------------------------------------------------
1 | sbindir ?= $(PREFIX)/sbin
2 | libdir ?= $(PREFIX)/lib/tgt
3 |
4 | ifneq ($(shell test -e /usr/include/linux/signalfd.h && echo 1),)
5 | CFLAGS += -DUSE_SIGNALFD
6 | endif
7 |
8 | ifneq ($(shell test -n $(shell find /usr/include -name "timerfd.h" | head -n1) && echo 1),)
9 | CFLAGS += -DUSE_TIMERFD
10 | endif
11 |
12 | TGTD_OBJS += $(addprefix iscsi/, conn.o param.o session.o \
13 | iscsid.o target.o chap.o sha1.o md5.o transport.o iscsi_tcp.o \
14 | isns.o)
15 |
16 | CURVE_LIBS = -lcbd -lcurve_client -lcurve_common -lcurve_auth -lcurve_concurrent \
17 | -lnameserver2_proto -ltopology_proto -lchunkserver-protos -lbrpc -lbutil -lbvar \
18 | -lbthread -lcc_brpc_internal_proto -ljson2pb -lmcpack2pb -lcc_brpc_idl_options_proto \
19 | -lcommon_proto \
20 | -lprotobuf -lprotobuf_lite -lrt -lssl -lcrypto -ldl -lz -lpthread -lleveldb -lgflags -lglog
21 |
22 | ifneq ($(CURVE_CBD),)
23 | MODULES += bs_curve.so
24 | endif
25 |
26 | ifneq ($(CEPH_RBD),)
27 | MODULES += bs_rbd.so
28 | endif
29 |
30 | ifneq ($(GLFS_BD),)
31 | MODULES += bs_glfs.so
32 | endif
33 |
34 | ifneq ($(SD_NOTIFY),)
35 | CFLAGS += -DUSE_SYSTEMD
36 | endif
37 |
38 | ifneq ($(shell test -e /usr/include/sys/eventfd.h && test -e /usr/include/libaio.h && echo 1),)
39 | CFLAGS += -DUSE_EVENTFD
40 | TGTD_OBJS += bs_aio.o
41 | LIBS += -laio
42 | endif
43 |
44 | ifneq ($(ISCSI_RDMA),)
45 | TGTD_OBJS += iscsi/iser.o iscsi/iser_text.o
46 | LIBS += -libverbs -lrdmacm
47 | endif
48 |
49 | INCLUDES += -I.
50 |
51 | CFLAGS += -D_GNU_SOURCE
52 | CFLAGS += $(INCLUDES)
53 | ifneq ($(DEBUG),)
54 | CFLAGS += -g -O0 -ggdb -rdynamic
55 | else
56 | CFLAGS += -g -O2 -fno-strict-aliasing
57 | endif
58 | CFLAGS += -Wall -Wstrict-prototypes -Werror -fPIC
59 | CFLAGS += -DTGT_VERSION=\"$(VERSION)$(EXTRAVERSION)\"
60 | CFLAGS += -DBSDIR=\"$(DESTDIR)$(libdir)/backing-store\"
61 |
62 | LIBS += -lpthread -ldl
63 |
64 | ifneq ($(SD_NOTIFY),)
65 | LIBS += -lsystemd
66 | endif
67 |
68 | PROGRAMS += tgtd tgtadm tgtimg
69 | TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \
70 | concat_buf.o parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o \
71 | ssc.o libssc.o bs_rdwr.o bs_ssc.o mutex.o \
72 | bs_null.o bs_sg.o bs.o libcrc32c.o bs_sheepdog.o
73 |
74 | TGTD_DEP = $(TGTD_OBJS:.o=.d)
75 |
76 | LDFLAGS = -Wl,-E,-rpath=$(libdir)
77 |
78 | .PHONY:all
79 | all: $(PROGRAMS) $(MODULES)
80 |
81 | tgtd: $(TGTD_OBJS)
82 | echo $(CC) $^ -o $@ $(LIBS)
83 | $(CC) $^ -o $@ $(LDFLAGS) $(LIBS)
84 |
85 | -include $(TGTD_DEP)
86 |
87 | TGTADM_OBJS = tgtadm.o concat_buf.o
88 | TGTADM_DEP = $(TGTADM_OBJS:.o=.d)
89 |
90 | tgtadm: $(TGTADM_OBJS)
91 | $(CC) $^ -o $@
92 |
93 | -include $(TGTADM_DEP)
94 |
95 | TGTIMG_OBJS = tgtimg.o libssc.o libcrc32c.o
96 | TGTIMG_DEP = $(TGTIMG_OBJS:.o=.d)
97 |
98 | tgtimg: $(TGTIMG_OBJS)
99 | $(CC) $^ -o $@
100 |
101 | -include $(TGTIMG_DEP)
102 |
103 | %.o: %.c
104 | $(CC) -c $(CFLAGS) $*.c -o $*.o
105 | @$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c
106 |
107 | %.so: %.c
108 | $(CC) -shared $(CFLAGS) $*.c -o $*.so
109 |
110 | bs_rbd.so: bs_rbd.c
111 | $(CC) -shared $(CFLAGS) bs_rbd.c -o bs_rbd.so -lrados -lrbd
112 |
113 | bs_curve.so: bs_curve.cc
114 | $(CXX) -shared $(CFLAGS) bs_curve.cc -o bs_curve.so -isystem . -Wl,-rpath=/usr/lib/curve -L/usr/lib/curve $(CURVE_LIBS) -lpthread
115 |
116 | bs_glfs.so: bs_glfs.c
117 | $(CC) -I/usr/include/glusterfs/api -shared $(CFLAGS) bs_glfs.c -o bs_glfs.so -lgfapi
118 |
119 | .PHONY: install
120 | install: $(PROGRAMS) $(MODULES)
121 | install -d -m 755 $(DESTDIR)$(sbindir)
122 | install -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir)
123 | ifneq ($(MODULES),)
124 | install -d -m 755 $(DESTDIR)$(libdir)/backing-store
125 | install -m 755 $(MODULES) $(DESTDIR)$(libdir)/backing-store
126 | endif
127 |
128 | .PHONY: clean
129 | clean:
130 | rm -f *.[od] *.so $(PROGRAMS) iscsi/*.[od]
131 |
--------------------------------------------------------------------------------
/usr/be_byteshift.h:
--------------------------------------------------------------------------------
1 | #ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H
2 | #define _LINUX_UNALIGNED_BE_BYTESHIFT_H
3 |
4 | static inline uint16_t __get_unaligned_be16(const uint8_t *p)
5 | {
6 | return p[0] << 8 | p[1];
7 | }
8 |
9 | static inline uint32_t __get_unaligned_be32(const uint8_t *p)
10 | {
11 | return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
12 | }
13 |
14 | static inline uint64_t __get_unaligned_be64(const uint8_t *p)
15 | {
16 | return (uint64_t)__get_unaligned_be32(p) << 32 |
17 | __get_unaligned_be32(p + 4);
18 | }
19 |
20 | static inline void __put_unaligned_be16(uint16_t val, uint8_t *p)
21 | {
22 | *p++ = val >> 8;
23 | *p++ = val;
24 | }
25 |
26 | static inline void __put_unaligned_be32(uint32_t val, uint8_t *p)
27 | {
28 | __put_unaligned_be16(val >> 16, p);
29 | __put_unaligned_be16(val, p + 2);
30 | }
31 |
32 | static inline void __put_unaligned_be64(uint64_t val, uint8_t *p)
33 | {
34 | __put_unaligned_be32(val >> 32, p);
35 | __put_unaligned_be32(val, p + 4);
36 | }
37 |
38 | static inline uint16_t get_unaligned_be16(const void *p)
39 | {
40 | return __get_unaligned_be16((const uint8_t *)p);
41 | }
42 |
43 | static inline uint32_t get_unaligned_be24(const uint8_t *p)
44 | {
45 | return p[0] << 16 | p[1] << 8 | p[2];
46 | }
47 |
48 | static inline uint32_t get_unaligned_be32(const void *p)
49 | {
50 | return __get_unaligned_be32((const uint8_t *)p);
51 | }
52 |
53 | static inline uint64_t get_unaligned_be64(const void *p)
54 | {
55 | return __get_unaligned_be64((const uint8_t *)p);
56 | }
57 |
58 | static inline void put_unaligned_be16(uint16_t val, void *p)
59 | {
60 | __put_unaligned_be16(val, (uint8_t *)p);
61 | }
62 |
63 | static inline void put_unaligned_be24(uint32_t val, void *p)
64 | {
65 | ((uint8_t *)p)[0] = (val >> 16) & 0xff;
66 | ((uint8_t *)p)[1] = (val >> 8) & 0xff;
67 | ((uint8_t *)p)[2] = val & 0xff;
68 | }
69 |
70 | static inline void put_unaligned_be32(uint32_t val, void *p)
71 | {
72 | __put_unaligned_be32(val, (uint8_t *)p);
73 | }
74 |
75 | static inline void put_unaligned_be64(uint64_t val, void *p)
76 | {
77 | __put_unaligned_be64(val, (uint8_t *)p);
78 | }
79 |
80 | #endif /* _LINUX_UNALIGNED_BE_BYTESHIFT_H */
81 |
--------------------------------------------------------------------------------
/usr/bs_aio.h:
--------------------------------------------------------------------------------
1 | #ifndef __BS_AIO_H
2 | #define __BS_AIO_H
3 |
4 | /* this file is a workaround */
5 |
6 | /*
7 | * eventfd-aio-test by Davide Libenzi (test app for eventfd hooked into KAIO)
8 | * Copyright (C) 2007 Davide Libenzi
9 | *
10 | * This program is free software; you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation; either version 2 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * This program is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; if not, write to the Free Software
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 | *
24 | * Davide Libenzi
25 | *
26 | */
27 |
28 | enum {
29 | IOCB_CMD_PREAD = 0,
30 | IOCB_CMD_PWRITE = 1,
31 | IOCB_CMD_FSYNC = 2,
32 | IOCB_CMD_FDSYNC = 3,
33 | /* These two are experimental.
34 | * IOCB_CMD_PREADX = 4,
35 | * IOCB_CMD_POLL = 5,
36 | */
37 | IOCB_CMD_NOOP = 6,
38 | IOCB_CMD_PREADV = 7,
39 | IOCB_CMD_PWRITEV = 8,
40 | };
41 |
42 | #define IOCB_FLAG_RESFD (1 << 0)
43 |
44 | #if defined(__LITTLE_ENDIAN)
45 | #define PADDED(x, y) x, y
46 | #elif defined(__BIG_ENDIAN)
47 | #define PADDED(x, y) y, x
48 | #else
49 | #error edit for your odd byteorder.
50 | #endif
51 |
52 | typedef unsigned long io_context_t;
53 |
54 | struct io_event {
55 | uint64_t data; /* the data field from the iocb */
56 | uint64_t obj; /* what iocb this event came from */
57 | int64_t res; /* result code for this event */
58 | int64_t res2; /* secondary result */
59 | };
60 |
61 | struct iocb {
62 | /* these are internal to the kernel/libc. */
63 | uint64_t aio_data; /* data to be returned in event's data */
64 | int32_t PADDED(aio_key, aio_reserved1);
65 | /* the kernel sets aio_key to the req # */
66 |
67 | /* common fields */
68 | uint16_t aio_lio_opcode; /* see IOCB_CMD_ above */
69 | int16_t aio_reqprio;
70 | int32_t aio_fildes;
71 |
72 | uint64_t aio_buf;
73 | uint64_t aio_nbytes;
74 | int64_t aio_offset;
75 |
76 | /* extra parameters */
77 | uint64_t aio_reserved2; /* TODO: use this for a (struct sigevent *) */
78 |
79 | /* flags for the "struct iocb" */
80 | int32_t aio_flags;
81 |
82 | /*
83 | * if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an
84 | * eventfd to signal AIO readiness to
85 | */
86 | int32_t aio_resfd;
87 | }; /* 64 bytes */
88 |
89 | static inline int io_setup(unsigned nr_reqs, io_context_t *ctx)
90 | {
91 | return syscall(__NR_io_setup, nr_reqs, ctx);
92 | }
93 |
94 | static inline long io_destroy(io_context_t ctx)
95 | {
96 | return syscall(__NR_io_destroy, ctx);
97 | }
98 |
99 | static inline int io_submit(io_context_t ctx, long n, struct iocb **paiocb)
100 | {
101 | return syscall(__NR_io_submit, ctx, n, paiocb);
102 | }
103 |
104 | static inline long io_cancel(io_context_t ctx, struct iocb *aiocb,
105 | struct io_event *res)
106 | {
107 | return syscall(__NR_io_cancel, ctx, aiocb, res);
108 | }
109 |
110 | static inline long io_getevents(io_context_t ctx, long min_nr, long nr,
111 | struct io_event *events, struct timespec *tmo)
112 | {
113 | return syscall(__NR_io_getevents, ctx, min_nr, nr, events, tmo);
114 | }
115 |
116 | static inline int eventfd(int count)
117 | {
118 | return syscall(__NR_eventfd, count);
119 | }
120 |
121 | #endif
122 |
--------------------------------------------------------------------------------
/usr/bs_null.c:
--------------------------------------------------------------------------------
1 | /*
2 | * NULL I/O backing store routine
3 | *
4 | * Copyright (C) 2008 Alexander Nezhinsky
5 | *
6 | * This program is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU General Public License as
8 | * published by the Free Software Foundation, version 2 of the
9 | * License.
10 | *
11 | * This program is distributed in the hope that it will be useful, but
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 | * 02110-1301 USA
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "list.h"
28 | #include "tgtd.h"
29 | #include "scsi.h"
30 |
31 | #define NULL_BS_DEV_SIZE (1ULL << 40)
32 |
33 | int bs_null_cmd_submit(struct scsi_cmd *cmd)
34 | {
35 | scsi_set_result(cmd, SAM_STAT_GOOD);
36 | return 0;
37 | }
38 |
39 | static int bs_null_open(struct scsi_lu *lu, char *path,
40 | int *fd, uint64_t *size)
41 | {
42 | *size = NULL_BS_DEV_SIZE;
43 | dprintf("NULL backing store open, size: %" PRIu64 "\n", *size);
44 | return 0;
45 | }
46 |
47 | static void bs_null_close(struct scsi_lu *lu)
48 | {
49 | }
50 |
51 | static struct backingstore_template null_bst = {
52 | .bs_name = "null",
53 | .bs_datasize = 0,
54 | .bs_open = bs_null_open,
55 | .bs_close = bs_null_close,
56 | .bs_cmd_submit = bs_null_cmd_submit,
57 | };
58 |
59 | __attribute__((constructor)) static void bs_null_constructor(void)
60 | {
61 | register_backingstore_template(&null_bst);
62 | }
63 |
--------------------------------------------------------------------------------
/usr/bs_ssc.h:
--------------------------------------------------------------------------------
1 | #ifndef __BS_SSC_H
2 | #define __BS_SSC_H
3 |
4 | /*
5 | * structure of a 'poor mans double linked list' on disk.
6 | */
7 |
8 | /**
9 | * Block type definitations
10 | *
11 | * @BLK_NOOP: No Operation.. Dummy value
12 | * @BLK_UNCOMPRESS_DATA: If true, data block is uncompressed
13 | * @BLK_ENCRYPTED_DATA: If true, data block is encrypted
14 | * @BLK_FILEMARK: Represents a filemark
15 | * @BLK_SETMARK: Represents a setmark
16 | * @BLK_BOT: Represents a Beginning of Tape marker
17 | * @BLK_EOD: Represents an End of Data marker
18 | *
19 | * Defines for types of SSC data blocks
20 | */
21 | #define BLK_NOOP 0x00000000
22 | #define BLK_COMPRESSED_DATA 0x00000001
23 | #define BLK_UNCOMPRESS_DATA 0x00000002
24 | #define BLK_ENCRYPTED_DATA 0x00000004
25 | #define BLK_BOT 0x00000010
26 | #define BLK_EOD 0x00000020
27 | #define BLK_FILEMARK 0x00000040
28 | #define BLK_SETMARK 0x00000080
29 |
30 | #define TGT_TAPE_VERSION 2
31 |
32 | #define SSC_BLK_HDR_SIZE (sizeof(struct blk_header))
33 |
34 | struct blk_header {
35 | uint8_t h_csum[4];
36 | uint32_t ondisk_sz;
37 | uint32_t blk_sz;
38 | uint32_t blk_type;
39 | uint64_t blk_num;
40 | uint64_t prev;
41 | uint64_t curr;
42 | uint64_t next;
43 | };
44 |
45 | /*
46 | * MAM (media access memory) structure based from IBM Ultrium SCSI
47 | * Reference WB1109-02
48 | */
49 | struct MAM {
50 | uint32_t tape_fmt_version;
51 | uint32_t __pad1;
52 |
53 | uint64_t remaining_capacity;
54 | uint64_t max_capacity;
55 | uint64_t TapeAlert;
56 | uint64_t load_count;
57 | uint64_t MAM_space_remaining;
58 |
59 | uint8_t assigning_organization_1[8];
60 | uint8_t formatted_density_code;
61 | uint8_t __pad2[5];
62 | uint8_t initialization_count[2];
63 | uint8_t dev_make_serial_last_load[4][40];
64 |
65 | uint64_t written_in_medium_life;
66 | uint64_t read_in_medium_life;
67 | uint64_t written_in_last_load;
68 | uint64_t read_in_last_load;
69 |
70 | uint8_t medium_manufacturer[8];
71 | uint8_t medium_serial_number[32];
72 | uint32_t medium_length;
73 | uint32_t medium_width;
74 | uint8_t assigning_organization_2[8];
75 | uint8_t medium_density_code;
76 | uint8_t __pad3[7];
77 | uint8_t medium_manufacture_date[8];
78 | uint64_t MAM_capacity;
79 | uint8_t medium_type;
80 | uint8_t __pad4;
81 | uint16_t medium_type_information;
82 | uint8_t __pad5[4];
83 |
84 | uint8_t application_vendor[8];
85 | uint8_t application_name[32];
86 | uint8_t application_version[8];
87 | uint8_t user_medium_text_label[160];
88 | uint8_t date_time_last_written[12];
89 | uint8_t __pad6[3];
90 | uint8_t localization_identifier;
91 | uint8_t barcode[32];
92 | uint8_t owning_host_textual_name[80];
93 | uint8_t media_pool[160];
94 |
95 | uint8_t vendor_unique[256];
96 |
97 | uint8_t dirty;
98 | uint8_t __reserved[7];
99 | };
100 |
101 | #endif
102 |
--------------------------------------------------------------------------------
/usr/bs_thread.h:
--------------------------------------------------------------------------------
1 | typedef void (request_func_t) (struct scsi_cmd *);
2 |
3 | struct tgt_evloop;
4 | struct bs_thread_info {
5 | pthread_t *worker_thread;
6 | int nr_worker_threads;
7 |
8 | /* wokers sleep on this and signaled by tgtd */
9 | pthread_cond_t pending_cond;
10 | /* locked by tgtd and workers */
11 | pthread_mutex_t pending_lock;
12 | /* protected by pending_lock */
13 | struct list_head pending_list;
14 |
15 | pthread_mutex_t finished_lock;
16 | struct list_head finished_list;
17 |
18 | request_func_t *request_fn;
19 |
20 | struct tgt_evloop *evloop;
21 |
22 | int sig_fd;
23 | };
24 |
25 | static inline struct bs_thread_info *BS_THREAD_I(struct scsi_lu *lu)
26 | {
27 | return (struct bs_thread_info *) ((char *)lu + sizeof(*lu));
28 | }
29 |
30 | extern tgtadm_err bs_thread_open(struct tgt_evloop *evloop,
31 | struct bs_thread_info *info, request_func_t *rfn,
32 | int nr_threads);
33 | extern void bs_thread_close(struct bs_thread_info *info);
34 | extern int bs_thread_cmd_submit(struct scsi_cmd *cmd);
35 | extern int nr_iothreads;
36 |
--------------------------------------------------------------------------------
/usr/bsg.h:
--------------------------------------------------------------------------------
1 | #ifndef BSG_H
2 | #define BSG_H
3 |
4 | #include
5 |
6 | #define BSG_PROTOCOL_SCSI 0
7 |
8 | #define BSG_SUB_PROTOCOL_SCSI_CMD 0
9 | #define BSG_SUB_PROTOCOL_SCSI_TMF 1
10 | #define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2
11 |
12 | /*
13 | * For flags member below
14 | * sg.h sg_io_hdr also has bits defined for it's flags member. However
15 | * none of these bits are implemented/used by bsg. The bits below are
16 | * allocated to not conflict with sg.h ones anyway.
17 | */
18 | #define BSG_FLAG_Q_AT_TAIL 0x10 /* default, == 0 at this bit, is Q_AT_HEAD */
19 |
20 | struct sg_io_v4 {
21 | __s32 guard; /* [i] 'Q' to differentiate from v3 */
22 | __u32 protocol; /* [i] 0 -> SCSI , .... */
23 | __u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task
24 | management function, .... */
25 |
26 | __u32 request_len; /* [i] in bytes */
27 | __u64 request; /* [i], [*i] {SCSI: cdb} */
28 | __u64 request_tag; /* [i] {SCSI: task tag (only if flagged)} */
29 | __u32 request_attr; /* [i] {SCSI: task attribute} */
30 | __u32 request_priority; /* [i] {SCSI: task priority} */
31 | __u32 request_extra; /* [i] {spare, for padding} */
32 | __u32 max_response_len; /* [i] in bytes */
33 | __u64 response; /* [i], [*o] {SCSI: (auto)sense data} */
34 |
35 | /* "dout_": data out (to device); "din_": data in (from device) */
36 | __u32 dout_iovec_count; /* [i] 0 -> "flat" dout transfer else
37 | dout_xfer points to array of iovec */
38 | __u32 dout_xfer_len; /* [i] bytes to be transferred to device */
39 | __u32 din_iovec_count; /* [i] 0 -> "flat" din transfer */
40 | __u32 din_xfer_len; /* [i] bytes to be transferred from device */
41 | __u64 dout_xferp; /* [i], [*i] */
42 | __u64 din_xferp; /* [i], [*o] */
43 |
44 | __u32 timeout; /* [i] units: millisecond */
45 | __u32 flags; /* [i] bit mask */
46 | __u64 usr_ptr; /* [i->o] unused internally */
47 | __u32 spare_in; /* [i] */
48 |
49 | __u32 driver_status; /* [o] 0 -> ok */
50 | __u32 transport_status; /* [o] 0 -> ok */
51 | __u32 device_status; /* [o] {SCSI: command completion status} */
52 | __u32 retry_delay; /* [o] {SCSI: status auxiliary information} */
53 | __u32 info; /* [o] additional information */
54 | __u32 duration; /* [o] time to complete, in milliseconds */
55 | __u32 response_len; /* [o] bytes of response actually written */
56 | __s32 din_resid; /* [o] din_xfer_len - actual_din_xfer_len */
57 | __s32 dout_resid; /* [o] dout_xfer_len - actual_dout_xfer_len */
58 | __u64 generated_tag; /* [o] {SCSI: transport generated task tag} */
59 | __u32 spare_out; /* [o] */
60 |
61 | __u32 padding;
62 | };
63 |
64 | #ifdef __KERNEL__
65 |
66 | #if defined(CONFIG_BLK_DEV_BSG)
67 | struct bsg_class_device {
68 | struct device *class_dev;
69 | struct device *parent;
70 | int minor;
71 | struct request_queue *queue;
72 | struct kref ref;
73 | void (*release)(struct device *);
74 | };
75 |
76 | extern int bsg_register_queue(struct request_queue *q,
77 | struct device *parent, const char *name,
78 | void (*release)(struct device *));
79 | extern void bsg_unregister_queue(struct request_queue *);
80 | #else
81 | static inline int bsg_register_queue(struct request_queue *q,
82 | struct device *parent, const char *name,
83 | void (*release)(struct device *))
84 | {
85 | return 0;
86 | }
87 | static inline void bsg_unregister_queue(struct request_queue *q)
88 | {
89 | }
90 | #endif
91 |
92 | #endif /* __KERNEL__ */
93 |
94 | #endif
95 |
--------------------------------------------------------------------------------
/usr/concat_buf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * concat_buf functions
3 | * appending formatted output to dynamically grown strings
4 | *
5 | * Copyright (C) 2011 Alexander Nezhinsky
6 | *
7 | * This program is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU General Public License as
9 | * published by the Free Software Foundation, version 2 of the
10 | * License.
11 | *
12 | * This program is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 | * 02110-1301 USA
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | #include "log.h"
28 | #include "util.h"
29 |
30 | void concat_buf_init(struct concat_buf *b)
31 | {
32 | b->streamf = open_memstream(&b->buf, &b->size);
33 | b->err = b->streamf ? 0 : errno;
34 | b->used = 0;
35 | }
36 |
37 | int concat_printf(struct concat_buf *b, const char *format, ...)
38 | {
39 | va_list args;
40 | int nprinted;
41 |
42 | if (!b->err) {
43 | va_start(args, format);
44 | nprinted = vfprintf(b->streamf, format, args);
45 | if (nprinted >= 0)
46 | b->used += nprinted;
47 | else {
48 | b->err = nprinted;
49 | fclose(b->streamf);
50 | b->streamf = NULL;
51 | }
52 | va_end(args);
53 | }
54 | return b->err;
55 | }
56 |
57 | const char *concat_delim(struct concat_buf *b, const char *delim)
58 | {
59 | return !b->used ? "" : delim;
60 | }
61 |
62 | int concat_buf_finish(struct concat_buf *b)
63 | {
64 | if (b->streamf) {
65 | fclose(b->streamf);
66 | b->streamf = NULL;
67 | if (b->size)
68 | b->size++; /* account for trailing NULL char */
69 | }
70 | return b->err;
71 | }
72 |
73 | int concat_write(struct concat_buf *b, int fd, int offset)
74 | {
75 | concat_buf_finish(b);
76 |
77 | if (b->err) {
78 | errno = b->err;
79 | return -1;
80 | }
81 |
82 | if (b->size - offset > 0)
83 | return write(fd, b->buf + offset, b->size - offset);
84 | else {
85 | errno = EINVAL;
86 | return -1;
87 | }
88 | }
89 |
90 | void concat_buf_release(struct concat_buf *b)
91 | {
92 | concat_buf_finish(b);
93 | if (b->buf) {
94 | free(b->buf);
95 | memset(b, 0, sizeof(*b));
96 | }
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/usr/crc32c.h:
--------------------------------------------------------------------------------
1 | #ifndef _LINUX_CRC32C_H
2 | #define _LINUX_CRC32C_H
3 |
4 | #include
5 | #include
6 |
7 | extern uint32_t crc32c_le(uint32_t crc, unsigned char const *address, size_t length);
8 | extern uint32_t crc32c_be(uint32_t crc, unsigned char const *address, size_t length);
9 |
10 | #define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
11 |
12 | #endif /* _LINUX_CRC32C_H */
13 |
--------------------------------------------------------------------------------
/usr/driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | * driver routine
3 | *
4 | * Copyright (C) 2007 FUJITA Tomonori
5 | * Copyright (C) 2007 Mike Christie
6 | *
7 | * This program is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU General Public License as
9 | * published by the Free Software Foundation, version 2 of the
10 | * License.
11 | *
12 | * This program is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 | * 02110-1301 USA
21 | */
22 | #include
23 | #include
24 | #include
25 |
26 | #include "list.h"
27 | #include "util.h"
28 | #include "tgtd.h"
29 | #include "driver.h"
30 |
31 | #define MAX_NR_DRIVERS 32
32 |
33 | struct tgt_driver *tgt_drivers[MAX_NR_DRIVERS] = {
34 | };
35 |
36 | int get_driver_index(char *name)
37 | {
38 | int i;
39 |
40 | for (i = 0; tgt_drivers[i]; i++) {
41 | if (!strcmp(name, tgt_drivers[i]->name))
42 | return i;
43 | }
44 |
45 | return -ENOENT;
46 | }
47 |
48 | int register_driver(struct tgt_driver *drv)
49 | {
50 | int i;
51 |
52 | for (i = 0; i < ARRAY_SIZE(tgt_drivers); i++)
53 | if (!tgt_drivers[i]) {
54 | drv->drv_state = DRIVER_REGD;
55 | tgt_drivers[i] = drv;
56 | return 0;
57 | }
58 |
59 | return -1;
60 | }
61 |
62 | const char *driver_state_name(struct tgt_driver *drv)
63 | {
64 | switch (drv->drv_state) {
65 | case DRIVER_REGD:
66 | return "uninitialized";
67 | case DRIVER_INIT:
68 | return "ready";
69 | case DRIVER_ERR:
70 | return "error";
71 | case DRIVER_EXIT:
72 | return "stopped";
73 | default:
74 | return "unsupported";
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/usr/driver.h:
--------------------------------------------------------------------------------
1 | #ifndef __DRIVER_H__
2 | #define __DRIVER_H__
3 |
4 | #include "tgtadm_error.h"
5 |
6 | enum tgt_driver_state {
7 | DRIVER_REGD = 0, /* just registered */
8 | DRIVER_INIT, /* initialized ok */
9 | DRIVER_ERR, /* failed to initialize */
10 | DRIVER_EXIT /* exited */
11 | };
12 |
13 | struct tgt_driver {
14 | const char *name;
15 | enum tgt_driver_state drv_state;
16 |
17 | int (*init)(int, char *);
18 | void (*exit)(void);
19 |
20 | int (*target_create)(struct target *);
21 | void (*target_destroy)(struct target *, int);
22 |
23 | int (*portal_create)(char *);
24 | int (*portal_destroy)(char *);
25 |
26 | int (*lu_create)(struct scsi_lu *);
27 |
28 | tgtadm_err (*update)(int, int, int ,uint64_t, uint64_t, uint32_t, char *);
29 | tgtadm_err (*show)(int, int, uint64_t, uint32_t, uint64_t, struct concat_buf *);
30 | tgtadm_err (*stat)(int, int, uint64_t, uint32_t, uint64_t, struct concat_buf *);
31 |
32 | uint64_t (*scsi_get_lun)(uint8_t *);
33 |
34 | int (*cmd_end_notify)(uint64_t nid, int result, struct scsi_cmd *);
35 | int (*mgmt_end_notify)(struct mgmt_req *);
36 |
37 | int (*transportid)(int, uint64_t, char *, int);
38 |
39 | int (*init_evloop)(struct tgt_evloop *);
40 | void (*fini_evloop)(struct tgt_evloop *);
41 |
42 | const char *default_bst;
43 |
44 | struct list_head target_list;
45 | };
46 |
47 | extern struct tgt_driver *tgt_drivers[];
48 | extern int get_driver_index(char *name);
49 | extern int register_driver(struct tgt_driver *drv);
50 | extern const char *driver_state_name(struct tgt_driver *drv);
51 |
52 | #endif /* __DRIVER_H__ */
53 |
--------------------------------------------------------------------------------
/usr/iscsi/md5.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the header file for the MD5 message-digest algorithm.
3 | * The algorithm is due to Ron Rivest. This code was
4 | * written by Colin Plumb in 1993, no copyright is claimed.
5 | * This code is in the public domain; do with it what you wish.
6 | *
7 | * Equivalent code is available from RSA Data Security, Inc.
8 | * This code has been tested against that, and is equivalent,
9 | * except that you don't need to include two pages of legalese
10 | * with every copy.
11 | *
12 | * To compute the message digest of a chunk of bytes, declare an
13 | * MD5Context structure, pass it to MD5Init, call MD5Update as
14 | * needed on buffers full of bytes, and then call MD5Final, which
15 | * will fill a supplied 16-byte array with the digest.
16 | *
17 | * Changed so as no longer to depend on Colin Plumb's `usual.h'
18 | * header definitions; now uses stuff from dpkg's config.h
19 | * - Ian Jackson .
20 | * Still in the public domain.
21 | */
22 |
23 | #ifndef MD5_H
24 | #define MD5_H
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #if (__BYTE_ORDER == __BIG_ENDIAN)
31 | # define WORDS_BIGENDIAN 1
32 | #endif
33 |
34 | typedef uint32_t UWORD32;
35 |
36 |
37 | #ifdef __cplusplus
38 | extern "C" {
39 | #endif
40 |
41 |
42 | #define md5byte unsigned char
43 |
44 | struct MD5Context {
45 | UWORD32 buf[4];
46 | UWORD32 bytes[2];
47 | UWORD32 in[16];
48 | };
49 |
50 | void MD5Init(struct MD5Context *context);
51 | void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
52 | void MD5Final(unsigned char digest[16], struct MD5Context *context);
53 | void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
54 |
55 |
56 | #ifdef __cplusplus
57 | }
58 | #endif
59 |
60 | #endif /* !MD5_H */
61 |
--------------------------------------------------------------------------------
/usr/iscsi/param.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2005-2007 FUJITA Tomonori
3 | *
4 | * This program is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU General Public License as
6 | * published by the Free Software Foundation, version 2 of the
7 | * License.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 | * 02110-1301 USA
18 | */
19 | #ifndef PARAMS_H
20 | #define PARAMS_H
21 |
22 | struct iscsi_key;
23 |
24 | struct param {
25 | int state;
26 | unsigned int val;
27 | };
28 |
29 | #define KEY_STATE_START 0
30 | #define KEY_STATE_REQUEST 1
31 | #define KEY_STATE_DONE 2
32 |
33 | struct iscsi_key_ops {
34 | int (*val_to_str)(unsigned int, char *);
35 | int (*str_to_val)(char *, unsigned int *);
36 | int (*check_val)(struct iscsi_key *, unsigned int *);
37 | void (*set_val)(struct param *, int, unsigned int *);
38 | };
39 |
40 | struct iscsi_key {
41 | char *name;
42 | unsigned int def;
43 | unsigned int min;
44 | unsigned int max;
45 | struct iscsi_key_ops *ops;
46 | };
47 |
48 | extern struct iscsi_key session_keys[];
49 |
50 | extern void param_set_defaults(struct param *, struct iscsi_key *);
51 | extern int param_index_by_name(char *, struct iscsi_key *);
52 | extern int param_val_to_str(struct iscsi_key *, int, unsigned int, char *);
53 | extern int param_str_to_val(struct iscsi_key *, int, char *, unsigned int *);
54 | extern int param_check_val(struct iscsi_key *, int, unsigned int *);
55 | extern void param_set_val(struct iscsi_key *, struct param *, int, unsigned int *);
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/usr/iscsi/session.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2002-2003 Ardis Technolgies
3 | *
4 | * This program is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU General Public License as
6 | * published by the Free Software Foundation, version 2 of the
7 | * License.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 | * 02110-1301 USA
18 | */
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include
27 | #include
28 |
29 | #include "iscsid.h"
30 | #include "tgtd.h"
31 | #include "target.h"
32 | #include "util.h"
33 |
34 | struct iscsi_session *session_find_name(int tid, const char *iname, uint8_t *isid)
35 | {
36 | struct iscsi_session *session;
37 | struct iscsi_target *target;
38 |
39 | target = target_find_by_id(tid);
40 | if (!target)
41 | return NULL;
42 |
43 | dprintf("session_find_name: %s %x %x %x %x %x %x\n", iname,
44 | isid[0], isid[1], isid[2], isid[3], isid[4], isid[5]);
45 | list_for_each_entry(session, &target->sessions_list, slist) {
46 | if (!memcmp(isid, session->isid, sizeof(session->isid)) &&
47 | !strcmp(iname, session->initiator))
48 | return session;
49 | }
50 |
51 | return NULL;
52 | }
53 |
54 | struct iscsi_session *session_lookup_by_tsih(int tid, uint16_t tsih)
55 | {
56 | struct iscsi_session *session;
57 | struct iscsi_target *target;
58 |
59 | target = target_find_by_id(tid);
60 | if (!target)
61 | return NULL;
62 |
63 | list_for_each_entry(session, &target->sessions_list, slist) {
64 | if (session->tsih == tsih)
65 | return session;
66 | }
67 | return NULL;
68 | }
69 |
70 | int session_create(struct iscsi_connection *conn)
71 | {
72 | int err;
73 | struct iscsi_session *session = NULL;
74 | static uint16_t tsih, last_tsih = 0;
75 | struct iscsi_target *target;
76 | char addr[128];
77 |
78 |
79 | target = target_find_by_id(conn->tid);
80 | if (!target)
81 | return -EINVAL;
82 |
83 | for (tsih = last_tsih + 1; tsih != last_tsih; tsih++) {
84 | if (!tsih)
85 | continue;
86 | session = session_lookup_by_tsih(target->base_target->tid, tsih);
87 | if (!session)
88 | break;
89 | }
90 | if (session)
91 | return -EINVAL;
92 |
93 | session = zalloc(sizeof(*session));
94 | if (!session)
95 | return -ENOMEM;
96 |
97 | session->initiator = strdup(conn->initiator);
98 | if (!session->initiator) {
99 | free(session);
100 | return -ENOMEM;
101 | }
102 |
103 | if (conn->initiator_alias) {
104 | session->initiator_alias = strdup(conn->initiator_alias);
105 | if (!session->initiator_alias) {
106 | free(session->initiator);
107 | free(session);
108 | return -ENOMEM;
109 | }
110 | }
111 |
112 | session->info = zalloc(1024);
113 | if (!session->info) {
114 | free(session->initiator);
115 | free(session->initiator_alias);
116 | free(session);
117 | return -ENOMEM;
118 | }
119 |
120 | memset(addr, 0, sizeof(addr));
121 | conn->tp->ep_show(conn, addr, sizeof(addr));
122 |
123 | snprintf(session->info, 1024, _TAB3 "Initiator: %s alias: %s\n"
124 | _TAB3 "Connection: %u\n"
125 | _TAB4 "%s\n", session->initiator,
126 | session->initiator_alias ? session->initiator_alias : "none",
127 | conn->cid, addr);
128 |
129 | err = it_nexus_create(target->base_target->tid, tsih, 0, session->info);
130 | if (err) {
131 | free(session->initiator);
132 | free(session->initiator_alias);
133 | free(session->info);
134 | free(session);
135 | return err;
136 | }
137 |
138 | session->target = target;
139 | INIT_LIST_HEAD(&session->slist);
140 | list_add(&session->slist, &target->sessions_list);
141 |
142 | INIT_LIST_HEAD(&session->conn_list);
143 | INIT_LIST_HEAD(&session->cmd_list);
144 | INIT_LIST_HEAD(&session->pending_cmd_list);
145 |
146 | memcpy(session->isid, conn->isid, sizeof(session->isid));
147 | session->tsih = last_tsih = tsih;
148 |
149 | session->rdma = conn->tp->rdma;
150 |
151 | conn_add_to_session(conn, session);
152 |
153 | dprintf("session_create: %#" PRIx64 "\n", sid64(conn->isid, session->tsih));
154 |
155 | session->exp_cmd_sn = conn->exp_cmd_sn;
156 |
157 | memcpy(session->session_param, conn->session_param,
158 | sizeof(session->session_param));
159 |
160 | session->max_queue_cmd =
161 | session->session_param[ISCSI_PARAM_MAX_QUEUE_CMD].val;
162 |
163 | return 0;
164 | }
165 |
166 | static void session_destroy(struct iscsi_session *session)
167 | {
168 | if (!list_empty(&session->conn_list)) {
169 | eprintf("%d conn_list is not null\n", session->tsih);
170 | return;
171 | }
172 |
173 | if (session->target) {
174 | list_del(&session->slist);
175 | /* session->target->nr_sessions--; */
176 | it_nexus_destroy_in_target(session->target->base_target, session->tsih);
177 | }
178 |
179 | free(session->initiator);
180 | free(session->initiator_alias);
181 | free(session->info);
182 | free(session);
183 | }
184 |
185 | void session_get(struct iscsi_session *session)
186 | {
187 | session->refcount++;
188 | }
189 |
190 | void session_put(struct iscsi_session *session)
191 | {
192 | if (!--session->refcount)
193 | session_destroy(session);
194 | }
195 |
--------------------------------------------------------------------------------
/usr/iscsi/sha1.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Cryptographic API.
3 | *
4 | * SHA1 Secure Hash Algorithm.
5 | *
6 | * Derived from cryptoapi implementation, adapted for in-place
7 | * scatterlist interface. Originally based on the public domain
8 | * implementation written by Steve Reid.
9 | *
10 | * Copyright (c) Alan Smithee.
11 | * Copyright (c) Andrew McDonald
12 | * Copyright (c) Jean-Francois Dive
13 | *
14 | * This program is free software; you can redistribute it and/or modify it
15 | * under the terms of the GNU General Public License as published by the Free
16 | * Software Foundation; either version 2 of the License, or (at your option)
17 | * any later version.
18 | *
19 | */
20 | #include
21 | #include "sha1.h"
22 |
23 | #define SHA1_DIGEST_SIZE 20
24 | #define SHA1_HMAC_BLOCK_SIZE 64
25 |
26 | static inline uint32_t rol(uint32_t value, uint32_t bits)
27 | {
28 | return (((value) << (bits)) | ((value) >> (32 - (bits))));
29 | }
30 |
31 | /* blk0() and blk() perform the initial expand. */
32 | /* I got the idea of expanding during the round function from SSLeay */
33 | # define blk0(i) block32[i]
34 |
35 | #define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
36 | ^block32[(i+2)&15]^block32[i&15],1))
37 |
38 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
39 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
40 | w=rol(w,30);
41 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
42 | w=rol(w,30);
43 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
44 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
45 | w=rol(w,30);
46 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
47 |
48 | /* Hash a single 512-bit block. This is the core of the algorithm. */
49 | static void sha1_transform(uint32_t *state, const uint8_t *in)
50 | {
51 | uint32_t a, b, c, d, e;
52 | uint32_t block32[16];
53 |
54 | /* convert/copy data to workspace */
55 | for (a = 0; a < sizeof(block32)/sizeof(uint32_t); a++)
56 | block32[a] = ntohl (((const uint32_t *)in)[a]);
57 |
58 | /* Copy context->state[] to working vars */
59 | a = state[0];
60 | b = state[1];
61 | c = state[2];
62 | d = state[3];
63 | e = state[4];
64 |
65 | /* 4 rounds of 20 operations each. Loop unrolled. */
66 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
67 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
68 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
69 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
70 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
71 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
72 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
73 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
74 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
75 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
76 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
77 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
78 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
79 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
80 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
81 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
82 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
83 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
84 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
85 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
86 | /* Add the working vars back into context.state[] */
87 | state[0] += a;
88 | state[1] += b;
89 | state[2] += c;
90 | state[3] += d;
91 | state[4] += e;
92 | /* Wipe variables */
93 | a = b = c = d = e = 0;
94 | memset (block32, 0x00, sizeof block32);
95 | }
96 |
97 | void sha1_init(void *ctx)
98 | {
99 | struct sha1_ctx *sctx = ctx;
100 | static const struct sha1_ctx initstate = {
101 | 0,
102 | { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
103 | { 0, }
104 | };
105 |
106 | *sctx = initstate;
107 | }
108 |
109 | void sha1_update(void *ctx, const uint8_t *data, unsigned int len)
110 | {
111 | struct sha1_ctx *sctx = ctx;
112 | unsigned int i, j;
113 |
114 | j = (sctx->count >> 3) & 0x3f;
115 | sctx->count += len << 3;
116 |
117 | if ((j + len) > 63) {
118 | memcpy(&sctx->buffer[j], data, (i = 64-j));
119 | sha1_transform(sctx->state, sctx->buffer);
120 | for ( ; i + 63 < len; i += 64) {
121 | sha1_transform(sctx->state, &data[i]);
122 | }
123 | j = 0;
124 | }
125 | else i = 0;
126 | memcpy(&sctx->buffer[j], &data[i], len - i);
127 | }
128 |
129 |
130 | /* Add padding and return the message digest. */
131 | void sha1_final(void* ctx, uint8_t *out)
132 | {
133 | struct sha1_ctx *sctx = ctx;
134 | uint32_t i, j, index, padlen;
135 | uint64_t t;
136 | uint8_t bits[8] = { 0, };
137 | static const uint8_t padding[64] = { 0x80, };
138 |
139 | t = sctx->count;
140 | bits[7] = 0xff & t; t>>=8;
141 | bits[6] = 0xff & t; t>>=8;
142 | bits[5] = 0xff & t; t>>=8;
143 | bits[4] = 0xff & t; t>>=8;
144 | bits[3] = 0xff & t; t>>=8;
145 | bits[2] = 0xff & t; t>>=8;
146 | bits[1] = 0xff & t; t>>=8;
147 | bits[0] = 0xff & t;
148 |
149 | /* Pad out to 56 mod 64 */
150 | index = (sctx->count >> 3) & 0x3f;
151 | padlen = (index < 56) ? (56 - index) : ((64+56) - index);
152 | sha1_update(sctx, padding, padlen);
153 |
154 | /* Append length */
155 | sha1_update(sctx, bits, sizeof bits);
156 |
157 | /* Store state in digest */
158 | for (i = j = 0; i < 5; i++, j += 4) {
159 | uint32_t t2 = sctx->state[i];
160 | out[j+3] = t2 & 0xff; t2>>=8;
161 | out[j+2] = t2 & 0xff; t2>>=8;
162 | out[j+1] = t2 & 0xff; t2>>=8;
163 | out[j ] = t2 & 0xff;
164 | }
165 |
166 | /* Wipe context */
167 | memset(sctx, 0, sizeof *sctx);
168 | }
169 |
--------------------------------------------------------------------------------
/usr/iscsi/sha1.h:
--------------------------------------------------------------------------------
1 | /*
2 | * sha1.h - SHA1 Secure Hash Algorithm used for CHAP authentication.
3 | * copied from the Linux kernel's Cryptographic API and slightly adjusted to
4 | * fit IET's needs
5 | *
6 | * This file is (c) 2004 Xiranet Communications GmbH
7 | * and licensed under the GPL.
8 | */
9 |
10 | #ifndef SHA1_H
11 | #define SHA1_H
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | struct sha1_ctx {
18 | uint64_t count;
19 | uint32_t state[5];
20 | uint8_t buffer[64];
21 | };
22 |
23 | void sha1_init(void *ctx);
24 | void sha1_update(void *ctx, const uint8_t *data, unsigned int len);
25 | void sha1_final(void* ctx, uint8_t *out);
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/usr/iscsi/transport.c:
--------------------------------------------------------------------------------
1 | /*
2 | * iSCSI transport functions
3 | *
4 | * Copyright (C) 2007 FUJITA Tomonori
5 | * Copyright (C) 2007 Mike Christie
6 | *
7 | * This program is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU General Public License as
9 | * published by the Free Software Foundation, version 2 of the
10 | * License.
11 | *
12 | * This program is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 | * 02110-1301 USA
21 | */
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "iscsid.h"
28 | #include "transport.h"
29 |
30 | static LIST_HEAD(iscsi_transport_list);
31 |
32 | int lld_index;
33 |
34 | int iscsi_init(int index, char *args)
35 | {
36 | int err, nr = 0;
37 | struct iscsi_transport *t;
38 |
39 | lld_index = index;
40 |
41 | list_for_each_entry(t, &iscsi_transport_list,
42 | iscsi_transport_siblings) {
43 | err = t->ep_init();
44 | if (!err)
45 | nr++;
46 | }
47 |
48 | return !nr;
49 | }
50 |
51 | void iscsi_exit(void)
52 | {
53 | struct iscsi_transport *t;
54 |
55 | list_for_each_entry(t, &iscsi_transport_list,
56 | iscsi_transport_siblings)
57 | if (t->ep_exit)
58 | t->ep_exit();
59 | }
60 |
61 | int iscsi_transport_register(struct iscsi_transport *t)
62 | {
63 | list_add_tail(&t->iscsi_transport_siblings, &iscsi_transport_list);
64 | return 0;
65 | }
66 |
67 | int iscsi_init_evloop(struct tgt_evloop *evloop)
68 | {
69 | int err, nr = 0;
70 | struct iscsi_transport *t;
71 |
72 | list_for_each_entry(t, &iscsi_transport_list,
73 | iscsi_transport_siblings) {
74 | err = t->ep_init_evloop(evloop);
75 | if (!err)
76 | nr++;
77 | }
78 |
79 | return !nr;
80 | }
81 |
82 | void iscsi_fini_evloop(struct tgt_evloop *evloop)
83 | {
84 | struct iscsi_transport *t;
85 |
86 | list_for_each_entry(t, &iscsi_transport_list,
87 | iscsi_transport_siblings)
88 | if (t->ep_fini_evloop)
89 | t->ep_fini_evloop(evloop);
90 | }
91 |
92 |
--------------------------------------------------------------------------------
/usr/iscsi/transport.h:
--------------------------------------------------------------------------------
1 | #ifndef __TRANSPORT_H
2 | #define __TRANSPORT_H
3 |
4 | #include
5 | #include "list.h"
6 |
7 | struct iscsi_connection;
8 | struct iscsi_task;
9 | struct tgt_evloop;
10 |
11 | struct iscsi_transport {
12 | struct list_head iscsi_transport_siblings;
13 |
14 | const char *name;
15 | int rdma;
16 | int data_padding;
17 |
18 | int (*ep_init) (void);
19 | void (*ep_exit) (void);
20 | int (*ep_login_complete)(struct iscsi_connection *conn);
21 | struct iscsi_task *(*alloc_task)(struct iscsi_connection *conn,
22 | size_t ext_len);
23 | void (*free_task)(struct iscsi_task *task);
24 | size_t (*ep_read)(struct iscsi_connection *conn, void *buf,
25 | size_t nbytes);
26 | size_t (*ep_write_begin)(struct iscsi_connection *conn, void *buf,
27 | size_t nbytes);
28 | void (*ep_write_end)(struct iscsi_connection *conn);
29 | int (*ep_rdma_read)(struct iscsi_connection *conn);
30 | int (*ep_rdma_write)(struct iscsi_connection *conn);
31 | size_t (*ep_close)(struct iscsi_connection *conn);
32 | void (*ep_force_close)(struct iscsi_connection *conn);
33 | void (*ep_release)(struct iscsi_connection *conn);
34 |
35 | int (*ep_show)(struct iscsi_connection *conn, char *buf, int rest);
36 | void (*ep_event_modify)(struct iscsi_connection *conn, int events);
37 | void *(*alloc_data_buf)(struct iscsi_connection *conn, size_t sz);
38 | void (*free_data_buf)(struct iscsi_connection *conn, void *buf);
39 | int (*ep_getsockname)(struct iscsi_connection *conn,
40 | struct sockaddr *sa, socklen_t *len);
41 | int (*ep_getpeername)(struct iscsi_connection *conn,
42 | struct sockaddr *sa, socklen_t *len);
43 | void (*ep_nop_reply) (struct tgt_evloop *evloop, long ttt);
44 | int (*ep_init_evloop) (struct tgt_evloop *evloop);
45 | void (*ep_fini_evloop) (struct tgt_evloop *evloop);
46 | void (*ep_migrate_evloop) (struct iscsi_connection *conn, struct tgt_evloop *old, struct tgt_evloop *new);
47 | };
48 |
49 | extern int iscsi_transport_register(struct iscsi_transport *);
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/usr/libcrc32c.c:
--------------------------------------------------------------------------------
1 | /*
2 | * CRC32C
3 | *@Article{castagnoli-crc,
4 | * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
5 | * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
6 | * and 32 Parity Bits}},
7 | * journal = IEEE Transactions on Communication,
8 | * year = {1993},
9 | * volume = {41},
10 | * number = {6},
11 | * pages = {},
12 | * month = {June},
13 | *}
14 | * Used by the iSCSI driver, possibly others, and derived from the
15 | * the iscsi-crc.c module of the linux-iscsi driver at
16 | * http://linux-iscsi.sourceforge.net.
17 | *
18 | * Following the example of lib/crc32, this function is intended to be
19 | * flexible and useful for all users. Modules that currently have their
20 | * own crc32c, but hopefully may be able to use this one are:
21 | * net/sctp (please add all your doco to here if you change to
22 | * use this one!)
23 | *
24 | *
25 | * Copyright (c) 2004 Cisco Systems, Inc.
26 | *
27 | * This program is free software; you can redistribute it and/or modify it
28 | * under the terms of the GNU General Public License as published by the Free
29 | * Software Foundation; either version 2 of the License, or (at your option)
30 | * any later version.
31 | *
32 | */
33 | #include "crc32c.h"
34 | #include
35 |
36 | /*
37 | * MODULE_AUTHOR("Clay Haapala ");
38 | * MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
39 | * MODULE_LICENSE("GPL");
40 | */
41 |
42 | #define CRC32C_POLY_BE 0x1EDC6F41
43 | #define CRC32C_POLY_LE 0x82F63B78
44 |
45 | #ifndef CRC_LE_BITS
46 | # define CRC_LE_BITS 8
47 | #endif
48 |
49 | /*
50 | * Haven't generated a big-endian table yet, but the bit-wise version
51 | * should at least work.
52 | */
53 | #if defined CRC_BE_BITS && CRC_BE_BITS != 1
54 | #undef CRC_BE_BITS
55 | #endif
56 | #ifndef CRC_BE_BITS
57 | # define CRC_BE_BITS 1
58 | #endif
59 |
60 | #if CRC_LE_BITS == 1
61 | /*
62 | * Compute things bit-wise, as done in crc32.c. We could share the tight
63 | * loop below with crc32 and vary the POLY if we don't find value in terms
64 | * of space and maintainability in keeping the two modules separate.
65 | */
66 | uint32_t __attribute__((pure))
67 | crc32c_le(uint32_t crc, unsigned char const *p, size_t len)
68 | {
69 | int i;
70 | while (len--) {
71 | crc ^= *p++;
72 | for (i = 0; i < 8; i++)
73 | crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
74 | }
75 | return crc;
76 | }
77 | #else
78 |
79 | /*
80 | * This is the CRC-32C table
81 | * Generated with:
82 | * width = 32 bits
83 | * poly = 0x1EDC6F41
84 | * reflect input bytes = true
85 | * reflect output bytes = true
86 | */
87 |
88 | static const uint32_t crc32c_table[256] = {
89 | 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
90 | 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
91 | 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
92 | 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
93 | 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
94 | 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
95 | 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
96 | 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
97 | 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
98 | 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
99 | 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
100 | 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
101 | 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
102 | 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
103 | 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
104 | 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
105 | 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
106 | 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
107 | 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
108 | 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
109 | 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
110 | 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
111 | 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
112 | 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
113 | 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
114 | 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
115 | 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
116 | 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
117 | 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
118 | 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
119 | 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
120 | 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
121 | 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
122 | 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
123 | 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
124 | 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
125 | 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
126 | 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
127 | 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
128 | 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
129 | 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
130 | 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
131 | 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
132 | 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
133 | 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
134 | 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
135 | 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
136 | 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
137 | 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
138 | 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
139 | 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
140 | 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
141 | 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
142 | 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
143 | 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
144 | 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
145 | 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
146 | 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
147 | 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
148 | 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
149 | 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
150 | 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
151 | 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
152 | 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
153 | };
154 |
155 | /*
156 | * Steps through buffer one byte at at time, calculates reflected
157 | * crc using table.
158 | */
159 |
160 | uint32_t __attribute__((pure))
161 | crc32c_le(uint32_t seed, unsigned char const *data, size_t length)
162 | {
163 | uint32_t crc = __cpu_to_le32(seed);
164 |
165 | while (length--)
166 | crc =
167 | crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
168 |
169 | return __le32_to_cpu(crc);
170 | }
171 |
172 | #endif /* CRC_LE_BITS == 8 */
173 |
174 | #if CRC_BE_BITS == 1
175 | uint32_t __attribute__((pure))
176 | crc32c_be(uint32_t crc, unsigned char const *p, size_t len)
177 | {
178 | int i;
179 | while (len--) {
180 | crc ^= *p++ << 24;
181 | for (i = 0; i < 8; i++)
182 | crc =
183 | (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
184 | 0);
185 | }
186 | return crc;
187 | }
188 | #endif
189 |
--------------------------------------------------------------------------------
/usr/libssc.h:
--------------------------------------------------------------------------------
1 | #ifndef __LIBSSC_H
2 | #define __LIBSSC_H
3 |
4 | extern int ssc_read_mam_info(int fd, struct MAM_info *i);
5 | extern int ssc_write_mam_info(int fd, struct MAM_info *i);
6 | extern int ssc_read_blkhdr(int fd, struct blk_header_info *h, loff_t offset);
7 | extern int ssc_write_blkhdr(int fd, struct blk_header_info *h, loff_t offset);
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/usr/list.h:
--------------------------------------------------------------------------------
1 | #ifndef __LIST_H__
2 | #define __LIST_H__
3 |
4 | /* taken from linux kernel */
5 |
6 | #undef offsetof
7 | #ifdef __compiler_offsetof
8 | #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
9 | #else
10 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
11 | #endif
12 |
13 | #define container_of(ptr, type, member) ({ \
14 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \
15 | (type *)( (char *)__mptr - offsetof(type,member) );})
16 |
17 | struct list_head {
18 | struct list_head *next, *prev;
19 | };
20 |
21 | #define LIST_HEAD_INIT(name) { &(name), &(name) }
22 |
23 | #define LIST_HEAD(name) \
24 | struct list_head name = LIST_HEAD_INIT(name)
25 |
26 | static inline void INIT_LIST_HEAD(struct list_head *list)
27 | {
28 | list->next = list;
29 | list->prev = list;
30 | }
31 |
32 | #define list_first_entry(ptr, type, member) \
33 | list_entry((ptr)->next, type, member)
34 |
35 | static inline int list_empty(const struct list_head *head)
36 | {
37 | return head->next == head;
38 | }
39 |
40 | #define list_entry(ptr, type, member) \
41 | container_of(ptr, type, member)
42 |
43 | #define list_for_each(pos, head) \
44 | for (pos = (head)->next; pos != (head); pos = pos->next)
45 |
46 | #define list_for_each_prev(pos, head) \
47 | for (pos = (head)->prev; pos != (head); pos = pos->prev)
48 |
49 | #define list_for_each_entry(pos, head, member) \
50 | for (pos = list_entry((head)->next, typeof(*pos), member); \
51 | &pos->member != (head); \
52 | pos = list_entry(pos->member.next, typeof(*pos), member))
53 |
54 | #define list_for_each_entry_safe(pos, n, head, member) \
55 | for (pos = list_entry((head)->next, typeof(*pos), member), \
56 | n = list_entry(pos->member.next, typeof(*pos), member); \
57 | &pos->member != (head); \
58 | pos = n, n = list_entry(n->member.next, typeof(*n), member))
59 |
60 | #define list_first_entry(ptr, type, member) \
61 | list_entry((ptr)->next, type, member)
62 |
63 | #define list_last_entry(ptr, type, member) \
64 | list_entry((ptr)->prev, type, member)
65 |
66 | #define list_entry_is_head(pos, head, member) \
67 | (&pos->member == (head))
68 |
69 | #define list_prev_entry(pos, member) \
70 | list_entry((pos)->member.prev, typeof(*(pos)), member)
71 |
72 | #define list_for_each_entry_reverse(pos, head, member) \
73 | for (pos = list_last_entry(head, typeof(*pos), member); \
74 | !list_entry_is_head(pos, head, member); \
75 | pos = list_prev_entry(pos, member))
76 |
77 | static inline void __list_add(struct list_head *new_,
78 | struct list_head *prev,
79 | struct list_head *next)
80 | {
81 | next->prev = new_;
82 | new_->next = next;
83 | new_->prev = prev;
84 | prev->next = new_;
85 | }
86 |
87 | static inline void list_add(struct list_head *new_, struct list_head *head)
88 | {
89 | __list_add(new_, head, head->next);
90 | }
91 |
92 | static inline void list_add_tail(struct list_head *new_, struct list_head *head)
93 | {
94 | __list_add(new_, head->prev, head);
95 | }
96 |
97 | static inline void __list_del(struct list_head * prev, struct list_head * next)
98 | {
99 | next->prev = prev;
100 | prev->next = next;
101 | }
102 |
103 | static inline void list_del(struct list_head *entry)
104 | {
105 | __list_del(entry->prev, entry->next);
106 | entry->next = entry->prev = NULL;
107 | }
108 |
109 | static inline void list_del_init(struct list_head *entry)
110 | {
111 | __list_del(entry->prev, entry->next);
112 | INIT_LIST_HEAD(entry);
113 | }
114 |
115 | static inline void __list_splice(const struct list_head *list,
116 | struct list_head *prev,
117 | struct list_head *next)
118 | {
119 | struct list_head *first = list->next;
120 | struct list_head *last = list->prev;
121 |
122 | first->prev = prev;
123 | prev->next = first;
124 |
125 | last->next = next;
126 | next->prev = last;
127 | }
128 |
129 | static inline void list_splice_init(struct list_head *list,
130 | struct list_head *head)
131 | {
132 | if (!list_empty(list)) {
133 | __list_splice(list, head, head->next);
134 | INIT_LIST_HEAD(list);
135 | }
136 | }
137 |
138 | #endif
139 |
--------------------------------------------------------------------------------
/usr/log.h:
--------------------------------------------------------------------------------
1 | /*
2 | * iSCSI Safe Logging and Tracing Library
3 | *
4 | * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 | * maintained by open-iscsi@googlegroups.com
6 | *
7 | * circular buffer code based on log.c from dm-multipath project
8 | *
9 | * heavily based on code from log.c:
10 | * Copyright (C) 2002-2003 Ardis Technolgies ,
11 | * licensed under the terms of the GNU GPL v2.0,
12 | *
13 | * This program is free software; you can redistribute it and/or modify
14 | * it under the terms of the GNU General Public License as published
15 | * by the Free Software Foundation; either version 2 of the License, or
16 | * (at your option) any later version.
17 | *
18 | * This program is distributed in the hope that it will be useful, but
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 | * General Public License for more details.
22 | *
23 | * See the file COPYING included with this distribution for more details.
24 | */
25 |
26 | #ifndef LOG_H
27 | #define LOG_H
28 |
29 | #include
30 |
31 | #define likely(x) __builtin_expect(!!(x), 1)
32 | #define unlikely(x) __builtin_expect(!!(x), 0)
33 |
34 | union semun {
35 | int val;
36 | struct semid_ds *buf;
37 | unsigned short int *array;
38 | struct seminfo *__buf;
39 | };
40 |
41 | #define LOG_SPACE_SIZE 16384
42 | #define MAX_MSG_SIZE 256
43 |
44 | extern int log_daemon;
45 | extern int log_level;
46 |
47 | struct logmsg {
48 | short int prio;
49 | void *next;
50 | char *str;
51 | };
52 |
53 | struct logarea {
54 | int empty;
55 | int active;
56 | void *head;
57 | void *tail;
58 | void *start;
59 | void *end;
60 | char *buff;
61 | int semid;
62 | union semun semarg;
63 | };
64 |
65 | extern int log_init(char *progname, int size, int daemon, int debug);
66 | extern void log_close(void);
67 | extern void dump_logmsg(void *);
68 | extern void log_warning(const char *fmt, ...)
69 | __attribute__ ((format (printf, 1, 2)));
70 | extern void log_error(const char *fmt, ...)
71 | __attribute__ ((format (printf, 1, 2)));
72 | extern void log_debug(const char *fmt, ...)
73 | __attribute__ ((format (printf, 1, 2)));
74 |
75 | #ifdef NO_LOGGING
76 | #define eprintf(fmt, args...) \
77 | do { \
78 | fprintf(stderr, "%s: " fmt, program_name, ##args); \
79 | } while (0)
80 |
81 | #define dprintf(fmt, args...) \
82 | do { \
83 | if (debug) \
84 | fprintf(stderr, "%s %d: " fmt, \
85 | __FUNCTION__, __LINE__, ##args); \
86 | } while (0)
87 | #else
88 | #define eprintf(fmt, args...) \
89 | do { \
90 | log_error("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
91 | } while (0)
92 |
93 | #define dprintf(fmt, args...) \
94 | do { \
95 | if (unlikely(is_debug)) \
96 | log_debug("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
97 | } while (0)
98 | #endif
99 |
100 | #endif /* LOG_H */
101 |
--------------------------------------------------------------------------------
/usr/media.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; version 2 of the License.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License
12 | * along with this program; if not, write to the Free Software
13 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14 | */
15 | #ifndef _MEDIA_H_
16 | #define _MEDIA_H_
17 |
18 | enum c_type { /* Cartridge Types - Ref: smc3r06 - Table 20, page 37 */
19 | CART_UNSPECIFIED,
20 | CART_DATA,
21 | CART_CLEAN,
22 | CART_DIAGNOSTICS,
23 | CART_WORM,
24 | CART_MICROCODE,
25 | };
26 |
27 | #endif /* _MEDIA_H_ */
28 |
29 |
--------------------------------------------------------------------------------
/usr/mutex.c:
--------------------------------------------------------------------------------
1 | #include "mutex.h"
2 | #include "log.h"
3 | #include
4 | #include
5 |
6 | void mutex_init(tgt_mutex_t *m)
7 | {
8 | pthread_mutex_init(&m->raw_mutex, NULL);
9 | m->owner = 0;
10 | }
11 |
12 | void mutex_destroy(tgt_mutex_t *m)
13 | {
14 | if (m->owner != 0) {
15 | eprintf("mutex_destroy ower exists\n");
16 | }
17 | pthread_mutex_destroy(&m->raw_mutex);
18 | }
19 |
20 | void mutex_lock(tgt_mutex_t *m)
21 | {
22 | int err = pthread_mutex_lock(&m->raw_mutex);
23 | if (err) {
24 | errno = err;
25 | eprintf("mutex lock failed %m\n");
26 | abort();
27 | }
28 |
29 | m->owner = pthread_self();
30 | }
31 |
32 | void mutex_unlock(tgt_mutex_t *m)
33 | {
34 | if (m->owner != pthread_self()){
35 | eprintf("mutex unlock, mutex not owned\n");
36 | abort();
37 | }
38 |
39 | m->owner = 0;
40 | int err = pthread_mutex_unlock(&m->raw_mutex);
41 | if (err) {
42 | errno = err;
43 | eprintf("pthread_mutex_unlock failed %m\n");
44 | abort();
45 | }
46 | }
47 |
48 | int mutex_is_locked(tgt_mutex_t *m)
49 | {
50 | return pthread_self() == m->owner;
51 | }
52 |
53 | void mutex_assert_locked(tgt_mutex_t *m)
54 | {
55 | if (m->owner != pthread_self()){
56 | eprintf("mutex not owned\n");
57 | abort();
58 | }
59 | }
60 |
61 | void mutex_assert_unlocked(tgt_mutex_t *m)
62 | {
63 | if (m->owner == pthread_self()){
64 | eprintf("mutex owned\n");
65 | abort();
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/usr/mutex.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | struct tgt_mutex {
6 | pthread_mutex_t raw_mutex;
7 | pthread_t owner;
8 | };
9 |
10 | typedef struct tgt_mutex tgt_mutex_t;
11 |
12 | void mutex_init(tgt_mutex_t *m);
13 | void mutex_destroy(tgt_mutex_t *m);
14 | void mutex_lock(tgt_mutex_t *m);
15 | void mutex_unlock(tgt_mutex_t *m);
16 | int mutex_is_locked(tgt_mutex_t *m);
17 | void mutex_assert_locked(tgt_mutex_t *m);
18 | void mutex_assert_unlocked(tgt_mutex_t *m);
19 |
20 |
--------------------------------------------------------------------------------
/usr/osd.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SCSI object storage device command processing
3 | *
4 | * Copyright (C) 2006-2007 Pete Wyckoff
5 | * Copyright (C) 2007 FUJITA Tomonori
6 | * Copyright (C) 2007 Mike Christie
7 | *
8 | * This program is free software; you can redistribute it and/or
9 | * modify it under the terms of the GNU General Public License as
10 | * published by the Free Software Foundation, version 2 of the
11 | * License.
12 | *
13 | * This program is distributed in the hope that it will be useful, but
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | * General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with this program; if not, write to the Free Software
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 | * 02110-1301 USA
22 | */
23 | #include
24 | #include
25 |
26 | #include "list.h"
27 | #include "tgtd.h"
28 | #include "scsi.h"
29 | #include "spc.h"
30 | #include "tgtadm_error.h"
31 |
32 | static int osd_varlen_cdb(int host_no, struct scsi_cmd *cmd)
33 | {
34 | return cmd->dev->bst->bs_cmd_submit(cmd);
35 | }
36 |
37 | /*
38 | * XXX: missing support for b0 and b1, in page 0 and in inquiry code.
39 | * Figure out how to make spc_inquiry handle extra mode pages.
40 | */
41 | static tgtadm_err osd_lu_init(struct scsi_lu *lu)
42 | {
43 | if (spc_lu_init(lu))
44 | return TGTADM_NOMEM;
45 |
46 | strncpy(lu->attrs.product_id, "OSD", sizeof(lu->attrs.product_id));
47 | lu->attrs.sense_format = 1;
48 | lu->attrs.version_desc[0] = 0x0340; /* OSD */
49 | lu->attrs.version_desc[1] = 0x0960; /* iSCSI */
50 | lu->attrs.version_desc[2] = 0x0300; /* SPC-3 */
51 |
52 | return TGTADM_SUCCESS;
53 | }
54 |
55 | static struct device_type_template osd_template = {
56 | .type = TYPE_OSD,
57 | .lu_init = osd_lu_init,
58 | .lu_config = spc_lu_config,
59 | .lu_online = spc_lu_online,
60 | .lu_offline = spc_lu_offline,
61 | .lu_exit = spc_lu_exit,
62 | .ops = {
63 | /* 0x00 */
64 | {spc_test_unit,},
65 | {spc_illegal_op,},
66 | {spc_illegal_op,},
67 | {spc_request_sense,},
68 | {spc_illegal_op,},
69 | {spc_illegal_op,},
70 | {spc_illegal_op,},
71 | {spc_illegal_op,},
72 |
73 | {spc_illegal_op,},
74 | {spc_illegal_op,},
75 | {spc_illegal_op,},
76 | {spc_illegal_op,},
77 | {spc_illegal_op,},
78 | {spc_illegal_op,},
79 | {spc_illegal_op,},
80 | {spc_illegal_op,},
81 |
82 | /* 0x10 */
83 | {spc_illegal_op,},
84 | {spc_illegal_op,},
85 | {spc_inquiry,},
86 | {spc_illegal_op,},
87 | {spc_illegal_op,},
88 | {spc_illegal_op,},
89 | {spc_illegal_op,},
90 | {spc_illegal_op,},
91 |
92 | {spc_illegal_op,},
93 | {spc_illegal_op,},
94 | {spc_illegal_op,},
95 | {spc_illegal_op,},
96 | {spc_illegal_op,},
97 | {spc_illegal_op,},
98 | {spc_illegal_op,},
99 | {spc_illegal_op,},
100 |
101 | [0x20 ... 0x6f] = {spc_illegal_op},
102 |
103 | /* 0x70 */
104 | {spc_illegal_op,},
105 | {spc_illegal_op,},
106 | {spc_illegal_op,},
107 | {spc_illegal_op,},
108 | {spc_illegal_op,},
109 | {spc_illegal_op,},
110 | {spc_illegal_op,},
111 | {spc_illegal_op,},
112 |
113 | {spc_illegal_op,},
114 | {spc_illegal_op,},
115 | {spc_illegal_op,},
116 | {spc_illegal_op,},
117 | {spc_illegal_op,},
118 | {spc_illegal_op,},
119 | {spc_illegal_op,},
120 | {osd_varlen_cdb,},
121 |
122 | [0x80 ... 0x9f] = {spc_illegal_op},
123 |
124 | /* 0xA0 */
125 | {spc_report_luns,},
126 | {spc_illegal_op,},
127 | {spc_illegal_op,},
128 | {spc_illegal_op,},
129 | {spc_illegal_op,},
130 | {spc_illegal_op,},
131 | {spc_illegal_op,},
132 | {spc_illegal_op,},
133 |
134 | {spc_illegal_op,},
135 | {spc_illegal_op,},
136 | {spc_illegal_op,},
137 | {spc_illegal_op,},
138 | {spc_illegal_op,},
139 | {spc_illegal_op,},
140 | {spc_illegal_op,},
141 | {spc_illegal_op,},
142 |
143 | [0xb0 ... 0xff] = {spc_illegal_op},
144 | }
145 | };
146 |
147 | __attribute__((constructor)) static void osd_init(void)
148 | {
149 | device_type_register(&osd_template);
150 | }
151 |
--------------------------------------------------------------------------------
/usr/parser.c:
--------------------------------------------------------------------------------
1 | /*
2 | * lib/parser.c - simple parser for mount, etc. options.
3 | *
4 | * This source code is licensed under the GNU General Public License,
5 | * Version 2. See the file COPYING for more details.
6 | */
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "parser.h"
16 | #include "util.h"
17 |
18 | /**
19 | * match_one: - Determines if a string matches a simple pattern
20 | * @s: the string to examine for presense of the pattern
21 | * @p: the string containing the pattern
22 | * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
23 | * locations.
24 | *
25 | * Description: Determines if the pattern @p is present in string @s. Can only
26 | * match extremely simple token=arg style patterns. If the pattern is found,
27 | * the location(s) of the arguments will be returned in the @args array.
28 | */
29 | static int match_one(char *s, char *p, substring_t args[])
30 | {
31 | char *meta;
32 | int argc = 0;
33 |
34 | if (!p)
35 | return 1;
36 |
37 | while(1) {
38 | int len = -1;
39 | meta = strchr(p, '%');
40 | if (!meta)
41 | return strcmp(p, s) == 0;
42 |
43 | if (strncmp(p, s, meta-p))
44 | return 0;
45 |
46 | s += meta - p;
47 | p = meta + 1;
48 |
49 | if (isdigit(*p))
50 | len = strtoul(p, &p, 10);
51 | else if (*p == '%') {
52 | if (*s++ != '%')
53 | return 0;
54 | p++;
55 | continue;
56 | }
57 |
58 | if (argc >= MAX_OPT_ARGS)
59 | return 0;
60 |
61 | args[argc].from = s;
62 | switch (*p++) {
63 | case 's':
64 | if (strlen(s) == 0)
65 | return 0;
66 | else if (len == -1 || len > strlen(s))
67 | len = strlen(s);
68 | args[argc].to = s + len;
69 | break;
70 | case 'd':
71 | strtol(s, &args[argc].to, 0);
72 | goto num;
73 | case 'u':
74 | strtoul(s, &args[argc].to, 0);
75 | goto num;
76 | case 'o':
77 | strtoul(s, &args[argc].to, 8);
78 | goto num;
79 | case 'x':
80 | strtoul(s, &args[argc].to, 16);
81 | num:
82 | if (args[argc].to == args[argc].from)
83 | return 0;
84 | break;
85 | default:
86 | return 0;
87 | }
88 | s = args[argc].to;
89 | argc++;
90 | }
91 | }
92 |
93 | /**
94 | * match_token: - Find a token (and optional args) in a string
95 | * @s: the string to examine for token/argument pairs
96 | * @table: match_table_t describing the set of allowed option tokens and the
97 | * arguments that may be associated with them. Must be terminated with a
98 | * &struct match_token whose pattern is set to the NULL pointer.
99 | * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
100 | * locations.
101 | *
102 | * Description: Detects which if any of a set of token strings has been passed
103 | * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
104 | * format identifiers which will be taken into account when matching the
105 | * tokens, and whose locations will be returned in the @args array.
106 | */
107 | int match_token(char *s, match_table_t table, substring_t args[])
108 | {
109 | struct match_token *p;
110 |
111 | for (p = table; !match_one(s, p->pattern, args) ; p++)
112 | ;
113 |
114 | return p->token;
115 | }
116 |
117 | /**
118 | * match_number: scan a number in the given base from a substring_t
119 | * @s: substring to be scanned
120 | * @result: resulting integer on success
121 | * @base: base to use when converting string
122 | *
123 | * Description: Given a &substring_t and a base, attempts to parse the substring
124 | * as a number in that base. On success, sets @result to the integer represented
125 | * by the string and returns 0. Returns either -ENOMEM or -EINVAL on failure.
126 | */
127 | static int match_number(substring_t *s, int *result, int base)
128 | {
129 | char *endp;
130 | char *buf;
131 | int ret;
132 |
133 | buf = malloc(s->to - s->from + 1);
134 | if (!buf)
135 | return -ENOMEM;
136 | memcpy(buf, s->from, s->to - s->from);
137 | buf[s->to - s->from] = '\0';
138 | *result = strtol(buf, &endp, base);
139 | ret = 0;
140 | if (endp == buf)
141 | ret = -EINVAL;
142 | free(buf);
143 | return ret;
144 | }
145 |
146 | /**
147 | * match_int: - scan a decimal representation of an integer from a substring_t
148 | * @s: substring_t to be scanned
149 | * @result: resulting integer on success
150 | *
151 | * Description: Attempts to parse the &substring_t @s as a decimal integer. On
152 | * success, sets @result to the integer represented by the string and returns 0.
153 | * Returns either -ENOMEM or -EINVAL on failure.
154 | */
155 | int match_int(substring_t *s, int *result)
156 | {
157 | return match_number(s, result, 0);
158 | }
159 |
160 | /**
161 | * match_octal: - scan an octal representation of an integer from a substring_t
162 | * @s: substring_t to be scanned
163 | * @result: resulting integer on success
164 | *
165 | * Description: Attempts to parse the &substring_t @s as an octal integer. On
166 | * success, sets @result to the integer represented by the string and returns
167 | * 0. Returns either -ENOMEM or -EINVAL on failure.
168 | */
169 | int match_octal(substring_t *s, int *result)
170 | {
171 | return match_number(s, result, 8);
172 | }
173 |
174 | /**
175 | * match_hex: - scan a hex representation of an integer from a substring_t
176 | * @s: substring_t to be scanned
177 | * @result: resulting integer on success
178 | *
179 | * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
180 | * On success, sets @result to the integer represented by the string and
181 | * returns 0. Returns either -ENOMEM or -EINVAL on failure.
182 | */
183 | int match_hex(substring_t *s, int *result)
184 | {
185 | return match_number(s, result, 16);
186 | }
187 |
188 | /**
189 | * match_strcpy: - copies the characters from a substring_t to a string
190 | * @to: string to copy characters to.
191 | * @s: &substring_t to copy
192 | *
193 | * Description: Copies the set of characters represented by the given
194 | * &substring_t @s to the c-style string @to. Caller guarantees that @to is
195 | * large enough to hold the characters of @s.
196 | */
197 | char *match_strncpy(char *to, substring_t *s, size_t n)
198 | {
199 | snprintf(to, n, "%s", s->from);
200 | return to;
201 | }
202 |
203 | /**
204 | * match_strdup: - allocate a new string with the contents of a substring_t
205 | * @s: &substring_t to copy
206 | *
207 | * Description: Allocates and returns a string filled with the contents of
208 | * the &substring_t @s. The caller is responsible for freeing the returned
209 | * string with kfree().
210 | */
211 | char *match_strdup(substring_t *s)
212 | {
213 | size_t n = s->to - s->from + 1;
214 | char *p = malloc(n);
215 | if (p)
216 | match_strncpy(p, s, n);
217 |
218 | return p;
219 | }
220 |
--------------------------------------------------------------------------------
/usr/parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/include/linux/parser.h
3 | *
4 | * Header for lib/parser.c
5 | * Intended use of these functions is parsing filesystem argument lists,
6 | * but could potentially be used anywhere else that simple option=arg
7 | * parsing is required.
8 | */
9 |
10 |
11 | /* associates an integer enumerator with a pattern string. */
12 | struct match_token {
13 | int token;
14 | char *pattern;
15 | };
16 |
17 | typedef struct match_token match_table_t[];
18 |
19 | /* Maximum number of arguments that match_token will find in a pattern */
20 | enum {MAX_OPT_ARGS = 3};
21 |
22 | /* Describe the location within a string of a substring */
23 | typedef struct {
24 | char *from;
25 | char *to;
26 | } substring_t;
27 |
28 | int match_token(char *, match_table_t table, substring_t args[]);
29 | int match_int(substring_t *, int *result);
30 | int match_octal(substring_t *, int *result);
31 | int match_hex(substring_t *, int *result);
32 | char *match_strncpy(char *, substring_t *, size_t);
33 | char *match_strdup(substring_t *);
34 |
--------------------------------------------------------------------------------
/usr/scc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SCSI Controller command processing
3 | *
4 | * Copyright (C) 2007 FUJITA Tomonori
5 | * Copyright (C) 2007 Mike Christie
6 | *
7 | * This program is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU General Public License as
9 | * published by the Free Software Foundation, version 2 of the
10 | * License.
11 | *
12 | * This program is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 | * 02110-1301 USA
21 | */
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "list.h"
31 | #include "util.h"
32 | #include "tgtd.h"
33 | #include "target.h"
34 | #include "driver.h"
35 | #include "scsi.h"
36 | #include "tgtadm_error.h"
37 | #include "spc.h"
38 |
39 | static tgtadm_err scc_lu_init(struct scsi_lu *lu)
40 | {
41 | if (spc_lu_init(lu))
42 | return TGTADM_NOMEM;
43 |
44 | strncpy(lu->attrs.product_id, "Controller",
45 | sizeof(lu->attrs.product_id));
46 | lu->attrs.version_desc[0] = 0x04C0; /* SBC-3 no version claimed */
47 | lu->attrs.version_desc[1] = 0x0960; /* iSCSI */
48 | lu->attrs.version_desc[2] = 0x01fb; /* SCC-2 */
49 |
50 | lu->dev_type_template.lu_online(lu);
51 |
52 | return TGTADM_SUCCESS;
53 | }
54 |
55 | static struct device_type_template scc_template = {
56 | .type = TYPE_RAID,
57 | .lu_init = scc_lu_init,
58 | .lu_config = spc_lu_config,
59 | .lu_online = spc_lu_online,
60 | .lu_offline = spc_lu_offline,
61 | .lu_exit = spc_lu_exit,
62 | .ops = {
63 | {spc_test_unit,},
64 | {spc_illegal_op,},
65 | {spc_illegal_op,},
66 | {spc_request_sense,},
67 | {spc_illegal_op,},
68 | {spc_illegal_op,},
69 | {spc_illegal_op,},
70 | {spc_illegal_op,},
71 |
72 | {spc_illegal_op,},
73 | {spc_illegal_op,},
74 | {spc_illegal_op,},
75 | {spc_illegal_op,},
76 | {spc_illegal_op,},
77 | {spc_illegal_op,},
78 | {spc_illegal_op,},
79 | {spc_illegal_op,},
80 |
81 | /* 0x10 */
82 | {spc_illegal_op,},
83 | {spc_illegal_op,},
84 | {spc_inquiry,},
85 | {spc_illegal_op,},
86 | {spc_illegal_op,},
87 | {spc_illegal_op,},
88 | {spc_illegal_op,},
89 | {spc_illegal_op,},
90 |
91 | {spc_illegal_op,},
92 | {spc_illegal_op,},
93 | {spc_illegal_op,},
94 | {spc_illegal_op,},
95 | {spc_illegal_op,},
96 | {spc_illegal_op,},
97 | {spc_illegal_op,},
98 | {spc_illegal_op,},
99 |
100 | /* 0x20 */
101 | {spc_illegal_op,},
102 | {spc_illegal_op,},
103 | {spc_illegal_op,},
104 | {spc_illegal_op,},
105 | {spc_illegal_op,},
106 | {spc_illegal_op,},
107 | {spc_illegal_op,},
108 | {spc_illegal_op,},
109 |
110 | {spc_illegal_op,},
111 | {spc_illegal_op,},
112 | {spc_illegal_op,},
113 | {spc_illegal_op,},
114 | {spc_illegal_op,},
115 | {spc_illegal_op,},
116 | {spc_illegal_op,},
117 | {spc_test_unit},
118 |
119 | [0x30 ... 0x7f] = {spc_illegal_op,},
120 |
121 | /* 0x80 */
122 | {spc_illegal_op,},
123 | {spc_illegal_op,},
124 | {spc_illegal_op,},
125 | {spc_illegal_op,},
126 | {spc_illegal_op,},
127 | {spc_illegal_op,},
128 | {spc_illegal_op,},
129 | {spc_illegal_op,},
130 |
131 | {spc_illegal_op,},
132 | {spc_illegal_op,},
133 | {spc_illegal_op,},
134 | {spc_illegal_op,},
135 | {spc_illegal_op,},
136 | {spc_illegal_op,},
137 | {spc_illegal_op,},
138 | {spc_test_unit},
139 |
140 | [0x90 ... 0x9f] = {spc_illegal_op,},
141 |
142 | /* 0xA0 */
143 | {spc_report_luns,},
144 | {spc_illegal_op,},
145 | {spc_illegal_op,},
146 | {spc_service_action, maint_in_service_actions,},
147 | {spc_illegal_op,},
148 | {spc_illegal_op,},
149 | {spc_illegal_op,},
150 | {spc_illegal_op,},
151 |
152 | {spc_illegal_op,},
153 | {spc_illegal_op,},
154 | {spc_illegal_op,},
155 | {spc_illegal_op,},
156 | {spc_illegal_op,},
157 | {spc_illegal_op,},
158 | {spc_illegal_op,},
159 | {spc_test_unit,},
160 |
161 | [0xb0 ... 0xff] = {spc_illegal_op},
162 | }
163 | };
164 |
165 | __attribute__((constructor)) static void scc_init(void)
166 | {
167 | device_type_register(&scc_template);
168 | }
169 |
--------------------------------------------------------------------------------
/usr/scsi_cmnd.h:
--------------------------------------------------------------------------------
1 | struct target;
2 | struct mgmt_req;
3 |
4 | /* needs to move somewhere else */
5 | #define SCSI_SENSE_BUFFERSIZE 252
6 |
7 | enum data_direction {
8 | DATA_NONE = 0,
9 | DATA_WRITE = 1,
10 | DATA_READ = 2,
11 | DATA_BIDIRECTIONAL = 3,
12 | };
13 |
14 | struct scsi_data_buffer {
15 | uint64_t buffer;
16 | uint32_t length;
17 | uint32_t transfer_len;
18 | int32_t resid;
19 | };
20 |
21 | struct scsi_cmd {
22 | struct target *c_target;
23 | /* linked it_nexus->cmd_hash_list */
24 | struct list_head c_hlist;
25 | struct list_head qlist;
26 |
27 | uint64_t dev_id;
28 |
29 | struct scsi_lu *dev;
30 | unsigned long state;
31 |
32 | enum data_direction data_dir;
33 | struct scsi_data_buffer in_sdb;
34 | struct scsi_data_buffer out_sdb;
35 |
36 | uint64_t cmd_itn_id;
37 | uint64_t offset;
38 | uint32_t tl;
39 | uint8_t *scb;
40 | int scb_len;
41 | uint8_t lun[8];
42 | int attribute;
43 | uint64_t tag;
44 | int result;
45 | struct mgmt_req *mreq;
46 |
47 | unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
48 | int sense_len;
49 |
50 | struct list_head bs_list;
51 |
52 | struct it_nexus *it_nexus;
53 | struct it_nexus_lu_info *itn_lu_info;
54 | };
55 |
56 | #define scsi_cmnd_accessor(field, type) \
57 | static inline void scsi_set_##field(struct scsi_cmd *scmd, type val) \
58 | { \
59 | scmd->field = val; \
60 | } \
61 | static inline type scsi_get_##field(struct scsi_cmd *scmd) \
62 | { \
63 | return scmd->field; \
64 | }
65 |
66 | scsi_cmnd_accessor(result, int);
67 | scsi_cmnd_accessor(data_dir, enum data_direction);
68 |
69 |
70 | #define scsi_data_buffer_accessor(field, type, set_cast, get_cast) \
71 | scsi_data_buffer_function(in, field, type, set_cast, get_cast) \
72 | scsi_data_buffer_function(out, field, type, set_cast, get_cast)
73 |
74 | #define scsi_data_buffer_function(dir, field, type, set_cast, get_cast) \
75 | static inline void scsi_set_##dir##_##field(struct scsi_cmd *scmd, type val) \
76 | { \
77 | scmd->dir##_sdb.field = set_cast (val); \
78 | } \
79 | static inline type scsi_get_##dir##_##field(struct scsi_cmd *scmd) \
80 | { \
81 | return get_cast (scmd->dir##_sdb.field); \
82 | }
83 |
84 | scsi_data_buffer_accessor(length, uint32_t, ,);
85 | scsi_data_buffer_accessor(transfer_len, uint32_t, ,);
86 | scsi_data_buffer_accessor(resid, int32_t, ,);
87 | scsi_data_buffer_accessor(buffer, void *, (unsigned long), (void *)(unsigned long));
88 |
89 | static inline void scsi_set_in_resid_by_actual(struct scsi_cmd *scmd,
90 | uint32_t transfer_len)
91 | {
92 | uint32_t expected_len = scsi_get_in_length(scmd);
93 | int32_t resid;
94 |
95 | if (transfer_len <= expected_len)
96 | resid = expected_len - transfer_len;
97 | else {
98 | resid = -(int32_t)(transfer_len - expected_len);
99 | transfer_len = expected_len;
100 | }
101 | scsi_set_in_transfer_len(scmd, transfer_len);
102 | scsi_set_in_resid(scmd, resid);
103 | }
104 |
105 | static inline void scsi_set_out_resid_by_actual(struct scsi_cmd *scmd,
106 | uint32_t transfer_len)
107 | {
108 | uint32_t expected_len = scsi_get_out_length(scmd);
109 | int32_t resid;
110 |
111 | if (transfer_len <= expected_len)
112 | resid = expected_len - transfer_len;
113 | else {
114 | resid = -(int32_t)(transfer_len - expected_len);
115 | transfer_len = expected_len;
116 | }
117 | scsi_set_out_transfer_len(scmd, transfer_len);
118 | scsi_set_out_resid(scmd, resid);
119 | }
120 |
121 | enum {
122 | TGT_CMD_QUEUED,
123 | TGT_CMD_PROCESSED,
124 | TGT_CMD_ASYNC,
125 | TGT_CMD_NOT_LAST,
126 | };
127 |
128 | #define CMD_FNS(bit, name) \
129 | static inline void set_cmd_##name(struct scsi_cmd *c) \
130 | { \
131 | (c)->state |= (1UL << TGT_CMD_##bit); \
132 | } \
133 | static inline void clear_cmd_##name(struct scsi_cmd *c) \
134 | { \
135 | (c)->state &= ~(1UL << TGT_CMD_##bit); \
136 | } \
137 | static inline int cmd_##name(const struct scsi_cmd *c) \
138 | { \
139 | return ((c)->state & (1UL << TGT_CMD_##bit)); \
140 | }
141 |
142 | CMD_FNS(QUEUED, queued)
143 | CMD_FNS(PROCESSED, processed)
144 | CMD_FNS(ASYNC, async)
145 | CMD_FNS(NOT_LAST, not_last)
146 |
--------------------------------------------------------------------------------
/usr/smc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SCSI Medium Changer Command
3 | *
4 | * Copyright (C) 2007 Mark Harvey
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; version 2 of the License.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 | */
19 |
20 | #ifndef _SMC_H_
21 | #define _SMC_H_
22 |
23 | #define LOAD 1
24 | #define UNLOAD 0
25 |
26 | /**
27 | * Define for ELEMENT TYPE
28 | */
29 | #define ELEMENT_ANY 0
30 | #define ELEMENT_MEDIUM_TRANSPORT 1
31 | #define ELEMENT_STORAGE 2
32 | #define ELEMENT_MAP 3
33 | #define ELEMENT_DATA_TRANSFER 4
34 |
35 | /**
36 | * struct slot - Virtual Library element
37 | *
38 | * @slot_addr: Slot address - number between 0 & 65535
39 | * @last_addr: Last slot address where media came from
40 | * @asc: ASC/ASCQ for this slot
41 | * @element_type: 1 = Medium Transport, 2 = Storage, 3 = MAP, 4 = drive
42 | * @cart_type: Type of media in this slot
43 | * @status: Different bits used depending on element_type
44 | * @sides: If media is single or double sided
45 | * @barcode: Barcode of media ID
46 | * @drive_tid: TID of DATA TRANSFER DEVICE configured at this slot address.
47 | * @drive_lun: LUN of DATA TRANSFER DEVICE configured at this slot address.
48 | *
49 | * A linked list of slots describing each element within the virtual library
50 | */
51 | struct slot {
52 | struct list_head slot_siblings;
53 | uint16_t slot_addr;
54 | uint16_t last_addr;
55 | uint16_t asc;
56 | uint8_t element_type;
57 | uint8_t cart_type;
58 | uint8_t status;
59 | uint8_t sides;
60 | char barcode[11];
61 | uint8_t drive_tid;
62 | uint64_t drive_lun;
63 | char volume_tag[32];
64 | };
65 |
66 | /**
67 | * struct smc_info - Data structure for SMC device
68 | * @media_home: Home directory for virtual media
69 | * @slots: Linked list of 'slots' within the virtual library
70 | *
71 | */
72 | struct smc_info {
73 | char *media_home;
74 | struct list_head slots;
75 | };
76 |
77 | enum {
78 | Opt_element_type, Opt_start_address,
79 | Opt_quantity, Opt_sides, Opt_clear_slot,
80 | Opt_address, Opt_barcode,
81 | Opt_tid, Opt_lun,
82 | Opt_type, Opt_dump,
83 | Opt_media_home,
84 | Opt_err, Opt_volumetag,
85 | };
86 |
87 | static match_table_t tokens = {
88 | {Opt_element_type, "element_type=%s"},
89 | {Opt_start_address, "start_address=%s"},
90 | {Opt_quantity, "quantity=%s"},
91 | {Opt_sides, "sides=%s"},
92 | {Opt_clear_slot, "clear_slot=%s"},
93 | {Opt_address, "address=%s"},
94 | {Opt_barcode, "barcode=%s"},
95 | {Opt_tid, "tid=%s"},
96 | {Opt_lun, "lun=%s"},
97 | {Opt_type, "type=%s"},
98 | {Opt_dump, "dump=%s"},
99 | {Opt_media_home, "media_home=%s"},
100 | {Opt_volumetag, "volume_tag=%s"},
101 | {Opt_err, NULL},
102 | };
103 |
104 | /**
105 | * struct tmp_param{} -- temporary storage of param values from user
106 | *
107 | * As param parsing is stateless, several params need to be collected
108 | * before we know if we are attempting to configure a slot or adding
109 | * a number of new slots. This is just a temporary holder for all
110 | * possible valid params before processing.
111 | */
112 | struct tmp_param {
113 | int operation;
114 | int element_type;
115 | int start_addr;
116 | int quantity;
117 | int address;
118 | int tid;
119 | uint64_t lun;
120 | char barcode[20];
121 | int sides;
122 | int clear_slot;
123 | char volume_tag[32];
124 | } sv_param;
125 |
126 | #endif // _SMC_H_
127 |
--------------------------------------------------------------------------------
/usr/spc.h:
--------------------------------------------------------------------------------
1 | #ifndef __SPC_H
2 | #define __SPC_H
3 |
4 | extern struct service_action maint_in_service_actions[],
5 | persistent_reserve_in_actions[], persistent_reserve_out_actions[];
6 |
7 | extern int spc_service_action(int host_no, struct scsi_cmd *cmd);
8 | extern int spc_inquiry(int host_no, struct scsi_cmd *cmd);
9 | extern int spc_report_luns(int host_no, struct scsi_cmd *cmd);
10 | extern int spc_start_stop(int host_no, struct scsi_cmd *cmd);
11 | extern int spc_test_unit(int host_no, struct scsi_cmd *cmd);
12 | extern int spc_request_sense(int host_no, struct scsi_cmd *cmd);
13 | extern int spc_prevent_allow_media_removal(int host_no, struct scsi_cmd *cmd);
14 | extern int spc_illegal_op(int host_no, struct scsi_cmd *cmd);
15 | extern int spc_lu_init(struct scsi_lu *lu);
16 | extern int spc_send_diagnostics(int host_no, struct scsi_cmd *cmd);
17 |
18 | typedef tgtadm_err (match_fn_t)(struct scsi_lu *lu, char *params);
19 | extern tgtadm_err lu_config(struct scsi_lu *lu, char *params, match_fn_t *);
20 | extern tgtadm_err spc_lu_config(struct scsi_lu *lu, char *params);
21 | extern void spc_lu_exit(struct scsi_lu *lu);
22 | extern void dump_cdb(struct scsi_cmd *cmd);
23 | extern int spc_mode_sense(int host_no, struct scsi_cmd *cmd);
24 | extern tgtadm_err add_mode_page(struct scsi_lu *lu, char *params);
25 | extern int set_mode_page_changeable_mask(struct scsi_lu *lu, uint8_t pcode,
26 | uint8_t subpcode, uint8_t *mask);
27 | extern struct mode_pg *find_mode_page(struct scsi_lu *lu,
28 | uint8_t pcode, uint8_t subpcode);
29 | extern int spc_mode_select(int host_no, struct scsi_cmd *cmd,
30 | int (*update)(struct scsi_cmd *, uint8_t *, int *));
31 | extern struct vpd *alloc_vpd(uint16_t size);
32 | extern tgtadm_err spc_lu_online(struct scsi_lu *lu);
33 | extern tgtadm_err spc_lu_offline(struct scsi_lu *lu);
34 |
35 | extern int spc_access_check(struct scsi_cmd *cmd);
36 | #endif
37 |
--------------------------------------------------------------------------------
/usr/ssc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SCSI Streaming specific header
3 | */
4 |
5 | #ifndef _SSC_H_
6 | #define _SSC_H_
7 |
8 | struct blk_header_info {
9 | uint32_t ondisk_sz;
10 | uint32_t blk_sz;
11 | uint32_t blk_type;
12 | uint64_t blk_num;
13 | uint64_t prev;
14 | uint64_t curr;
15 | uint64_t next;
16 | };
17 |
18 | /*
19 | * MAM structure based from IBM Ultrium SCSI Reference WB1109-02
20 | */
21 | struct MAM_info {
22 | uint32_t tape_fmt_version;
23 |
24 | uint64_t remaining_capacity;
25 | uint64_t max_capacity;
26 | uint64_t TapeAlert;
27 | uint64_t load_count;
28 | uint64_t MAM_space_remaining;
29 |
30 | uint8_t assigning_organization_1[8];
31 | uint8_t formatted_density_code;
32 | uint8_t initialization_count[2];
33 | uint8_t dev_make_serial_last_load[4][40];
34 |
35 | uint64_t written_in_medium_life;
36 | uint64_t read_in_medium_life;
37 | uint64_t written_in_last_load;
38 | uint64_t read_in_last_load;
39 |
40 | uint8_t medium_manufacturer[8];
41 | uint8_t medium_serial_number[32];
42 | uint32_t medium_length;
43 | uint32_t medium_width;
44 | uint8_t assigning_organization_2[8];
45 | uint8_t medium_density_code;
46 | uint8_t medium_manufacture_date[8];
47 | uint64_t MAM_capacity;
48 | uint8_t medium_type;
49 | uint16_t medium_type_information;
50 |
51 | uint8_t application_vendor[8];
52 | uint8_t application_name[32];
53 | uint8_t application_version[8];
54 | uint8_t user_medium_text_label[160];
55 | uint8_t date_time_last_written[12];
56 | uint8_t localization_identifier;
57 | uint8_t barcode[32];
58 | uint8_t owning_host_textual_name[80];
59 | uint8_t media_pool[160];
60 |
61 | uint8_t vendor_unique[256];
62 |
63 | uint8_t dirty;
64 | };
65 |
66 | struct ssc_info {
67 | uint64_t bytes_read; /* Bytes read this load */
68 | uint64_t bytes_written; /* Bytes written this load */
69 |
70 | struct MAM_info mam;
71 |
72 | struct blk_header_info c_blk; /* Current block header */
73 | };
74 |
75 | #endif
76 |
77 |
--------------------------------------------------------------------------------
/usr/target.h:
--------------------------------------------------------------------------------
1 | #ifndef __TARGET_H__
2 | #define __TARGET_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "mutex.h"
8 |
9 | struct acl_entry {
10 | char *address;
11 | struct list_head aclent_list;
12 | };
13 |
14 | struct iqn_acl_entry {
15 | char *name;
16 | struct list_head iqn_aclent_list;
17 | };
18 |
19 | struct tgt_account {
20 | int out_aid;
21 | int nr_inaccount;
22 | int max_inaccount;
23 | int *in_aids;
24 | };
25 |
26 |
27 | RB_HEAD(lu_tree, scsi_lu);
28 | RB_PROTOTYPE(lu_tree, scsi_lu, device_sibling,);
29 | struct target {
30 | char *name;
31 |
32 | int tid;
33 | int lid;
34 |
35 | enum scsi_target_state target_state;
36 |
37 | struct list_head target_siblings;
38 |
39 | struct list_head device_list;
40 |
41 | struct lu_tree device_tree;
42 |
43 | struct list_head it_nexus_list;
44 |
45 | struct backingstore_template *bst;
46 |
47 | struct list_head acl_list;
48 |
49 | struct list_head iqn_acl_list;
50 |
51 | struct tgt_account account;
52 |
53 | struct list_head lld_siblings;
54 |
55 | struct tgt_evloop *evloop;
56 |
57 | pthread_t ev_td;
58 |
59 | tgt_mutex_t mutex;
60 |
61 | void *lld_target;
62 | };
63 |
64 | struct it_nexus {
65 | uint64_t itn_id;
66 | long ctime;
67 |
68 | struct list_head cmd_list;
69 |
70 | struct target *nexus_target;
71 |
72 | /* the list of i_t_nexus belonging to a target */
73 | struct list_head nexus_siblings;
74 |
75 | /* dirty hack for IBMVIO */
76 | int host_no;
77 |
78 | struct list_head itn_itl_info_list;
79 |
80 | /* only used for show operation */
81 | char *info;
82 | };
83 |
84 | enum {
85 | TGT_QUEUE_BLOCKED,
86 | TGT_QUEUE_DELETED,
87 | };
88 |
89 | #define QUEUE_FNS(bit, name) \
90 | static inline void set_queue_##name(struct tgt_cmd_queue *q) \
91 | { \
92 | (q)->state |= (1UL << TGT_QUEUE_##bit); \
93 | } \
94 | static inline void clear_queue_##name(struct tgt_cmd_queue *q) \
95 | { \
96 | (q)->state &= ~(1UL << TGT_QUEUE_##bit); \
97 | } \
98 | static inline int queue_##name(const struct tgt_cmd_queue *q) \
99 | { \
100 | return ((q)->state & (1UL << TGT_QUEUE_##bit)); \
101 | }
102 |
103 | QUEUE_FNS(BLOCKED, blocked)
104 | QUEUE_FNS(DELETED, deleted)
105 |
106 | static inline int queue_active(const struct tgt_cmd_queue *q)
107 | {
108 | return ((q)->active_cmd);
109 | }
110 |
111 | static inline void target_lock(struct target *t)
112 | {
113 | mutex_lock(&t->mutex);
114 | }
115 |
116 | static inline void target_unlock(struct target *t)
117 | {
118 | mutex_unlock(&t->mutex);
119 | }
120 |
121 | static inline int target_is_locked(struct target *t)
122 | {
123 | return mutex_is_locked(&t->mutex);
124 | }
125 |
126 | static inline void target_assert_locked(struct target *t)
127 | {
128 | mutex_assert_locked(&t->mutex);
129 | }
130 |
131 | static inline void target_assert_unlocked(struct target *t)
132 | {
133 | mutex_assert_unlocked(&t->mutex);
134 | }
135 |
136 | struct target *target_lookup(int tid);
137 |
138 | #endif
139 |
--------------------------------------------------------------------------------
/usr/tgtadm.h:
--------------------------------------------------------------------------------
1 | #ifndef TGTADM_H
2 | #define TGTADM_H
3 |
4 | #define TGT_IPC_DIR "/var/run/tgtd"
5 | #define TGT_IPC_NAMESPACE TGT_IPC_DIR"/socket"
6 | #define TGT_LLD_NAME_LEN 64
7 |
8 | #define GLOBAL_TID (~0U)
9 |
10 | #include "tgtadm_error.h"
11 |
12 | enum tgtadm_op {
13 | OP_NEW,
14 | OP_DELETE,
15 | OP_SHOW,
16 | OP_BIND,
17 | OP_UNBIND,
18 | OP_UPDATE,
19 | OP_STATS,
20 | OP_START,
21 | OP_STOP,
22 | };
23 |
24 | enum tgtadm_mode {
25 | MODE_SYSTEM,
26 | MODE_TARGET,
27 | MODE_DEVICE,
28 | MODE_PORTAL,
29 | MODE_LLD,
30 |
31 | MODE_SESSION,
32 | MODE_CONNECTION,
33 | MODE_ACCOUNT,
34 | };
35 |
36 | enum tgtadm_account_dir {
37 | ACCOUNT_TYPE_INCOMING,
38 | ACCOUNT_TYPE_OUTGOING,
39 | };
40 |
41 | struct tgtadm_req {
42 | enum tgtadm_mode mode;
43 | enum tgtadm_op op;
44 | char lld[TGT_LLD_NAME_LEN];
45 | uint32_t len;
46 | int32_t tid;
47 | uint64_t sid;
48 | uint64_t lun;
49 | uint32_t cid;
50 | uint32_t host_no;
51 | uint32_t device_type;
52 | uint32_t ac_dir;
53 | uint32_t pack;
54 | uint32_t force;
55 | };
56 |
57 | struct tgtadm_rsp {
58 | uint32_t err;
59 | uint32_t len;
60 | };
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/usr/tgtadm_error.h:
--------------------------------------------------------------------------------
1 | #ifndef TGTADM_ERROR_H
2 | #define TGTADM_ERROR_H
3 |
4 | enum tgtadm_errno {
5 | TGTADM_SUCCESS,
6 | TGTADM_UNKNOWN_ERR,
7 | TGTADM_NOMEM,
8 | TGTADM_NO_DRIVER,
9 | TGTADM_NO_TARGET,
10 |
11 | TGTADM_NO_LUN,
12 | TGTADM_NO_SESSION,
13 | TGTADM_NO_CONNECTION,
14 | TGTADM_NO_BINDING,
15 | TGTADM_TARGET_EXIST,
16 | TGTADM_LUN_EXIST,
17 | TGTADM_BINDING_EXIST,
18 |
19 | TGTADM_ACL_EXIST,
20 | TGTADM_ACL_NOEXIST,
21 | TGTADM_USER_EXIST,
22 | TGTADM_NO_USER,
23 | TGTADM_TOO_MANY_USER,
24 | TGTADM_INVALID_REQUEST,
25 |
26 | TGTADM_OUTACCOUNT_EXIST,
27 | TGTADM_TARGET_ACTIVE,
28 | TGTADM_LUN_ACTIVE,
29 | TGTADM_DRIVER_ACTIVE,
30 | TGTADM_UNSUPPORTED_OPERATION,
31 | TGTADM_UNKNOWN_PARAM,
32 |
33 | TGTADM_PREVENT_REMOVAL,
34 | };
35 |
36 | typedef enum tgtadm_errno tgtadm_err;
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/usr/util.c:
--------------------------------------------------------------------------------
1 | /*
2 | * common utility functions
3 | *
4 | * Copyright (C) 2007 FUJITA Tomonori
5 | * Copyright (C) 2007 Mike Christie
6 | *
7 | * This program is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU General Public License as
9 | * published by the Free Software Foundation, version 2 of the
10 | * License.
11 | *
12 | * This program is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 | * 02110-1301 USA
21 | */
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | #include "log.h"
35 | #include "util.h"
36 |
37 | int chrdev_open(char *modname, char *devpath, uint8_t minor, int *fd)
38 | {
39 | FILE *fp;
40 | char name[256], buf[256];
41 | int err, major;
42 |
43 | fp = fopen("/proc/devices", "r");
44 | if (!fp) {
45 | eprintf("Cannot open /proc/devices, %m\n");
46 | return -1;
47 | }
48 |
49 | major = 0;
50 | while (!feof(fp)) {
51 | if (!fgets(buf, sizeof (buf), fp))
52 | break;
53 |
54 | if (sscanf(buf, "%d %s", &major, name) != 2)
55 | continue;
56 |
57 | if (!strcmp(name, modname))
58 | break;
59 | major = 0;
60 | }
61 | fclose(fp);
62 |
63 | if (!major) {
64 | eprintf("cannot find %s in /proc/devices - "
65 | "make sure the module is loaded\n", modname);
66 | return -1;
67 | }
68 |
69 | unlink(devpath);
70 | err = mknod(devpath, (S_IFCHR | 0600), makedev(major, minor));
71 | if (err) {
72 | eprintf("cannot create %s, %m\n", devpath);
73 | return -errno;
74 | }
75 |
76 | *fd = open(devpath, O_RDWR);
77 | if (*fd < 0) {
78 | eprintf("cannot open %s, %m\n", devpath);
79 | return -errno;
80 | }
81 |
82 | return 0;
83 | }
84 |
85 | int backed_file_open(char *path, int oflag, uint64_t *size, uint32_t *blksize)
86 | {
87 | int fd, err;
88 | struct stat64 st;
89 |
90 | fd = open(path, oflag);
91 | if (fd < 0) {
92 | eprintf("Could not open %s, %m\n", path);
93 | return fd;
94 | }
95 |
96 | err = fstat64(fd, &st);
97 | if (err < 0) {
98 | eprintf("Cannot get stat %d, %m\n", fd);
99 | goto close_fd;
100 | }
101 |
102 | if (S_ISREG(st.st_mode)) {
103 | *size = st.st_size;
104 | if (blksize)
105 | *blksize = st.st_blksize;
106 | } else if (S_ISBLK(st.st_mode)) {
107 | err = ioctl(fd, BLKGETSIZE64, size);
108 | if (err < 0) {
109 | eprintf("Cannot get size, %m\n");
110 | goto close_fd;
111 | }
112 | } else {
113 | eprintf("Cannot use this mode %x\n", st.st_mode);
114 | err = -EINVAL;
115 | goto close_fd;
116 | }
117 |
118 | return fd;
119 |
120 | close_fd:
121 | close(fd);
122 | return err;
123 | }
124 |
125 | int set_non_blocking(int fd)
126 | {
127 | int err;
128 |
129 | err = fcntl(fd, F_GETFL);
130 | if (err < 0) {
131 | eprintf("unable to get fd flags, %m\n");
132 | } else {
133 | err = fcntl(fd, F_SETFL, err | O_NONBLOCK);
134 | if (err == -1)
135 | eprintf("unable to set fd flags, %m\n");
136 | else
137 | err = 0;
138 | }
139 | return err;
140 | }
141 |
142 | int str_to_open_flags(char *buf)
143 | {
144 | char *bsoflags_tok = NULL;
145 | int open_flags = 0;
146 |
147 | bsoflags_tok = strtok(buf, ":\0");
148 | while (bsoflags_tok != NULL) {
149 | while (*bsoflags_tok == ' ')
150 | bsoflags_tok++;
151 | if (!strncmp(bsoflags_tok, "sync", 4))
152 | open_flags |= O_SYNC;
153 | else if (!strncmp(bsoflags_tok, "direct", 6))
154 | open_flags |= O_DIRECT;
155 | else {
156 | eprintf("bsoflag option %s not supported\n",
157 | bsoflags_tok);
158 | return -1;
159 | }
160 |
161 | bsoflags_tok = strtok(NULL, ":");
162 | }
163 |
164 | return open_flags;
165 | }
166 |
167 | char *open_flags_to_str(char *dest, int flags)
168 | {
169 | *dest = '\0';
170 |
171 | if (flags & O_SYNC)
172 | strcat(dest, "sync");
173 | if (flags & O_DIRECT) {
174 | if (*dest)
175 | strcat(dest, ":");
176 | strcat(dest, "direct");
177 | }
178 | return dest;
179 | }
180 |
181 | int get_blk_shift(unsigned int size)
182 | {
183 | int shift = 0;
184 |
185 | if (!size)
186 | return -1;
187 |
188 | /* find the first non-zero bit */
189 | while ((size & (1 << shift)) == 0)
190 | shift++;
191 |
192 | /* if more non-zero bits, then size is not a power of 2 */
193 | if (size > (1 << shift))
194 | return -1;
195 |
196 | return shift;
197 | }
198 |
199 | /*
200 | * memory copy for spc-style scsi commands.
201 | * Copy up to src_len bytes from src,
202 | * not exceeding *dst_remain_len bytes available at dst.
203 | * Reflect decreased space in *dst_remain_len.
204 | * Return actually copied length.
205 | */
206 | int spc_memcpy(uint8_t *dst, uint32_t *dst_remain_len,
207 | uint8_t *src, uint32_t src_len)
208 | {
209 | int copy_len = min_t(uint32_t, *dst_remain_len, src_len);
210 |
211 | if (copy_len) {
212 | memcpy(dst, src, copy_len);
213 | *dst_remain_len -= copy_len;
214 | }
215 | return copy_len;
216 | }
217 |
218 | int tgt_get_file_length(int fd, uint64_t *size)
219 | {
220 | int err = 0;
221 | struct stat64 st;
222 |
223 | err = fstat64(fd, &st);
224 | if (err < 0) {
225 | err = -errno;
226 | eprintf("Cannot get stat %d, %m\n", fd);
227 | return err;
228 | }
229 |
230 | if (S_ISREG(st.st_mode)) {
231 | *size = st.st_size;
232 | } else if (S_ISBLK(st.st_mode)) {
233 | err = ioctl(fd, BLKGETSIZE64, size);
234 | if (err < 0) {
235 | err = -errno;
236 | eprintf("Cannot get size %d, %m\n", fd);
237 | }
238 | } else {
239 | err = -EINVAL;
240 | eprintf("Cannot use this file mode %x\n", st.st_mode);
241 | }
242 |
243 | return 0;
244 | }
245 |
246 |
--------------------------------------------------------------------------------
/usr/util.h:
--------------------------------------------------------------------------------
1 | #ifndef __UTIL_H__
2 | #define __UTIL_H__
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include "be_byteshift.h"
20 | #include "mutex.h"
21 |
22 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
23 | #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
24 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
25 | #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
26 |
27 | #if __BYTE_ORDER == __LITTLE_ENDIAN
28 | #define __cpu_to_be16(x) bswap_16(x)
29 | #define __cpu_to_be32(x) bswap_32(x)
30 | #define __cpu_to_be64(x) bswap_64(x)
31 | #define __be16_to_cpu(x) bswap_16(x)
32 | #define __be32_to_cpu(x) bswap_32(x)
33 | #define __be64_to_cpu(x) bswap_64(x)
34 | #define __cpu_to_le32(x) (x)
35 | #else
36 | #define __cpu_to_be16(x) (x)
37 | #define __cpu_to_be32(x) (x)
38 | #define __cpu_to_be64(x) (x)
39 | #define __be16_to_cpu(x) (x)
40 | #define __be32_to_cpu(x) (x)
41 | #define __be64_to_cpu(x) (x)
42 | #define __cpu_to_le32(x) bswap_32(x)
43 | #endif
44 |
45 | #define DEFDMODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
46 | #define DEFFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
47 |
48 | #define min(x,y) ({ \
49 | typeof(x) _x = (x); \
50 | typeof(y) _y = (y); \
51 | (void) (&_x == &_y); \
52 | _x < _y ? _x : _y; })
53 |
54 | #define max(x,y) ({ \
55 | typeof(x) _x = (x); \
56 | typeof(y) _y = (y); \
57 | (void) (&_x == &_y); \
58 | _x > _y ? _x : _y; })
59 |
60 | #define min_t(type,x,y) \
61 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
62 | #define max_t(type,x,y) \
63 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
64 |
65 | extern int get_blk_shift(unsigned int size);
66 | extern int chrdev_open(char *modname, char *devpath, uint8_t minor, int *fd);
67 | extern int backed_file_open(char *path, int oflag, uint64_t *size,
68 | uint32_t *blksize);
69 | extern int set_non_blocking(int fd);
70 | extern int str_to_open_flags(char *buf);
71 | extern char *open_flags_to_str(char *dest, int flags);
72 | extern int spc_memcpy(uint8_t *dst, uint32_t *dst_remain_len,
73 | uint8_t *src, uint32_t src_len);
74 |
75 | #define zalloc(size) \
76 | ({ \
77 | void *ptr = malloc(size); \
78 | if (ptr) \
79 | memset(ptr, 0, size); \
80 | else \
81 | eprintf("%m\n"); \
82 | ptr; \
83 | })
84 |
85 | static inline int before(uint32_t seq1, uint32_t seq2)
86 | {
87 | return (int32_t)(seq1 - seq2) < 0;
88 | }
89 |
90 | static inline int after(uint32_t seq1, uint32_t seq2)
91 | {
92 | return (int32_t)(seq2 - seq1) < 0;
93 | }
94 |
95 | /* is s2<=s1<=s3 ? */
96 | static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
97 | {
98 | return seq3 - seq2 >= seq1 - seq2;
99 | }
100 |
101 | extern unsigned long pagesize, pageshift;
102 |
103 | #if defined(__NR_signalfd) && defined(USE_SIGNALFD)
104 |
105 | /*
106 | * workaround for broken linux/signalfd.h including
107 | * usr/include/linux/fcntl.h
108 | */
109 | #define _LINUX_FCNTL_H
110 |
111 | #include
112 |
113 | static inline int __signalfd(int fd, const sigset_t *mask, int flags)
114 | {
115 | int fd2, ret;
116 |
117 | fd2 = syscall(__NR_signalfd, fd, mask, _NSIG / 8);
118 | if (fd2 < 0)
119 | return fd2;
120 |
121 | ret = fcntl(fd2, F_GETFL);
122 | if (ret < 0) {
123 | close(fd2);
124 | return -1;
125 | }
126 |
127 | ret = fcntl(fd2, F_SETFL, ret | O_NONBLOCK);
128 | if (ret < 0) {
129 | close(fd2);
130 | return -1;
131 | }
132 |
133 | return fd2;
134 | }
135 | #else
136 | #define __signalfd(fd, mask, flags) (-1)
137 | struct signalfd_siginfo {
138 | };
139 | #endif
140 |
141 | /* convert string to integer, check for validity of the string numeric format
142 | * and the natural boundaries of the integer value type (first get a 64-bit
143 | * value and check that it fits the range of the destination integer).
144 | */
145 | #define str_to_int(str, val) \
146 | ({ \
147 | int ret = 0; \
148 | char *ptr; \
149 | unsigned long long ull_val; \
150 | ull_val = strtoull(str, &ptr, 0); \
151 | val = (typeof(val)) ull_val; \
152 | if (ull_val == ULLONG_MAX || ptr == str) \
153 | ret = EINVAL; \
154 | else if (val != ull_val) \
155 | ret = ERANGE; \
156 | ret; \
157 | })
158 |
159 | /* convert to int and check: strictly greater than */
160 | #define str_to_int_gt(str, val, minv) \
161 | ({ \
162 | int ret = str_to_int(str, val); \
163 | if (!ret && (val <= minv)) \
164 | ret = ERANGE; \
165 | ret; \
166 | })
167 |
168 | /* convert and check: greater than or equal */
169 | #define str_to_int_ge(str, val, minv) \
170 | ({ \
171 | int ret = str_to_int(str, val); \
172 | if (!ret && (val < minv)) \
173 | ret = ERANGE; \
174 | ret; \
175 | })
176 |
177 | /* convert and check: strictly less than */
178 | #define str_to_int_lt(str, val, maxv) \
179 | ({ \
180 | int ret = str_to_int(str, val); \
181 | if (!ret && (val >= maxv)) \
182 | ret = ERANGE; \
183 | ret; \
184 | })
185 |
186 | /* convert and check: range, ends inclusive */
187 | #define str_to_int_range(str, val, minv, maxv) \
188 | ({ \
189 | int ret = str_to_int(str, val); \
190 | if (!ret && (val < minv || val > maxv)) \
191 | ret = ERANGE; \
192 | ret; \
193 | })
194 |
195 | struct concat_buf {
196 | FILE *streamf;
197 | int err;
198 | int used;
199 | char *buf;
200 | size_t size;
201 | };
202 |
203 | void concat_buf_init(struct concat_buf *b);
204 | int concat_printf(struct concat_buf *b, const char *format, ...);
205 | const char *concat_delim(struct concat_buf *b, const char *delim);
206 | int concat_buf_finish(struct concat_buf *b);
207 | int concat_write(struct concat_buf *b, int fd, int offset);
208 | void concat_buf_release(struct concat_buf *b);
209 |
210 | int tgt_get_file_length(int fd, uint64_t *size);
211 |
212 |
213 | /* If we have recent enough glibc to support PUNCH HOLE we try to unmap
214 | * the region.
215 | */
216 | static inline int unmap_file_region(int fd, off_t offset, off_t length)
217 | {
218 | #ifdef FALLOC_FL_PUNCH_HOLE
219 | if (fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
220 | offset, length) == 0)
221 | return 0;
222 | #endif
223 | return -1;
224 | }
225 |
226 | #define BITS_PER_LONG __WORDSIZE
227 | #define BITS_PER_BYTE 8
228 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
229 |
230 | static inline void set_bit(int nr, unsigned long *addr)
231 | {
232 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
233 | }
234 |
235 | static inline void clear_bit(int nr, unsigned long *addr)
236 | {
237 | addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
238 | }
239 |
240 | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
241 | {
242 | return ((1UL << (nr % BITS_PER_LONG)) &
243 | (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
244 | }
245 |
246 | #define scsi_sprintf(str, size, format, ...) \
247 | do { \
248 | char buf[size + 1]; \
249 | memset(buf, 0, sizeof(buf)); \
250 | snprintf(buf, sizeof(buf), format, ## __VA_ARGS__); \
251 | memcpy(str, buf, size); \
252 | } while (0)
253 |
254 | #endif
255 |
--------------------------------------------------------------------------------
/usr/work.h:
--------------------------------------------------------------------------------
1 | #ifndef __WORK_H
2 | #define __WORK_H
3 |
4 | #include
5 |
6 | struct tgt_work {
7 | struct list_head entry;
8 | void (*func)(struct tgt_work *);
9 | void *data;
10 | unsigned int when;
11 | struct tgt_evloop *evloop;
12 | };
13 |
14 | struct tgt_evloop;
15 |
16 | extern int work_timer_start(struct tgt_evloop *evloop);
17 | extern void work_timer_stop(struct tgt_evloop *evloop);
18 |
19 | extern void ev_add_work(struct tgt_evloop *evloop, struct tgt_work *work, unsigned int second);
20 | extern void ev_del_work(struct tgt_evloop *evloop, struct tgt_work *work);
21 | extern void add_work(struct tgt_work *work, unsigned int second);
22 | extern void del_work(struct tgt_work *work);
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------