├── .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.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 ├── 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 ├── initd.sample ├── openrc │ ├── tgtd.confd │ └── tgtd.initd ├── tgt-admin ├── tgt-core-test ├── tgt-setup-lun ├── tgt.bashcomp.sh ├── tgtd.service └── tgtd.spec └── usr ├── Makefile ├── be_byteshift.h ├── bs.c ├── bs_aio.c ├── bs_aio.h ├── 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 ├── libcrc32c.c ├── libssc.c ├── libssc.h ├── list.h ├── log.c ├── log.h ├── media.h ├── mgmt.c ├── mmc.c ├── 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_ubuntu: 7 | name: build on Ubuntu 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 | build_alpine: 19 | name: build on Alpine Linux 20 | runs-on: ubuntu-22.04 21 | steps: 22 | - name: checking out 23 | uses: actions/checkout@v3 24 | with: 25 | path: tgt 26 | - name: Setup Alpine Linux 27 | uses: jirutka/setup-alpine@v1 28 | 29 | - name: build 30 | working-directory: tgt 31 | run: | 32 | make 33 | -------------------------------------------------------------------------------- /.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.96 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 ISCSI_RDMA 14 | export CEPH_RBD 15 | export GLFS_BD 16 | export SD_NOTIFY 17 | 18 | .PHONY: all 19 | all: programs doc conf scripts 20 | 21 | # Targets for the /usr/sbin utilities 22 | .PHONY: programs install-programs clean-programs 23 | programs: 24 | $(MAKE) -C usr 25 | 26 | install-programs: 27 | $(MAKE) -C usr install 28 | 29 | clean-programs: 30 | $(MAKE) -C usr clean 31 | 32 | # Targets for man pages and other documentation 33 | .PHONY: doc install-doc clean-doc 34 | doc: 35 | $(MAKE) -C doc 36 | 37 | install-doc: 38 | $(MAKE) -C doc install 39 | 40 | clean-doc: 41 | $(MAKE) -C doc clean 42 | 43 | # Targets for scripts 44 | .PHONY: scripts install-scripts clean-scripts 45 | scripts: 46 | $(MAKE) -C scripts 47 | 48 | install-scripts: 49 | $(MAKE) -C scripts install 50 | 51 | clean-scripts: 52 | $(MAKE) -C scripts clean 53 | 54 | 55 | # Targets for configuration stubs 56 | .PHONY: conf install-conf clean-conf 57 | conf: 58 | $(MAKE) -C conf 59 | 60 | install-conf: 61 | $(MAKE) -C conf install 62 | 63 | clean-conf: 64 | $(MAKE) -C conf clean 65 | 66 | .PHONY: install 67 | install: install-programs install-doc install-conf install-scripts 68 | 69 | .PHONY: rpm 70 | rpm: 71 | @./scripts/build-pkg.sh rpm 72 | 73 | .PHONY: deb 74 | deb: 75 | @./scripts/build-pkg.sh deb 76 | 77 | .PHONY: clean 78 | clean-pkg: 79 | rm -fr pkg 80 | 81 | .PHONY: clean 82 | clean: clean-programs clean-doc clean-conf clean-scripts clean-pkg 83 | 84 | .PHONY:check 85 | check: ARCH=$(shell sh scripts/checkarch.sh) 86 | check: 87 | CC=$(CHECK_CC_FLAGS) $(MAKE) all 88 | 89 | .PHONY:check32 90 | check32: override ARCH=-m32 91 | check32: 92 | CC=$(CHECK_CC_FLAGS) $(MAKE) all 93 | 94 | .PHONY:check64 95 | check64: override ARCH=-m64 96 | check64: 97 | CC=$(CHECK_CC_FLAGS) $(MAKE) all 98 | 99 | cscope: 100 | find -name '*.[ch]' > cscope.files 101 | cscope -bq 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | The Linux target framework (tgt) is a user space SCSI target framework 3 | that supports the iSCSI and iSER transport protocols and that supports 4 | multiple methods for accessing block storage. Tgt consists of 5 | user-space daemon and tools. 6 | 7 | Currently, tgt supports the following SCSI transport protocols: 8 | - iSCSI software target driver for Ethernet NICs 9 | - iSER software target driver for Infiniband and RDMA NICs 10 | 11 | Tgt supports the following methods for accessing local storage: 12 | - aio, the asynchronous I/O interface also known as libaio. 13 | - rdwr, smc and mmc, synchronous I/O based on the pread() and pwrite() 14 | system calls. 15 | - null, discards all data and reads zeroes. 16 | - ssc, SCSI tape support. 17 | - sg and bsg, SCSI pass-through. 18 | - glfs, the GlusterFS network filesystem. 19 | - rbd, Ceph's distributed-storage RADOS Block Device. 20 | - sheepdog, a distributed object storage system. 21 | 22 | Tgt can emulate the following SCSI device types: 23 | - SBC: a virtual disk drive that can use a file to store the content. 24 | - SMC: a virtual media jukebox that can be controlled by the "mtx" 25 | tool. 26 | - MMC: a virtual DVD drive that can read DVD-ROM iso files and create 27 | burnable DVD+R. It can be combined with SMC to provide a fully 28 | operational DVD jukebox. 29 | - SSC: a virtual tape device (aka VTL) that can use a file to store 30 | the content. 31 | - OSD: a virtual object-based storage device that can use a file to 32 | store the content (in progress). 33 | 34 | 35 | ## License 36 | The code is released under the GNU General Public License version 2. 37 | 38 | 39 | ## Requirements 40 | Target drivers have their own ways to build, configure, etc. Please 41 | find an appropriate documentation in the doc directory. 42 | 43 | 44 | ## Developer Notes 45 | The central communication channel for tgt development is the mailing list 46 | (). 47 | 48 | First, please read the following documents (in short, follow Linux 49 | kernel development rules): 50 | 51 | - https://www.kernel.org/doc/Documentation/process/coding-style.rst 52 | - https://www.kernel.org/doc/Documentation/process/submitting-patches.rst 53 | 54 | Then, check your patches with the patch style checker prior to 55 | submission (scripts/checkpatch.pl) like the following example. 56 | 57 | fujita@arbre:~/git/tgt$ ./scripts/checkpatch.pl ~/0001-add-bidi-support.patch 58 | Your patch has no obvious style problems and is ready for submission. 59 | -------------------------------------------------------------------------------- /conf/Makefile: -------------------------------------------------------------------------------- 1 | sysconfdir ?= /etc 2 | docdatadir ?= /usr/share/doc/packages 3 | 4 | EXAMPLES = targets.conf.example targets.conf.vtl.L700 targets.conf.vtl.MSL2024 5 | 6 | .PHONY: all 7 | all: 8 | 9 | .PHONY: install 10 | install: 11 | install -d -m 755 $(DESTDIR)$(sysconfdir)/tgt 12 | if [ ! -f $(DESTDIR)$(sysconfdir)/tgt/targets.conf ] ; then \ 13 | install -m 644 targets.conf $(DESTDIR)$(sysconfdir)/tgt ; \ 14 | fi 15 | install -d -m 755 $(DESTDIR)$(docdatadir)/tgt/examples 16 | for f in $(EXAMPLES) ; do \ 17 | install -m 644 examples/$$f $(DESTDIR)$(docdatadir)/tgt/examples ;\ 18 | done 19 | install -d $(DESTDIR)$(sysconfdir)/tgt/conf.d 20 | 21 | .PHONY: clean 22 | clean: 23 | 24 | -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /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 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/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/openrc/tgtd.confd: -------------------------------------------------------------------------------- 1 | # Here you can specify options that are passed directly to tgt daemon 2 | #tgtd_opts="" 3 | 4 | # Config file for automatic configuration with tgt-admin 5 | #tgtd_conf="/etc/tgt/targets.conf" 6 | -------------------------------------------------------------------------------- /scripts/openrc/tgtd.initd: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | # Copyright 1999-2019 Gentoo Authors 3 | # Distributed under the terms of the GNU General Public License v2 4 | 5 | # shellcheck shell=sh 6 | 7 | # Default configuration fike 8 | : "${tgtd_conf:=/etc/tgt/targets.conf}" 9 | 10 | pidfile="/var/run/${RC_SVCNAME}.pid" 11 | command="/usr/sbin/tgtd" 12 | command_args_background="--pid-file ${pidfile} ${tgtd_opts}" 13 | extra_commands="forcedstop" 14 | extra_started_commands="forcedreload reload" 15 | 16 | depend() { 17 | use net 18 | } 19 | 20 | start_post() { 21 | # We need to wait for 1 second before do anything with tgtd. 22 | sleep 1 23 | # Put tgtd into "offline" state until all the targets are configured. 24 | # We don't want initiators to (re)connect and fail the connection 25 | # if configuration is not ready. 26 | tgtadm --op update --mode sys --name State -v offline 27 | 28 | # Configure the targets. 29 | if [ ! -r "${tgtd_conf}" ]; then 30 | ewarn "Configuration file '${tgtd_conf}' not found!" 31 | ewarn "Leaving ${SVCNAME} running in 'offline' state." 32 | eend 0 33 | else 34 | ebegin "Loading target configuration" 35 | tgt-admin --update ALL -c "${tgtd_conf}" 36 | retval=$? 37 | if [ $retval -ne 0 ]; then 38 | eerror "Could not load configuration!" 39 | stop 40 | exit $? 41 | fi 42 | eend $retval 43 | 44 | # Put tgtd into "ready" state. 45 | ebegin "Onlining targets. Accepting connections" 46 | tgtadm --op update --mode sys --name State -v ready 47 | eend $? 48 | fi 49 | } 50 | 51 | stop() { 52 | ebegin "Stopping ${SVCNAME}" 53 | # We need to force shutdown if system is restarting 54 | # or shutting down. 55 | if [ "$RC_RUNLEVEL" = "shutdown" ] ; then 56 | forcedstop 57 | else 58 | # Remove all targets. Only remove targets which are not in use. 59 | tgt-admin --update ALL -c /dev/null >/dev/null 2>&1 60 | retval=$? 61 | if [ $retval -eq 107 ] ; then 62 | einfo "tgtd is not running" 63 | else 64 | # tgtd will exit if all targets were removed. 65 | tgtadm --op delete --mode system >/dev/null 2>&1 66 | retval=$? 67 | if [ $retval -ne 0 ] ; then 68 | eerror "WARNING: Some initiators are still connected - could not stop tgtd" 69 | fi 70 | fi 71 | fi 72 | eend $retval 73 | } 74 | 75 | forcedstop() { 76 | # NOTE: Forced shutdown of the iscsi target may cause data corruption 77 | # for initiators that are connected. 78 | ewarn "WARNING: Force-stopping target framework daemon" 79 | for i in 5 4 3 2 1; do 80 | einfo "Continuing in $i seconds..." 81 | sleep 1 82 | done 83 | 84 | # Offline everything first. May be needed if we're rebooting, but 85 | # expect the initiators to reconnect cleanly when we boot again 86 | # (i.e. we don't want them to reconnect to a tgtd which is still 87 | # onlineg, but the target is gone). 88 | tgtadm --op update --mode sys --name State -v offline >/dev/null 2>&1 89 | retval=$? 90 | if [ $retval -eq 107 ] ; then 91 | einfo "tgtd is not running" 92 | else 93 | # Offline all targets 94 | tgt-admin --offline ALL 95 | 96 | # Remove all targets, even if they are still in use. 97 | tgt-admin --update ALL -c /dev/null -f 98 | 99 | # tgtd shuts down after all targets are removed. 100 | tgtadm --op delete --mode system 101 | retval=$? 102 | if [ $retval -ne 0 ] ; then 103 | eerror "Failed to shutdown tgtd" 104 | eend 1 105 | fi 106 | fi 107 | eend $retval 108 | } 109 | 110 | reload() { 111 | ebegin "Updating target framework daemon configuration" 112 | # Update configuration for targets. Only targets which 113 | # are not in use will be updated. 114 | tgt-admin --update ALL -c "${tgtd_conf}" >/dev/null 2>&1 115 | retval=$? 116 | if [ $retval -eq 107 ]; then 117 | ewarn "WARNING: tgtd is not running" 118 | fi 119 | eend $retval 120 | } 121 | 122 | forcedreload() { 123 | ebegin "Updating target framework daemon configuration" 124 | ewarn "WARNING: Force-updating running configuration!" 125 | # Update configuration for targets, even those in use. 126 | tgt-admin --update ALL -f -c "${tgtd_conf}" >/dev/null 2>&1 127 | retval=$? 128 | if [ $retval -eq 107 ]; then 129 | ewarn "WARNING: tgtd is not running" 130 | fi 131 | eend $retval 132 | } 133 | 134 | status_post() { 135 | einfo "Run 'tgt-admin -s' to see detailed target info." 136 | } 137 | -------------------------------------------------------------------------------- /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 | 46 | %{__install} -p -m 0755 scripts/tgt-setup-lun %{buildroot}%{_sbindir} 47 | %{__install} -p -m 0755 scripts/initd.sample %{buildroot}%{_initrddir}/tgtd 48 | %{__install} -p -m 0755 scripts/tgt-admin %{buildroot}/%{_sbindir}/tgt-admin 49 | %{__install} -p -m 0644 scripts/tgt.bashcomp.sh %{buildroot}/etc/bash_completion.d/tgt 50 | %{__install} -p -m 0644 doc/manpages/targets.conf.5 %{buildroot}/%{_mandir}/man5 51 | %{__install} -p -m 0644 doc/manpages/tgtadm.8 %{buildroot}/%{_mandir}/man8 52 | %{__install} -p -m 0644 doc/manpages/tgt-admin.8 %{buildroot}/%{_mandir}/man8 53 | %{__install} -p -m 0644 doc/manpages/tgt-setup-lun.8 %{buildroot}/%{_mandir}/man8 54 | %{__install} -p -m 0644 doc/manpages/tgtimg.8 %{buildroot}/%{_mandir}/man8 55 | %{__install} -p -m 0600 conf/targets.conf %{buildroot}/etc/tgt 56 | 57 | pushd usr 58 | %{__make} install DESTDIR=%{buildroot} sbindir=%{_sbindir} 59 | 60 | 61 | %post 62 | /sbin/chkconfig --add tgtd 63 | 64 | %postun 65 | if [ "$1" = "1" ] ; then 66 | /sbin/service tgtd condrestart > /dev/null 2>&1 || : 67 | fi 68 | 69 | %preun 70 | if [ "$1" = "0" ] ; then 71 | /sbin/chkconfig tgtd stop > /dev/null 2>&1 72 | /sbin/chkconfig --del tgtd 73 | fi 74 | 75 | 76 | %clean 77 | %{__rm} -rf %{buildroot} 78 | 79 | 80 | %files 81 | %defattr(-, root, root, -) 82 | %doc README doc/README.iscsi doc/README.iser doc/README.lu_configuration doc/README.mmc 83 | %{_sbindir}/tgtd 84 | %{_sbindir}/tgtadm 85 | %{_sbindir}/tgt-setup-lun 86 | %{_sbindir}/tgt-admin 87 | %{_sbindir}/tgtimg 88 | %{_mandir}/man5/* 89 | %{_mandir}/man8/* 90 | %{_initrddir}/tgtd 91 | /etc/bash_completion.d/tgt 92 | %attr(0600,root,root) %config(noreplace) /etc/tgt/targets.conf 93 | -------------------------------------------------------------------------------- /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 | ifneq ($(CEPH_RBD),) 17 | MODULES += bs_rbd.so 18 | endif 19 | 20 | ifneq ($(GLFS_BD),) 21 | MODULES += bs_glfs.so 22 | endif 23 | 24 | ifneq ($(SD_NOTIFY),) 25 | CFLAGS += -DUSE_SYSTEMD 26 | endif 27 | 28 | ifneq ($(shell test -e /usr/include/sys/eventfd.h && test -e /usr/include/libaio.h && echo 1),) 29 | CFLAGS += -DUSE_EVENTFD 30 | TGTD_OBJS += bs_aio.o 31 | LIBS += -laio 32 | endif 33 | 34 | ifneq ($(ISCSI_RDMA),) 35 | TGTD_OBJS += iscsi/iser.o iscsi/iser_text.o 36 | LIBS += -libverbs -lrdmacm 37 | endif 38 | 39 | INCLUDES += -I. 40 | 41 | CFLAGS += -D_FILE_OFFSET_BITS=64 42 | CFLAGS += -D_GNU_SOURCE 43 | CFLAGS += $(INCLUDES) 44 | ifneq ($(DEBUG),) 45 | CFLAGS += -g -O0 -ggdb -rdynamic 46 | else 47 | CFLAGS += -g -O2 -fno-strict-aliasing 48 | endif 49 | CFLAGS += -Wall -Wstrict-prototypes -Werror -fPIC 50 | CFLAGS += -DTGT_VERSION=\"$(VERSION)$(EXTRAVERSION)\" 51 | CFLAGS += -DBSDIR=\"$(DESTDIR)$(libdir)/backing-store\" 52 | 53 | LIBS += -lpthread -ldl 54 | 55 | ifneq ($(SD_NOTIFY),) 56 | LIBS += -lsystemd 57 | endif 58 | 59 | PROGRAMS += tgtd tgtadm tgtimg 60 | TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \ 61 | concat_buf.o parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o \ 62 | ssc.o libssc.o bs_rdwr.o bs_ssc.o \ 63 | bs_null.o bs_sg.o bs.o libcrc32c.o bs_sheepdog.o 64 | 65 | TGTD_DEP = $(TGTD_OBJS:.o=.d) 66 | 67 | LDFLAGS = -Wl,-E,-rpath=$(libdir) 68 | 69 | .PHONY:all 70 | all: $(PROGRAMS) $(MODULES) 71 | 72 | tgtd: $(TGTD_OBJS) 73 | echo $(CC) $^ -o $@ $(LIBS) 74 | $(CC) $^ -o $@ $(LDFLAGS) $(LIBS) 75 | 76 | -include $(TGTD_DEP) 77 | 78 | TGTADM_OBJS = tgtadm.o concat_buf.o 79 | TGTADM_DEP = $(TGTADM_OBJS:.o=.d) 80 | 81 | tgtadm: $(TGTADM_OBJS) 82 | $(CC) $^ -o $@ 83 | 84 | -include $(TGTADM_DEP) 85 | 86 | TGTIMG_OBJS = tgtimg.o libssc.o libcrc32c.o 87 | TGTIMG_DEP = $(TGTIMG_OBJS:.o=.d) 88 | 89 | tgtimg: $(TGTIMG_OBJS) 90 | $(CC) $^ -o $@ 91 | 92 | -include $(TGTIMG_DEP) 93 | 94 | %.o: %.c 95 | $(CC) -c $(CFLAGS) $*.c -o $*.o 96 | @$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c 97 | 98 | %.so: %.c 99 | $(CC) -shared $(CFLAGS) $*.c -o $*.so 100 | 101 | bs_rbd.so: bs_rbd.c 102 | $(CC) -shared $(CFLAGS) bs_rbd.c -o bs_rbd.so -lrados -lrbd 103 | 104 | bs_glfs.so: bs_glfs.c 105 | $(CC) -I/usr/include/glusterfs/api -shared $(CFLAGS) bs_glfs.c -o bs_glfs.so -lgfapi 106 | 107 | .PHONY: install 108 | install: $(PROGRAMS) $(MODULES) 109 | install -d -m 755 $(DESTDIR)$(sbindir) 110 | install -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir) 111 | ifneq ($(MODULES),) 112 | install -d -m 755 $(DESTDIR)$(libdir)/backing-store 113 | install -m 755 $(MODULES) $(DESTDIR)$(libdir)/backing-store 114 | endif 115 | 116 | .PHONY: clean 117 | clean: 118 | rm -f *.[od] *.so $(PROGRAMS) iscsi/*.[od] 119 | -------------------------------------------------------------------------------- /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, 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, p); 73 | } 74 | 75 | static inline void put_unaligned_be64(uint64_t val, void *p) 76 | { 77 | __put_unaligned_be64(val, 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 bs_thread_info { 4 | pthread_t *worker_thread; 5 | int nr_worker_threads; 6 | 7 | /* wokers sleep on this and signaled by tgtd */ 8 | pthread_cond_t pending_cond; 9 | /* locked by tgtd and workers */ 10 | pthread_mutex_t pending_lock; 11 | /* protected by pending_lock */ 12 | struct list_head pending_list; 13 | 14 | request_func_t *request_fn; 15 | }; 16 | 17 | static inline struct bs_thread_info *BS_THREAD_I(struct scsi_lu *lu) 18 | { 19 | return (struct bs_thread_info *) ((char *)lu + sizeof(*lu)); 20 | } 21 | 22 | extern tgtadm_err bs_thread_open(struct bs_thread_info *info, request_func_t *rfn, 23 | int nr_threads); 24 | extern void bs_thread_close(struct bs_thread_info *info); 25 | extern int bs_thread_cmd_submit(struct scsi_cmd *cmd); 26 | extern int nr_iothreads; 27 | -------------------------------------------------------------------------------- /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)(int, 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 | const char *default_bst; 40 | 41 | struct list_head target_list; 42 | }; 43 | 44 | extern struct tgt_driver *tgt_drivers[]; 45 | extern int get_driver_index(char *name); 46 | extern int register_driver(struct tgt_driver *drv); 47 | extern const char *driver_state_name(struct tgt_driver *drv); 48 | 49 | #endif /* __DRIVER_H__ */ 50 | -------------------------------------------------------------------------------- /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 "util.h" 32 | 33 | static LIST_HEAD(sessions_list); 34 | 35 | struct iscsi_session *session_find_name(int tid, const char *iname, uint8_t *isid) 36 | { 37 | struct iscsi_session *session; 38 | struct iscsi_target *target; 39 | 40 | target = target_find_by_id(tid); 41 | if (!target) 42 | return NULL; 43 | 44 | dprintf("session_find_name: %s %x %x %x %x %x %x\n", iname, 45 | isid[0], isid[1], isid[2], isid[3], isid[4], isid[5]); 46 | list_for_each_entry(session, &target->sessions_list, slist) { 47 | if (!memcmp(isid, session->isid, sizeof(session->isid)) && 48 | !strcmp(iname, session->initiator)) 49 | return session; 50 | } 51 | 52 | return NULL; 53 | } 54 | 55 | struct iscsi_session *session_lookup_by_tsih(uint16_t tsih) 56 | { 57 | struct iscsi_session *session; 58 | list_for_each_entry(session, &sessions_list, hlist) { 59 | if (session->tsih == tsih) 60 | return session; 61 | } 62 | return NULL; 63 | } 64 | 65 | int session_create(struct iscsi_connection *conn) 66 | { 67 | int err; 68 | struct iscsi_session *session = NULL; 69 | static uint16_t tsih, last_tsih = 0; 70 | struct iscsi_target *target; 71 | char addr[128]; 72 | 73 | 74 | target = target_find_by_id(conn->tid); 75 | if (!target) 76 | return -EINVAL; 77 | 78 | for (tsih = last_tsih + 1; tsih != last_tsih; tsih++) { 79 | if (!tsih) 80 | continue; 81 | session = session_lookup_by_tsih(tsih); 82 | if (!session) 83 | break; 84 | } 85 | if (session) 86 | return -EINVAL; 87 | 88 | session = zalloc(sizeof(*session)); 89 | if (!session) 90 | return -ENOMEM; 91 | 92 | session->initiator = strdup(conn->initiator); 93 | if (!session->initiator) { 94 | free(session); 95 | return -ENOMEM; 96 | } 97 | 98 | if (conn->initiator_alias) { 99 | session->initiator_alias = strdup(conn->initiator_alias); 100 | if (!session->initiator_alias) { 101 | free(session->initiator); 102 | free(session); 103 | return -ENOMEM; 104 | } 105 | } 106 | 107 | session->info = zalloc(1024); 108 | if (!session->info) { 109 | free(session->initiator); 110 | free(session->initiator_alias); 111 | free(session); 112 | return -ENOMEM; 113 | } 114 | 115 | memset(addr, 0, sizeof(addr)); 116 | conn->tp->ep_show(conn, addr, sizeof(addr)); 117 | 118 | snprintf(session->info, 1024, _TAB3 "Initiator: %s alias: %s\n" 119 | _TAB3 "Connection: %u\n" 120 | _TAB4 "%s\n", session->initiator, 121 | session->initiator_alias ? session->initiator_alias : "none", 122 | conn->cid, addr); 123 | 124 | err = it_nexus_create(target->tid, tsih, 0, session->info); 125 | if (err) { 126 | free(session->initiator); 127 | free(session->initiator_alias); 128 | free(session->info); 129 | free(session); 130 | return err; 131 | } 132 | 133 | session->target = target; 134 | INIT_LIST_HEAD(&session->slist); 135 | list_add(&session->slist, &target->sessions_list); 136 | 137 | INIT_LIST_HEAD(&session->conn_list); 138 | INIT_LIST_HEAD(&session->cmd_list); 139 | INIT_LIST_HEAD(&session->pending_cmd_list); 140 | 141 | memcpy(session->isid, conn->isid, sizeof(session->isid)); 142 | session->tsih = last_tsih = tsih; 143 | 144 | session->rdma = conn->tp->rdma; 145 | 146 | conn_add_to_session(conn, session); 147 | 148 | dprintf("session_create: %#" PRIx64 "\n", sid64(conn->isid, session->tsih)); 149 | 150 | list_add(&session->hlist, &sessions_list); 151 | session->exp_cmd_sn = conn->exp_cmd_sn; 152 | 153 | memcpy(session->session_param, conn->session_param, 154 | sizeof(session->session_param)); 155 | 156 | session->max_queue_cmd = 157 | session->session_param[ISCSI_PARAM_MAX_QUEUE_CMD].val; 158 | 159 | return 0; 160 | } 161 | 162 | static void session_destroy(struct iscsi_session *session) 163 | { 164 | if (!list_empty(&session->conn_list)) { 165 | eprintf("%d conn_list is not null\n", session->tsih); 166 | return; 167 | } 168 | 169 | if (session->target) { 170 | list_del(&session->slist); 171 | /* session->target->nr_sessions--; */ 172 | it_nexus_destroy(session->target->tid, session->tsih); 173 | } 174 | 175 | list_del(&session->hlist); 176 | 177 | free(session->initiator); 178 | free(session->initiator_alias); 179 | free(session->info); 180 | free(session); 181 | } 182 | 183 | void session_get(struct iscsi_session *session) 184 | { 185 | session->refcount++; 186 | } 187 | 188 | void session_put(struct iscsi_session *session) 189 | { 190 | if (!--session->refcount) 191 | session_destroy(session); 192 | } 193 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 10 | struct iscsi_transport { 11 | struct list_head iscsi_transport_siblings; 12 | 13 | const char *name; 14 | int rdma; 15 | int data_padding; 16 | 17 | int (*ep_init) (void); 18 | void (*ep_exit) (void); 19 | int (*ep_login_complete)(struct iscsi_connection *conn); 20 | struct iscsi_task *(*alloc_task)(struct iscsi_connection *conn, 21 | size_t ext_len); 22 | void (*free_task)(struct iscsi_task *task); 23 | size_t (*ep_read)(struct iscsi_connection *conn, void *buf, 24 | size_t nbytes); 25 | size_t (*ep_write_begin)(struct iscsi_connection *conn, void *buf, 26 | size_t nbytes); 27 | void (*ep_write_end)(struct iscsi_connection *conn); 28 | int (*ep_rdma_read)(struct iscsi_connection *conn); 29 | int (*ep_rdma_write)(struct iscsi_connection *conn); 30 | size_t (*ep_close)(struct iscsi_connection *conn); 31 | void (*ep_force_close)(struct iscsi_connection *conn); 32 | void (*ep_release)(struct iscsi_connection *conn); 33 | 34 | int (*ep_show)(struct iscsi_connection *conn, char *buf, int rest); 35 | void (*ep_event_modify)(struct iscsi_connection *conn, int events); 36 | void *(*alloc_data_buf)(struct iscsi_connection *conn, size_t sz); 37 | void (*free_data_buf)(struct iscsi_connection *conn, void *buf); 38 | int (*ep_getsockname)(struct iscsi_connection *conn, 39 | struct sockaddr *sa, socklen_t *len); 40 | int (*ep_getpeername)(struct iscsi_connection *conn, 41 | struct sockaddr *sa, socklen_t *len); 42 | void (*ep_nop_reply) (long ttt); 43 | }; 44 | 45 | extern int iscsi_transport_register(struct iscsi_transport *); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /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.c: -------------------------------------------------------------------------------- 1 | /* 2 | * helpers for assessing to ssc on-disk structures 3 | * 4 | * Copyright (C) 2008 FUJITA Tomonori 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 | #include 27 | #include "bs_ssc.h" 28 | #include "ssc.h" 29 | #include "be_byteshift.h" 30 | #include "crc32c.h" 31 | 32 | #define SSC_1ST_HDR_OFFSET (sizeof(struct MAM) + SSC_BLK_HDR_SIZE) 33 | 34 | #define SSC_GET_MAM_INFO_VAL(member, bits)\ 35 | {\ 36 | (i)->member = get_unaligned_be##bits(&((m)->member));\ 37 | } 38 | 39 | #define SSC_GET_MAM_INFO_ARRAY(member)\ 40 | {\ 41 | memcpy((i)->member, (m)->member, sizeof((m)->member));\ 42 | } 43 | 44 | static inline uint8_t get_unaligned_be8(const uint8_t *p) 45 | { 46 | return p[0]; 47 | } 48 | 49 | int ssc_read_mam_info(int fd, struct MAM_info *i) 50 | { 51 | struct MAM mam, *m; 52 | int ret; 53 | 54 | m = &mam; 55 | 56 | ret = pread(fd, m, sizeof(struct MAM), SSC_BLK_HDR_SIZE); 57 | if (ret != sizeof(struct MAM)) 58 | return 1; 59 | 60 | if (lseek(fd, SSC_1ST_HDR_OFFSET, SEEK_SET) != SSC_1ST_HDR_OFFSET) 61 | return 1; 62 | 63 | SSC_GET_MAM_INFO_VAL(tape_fmt_version, 32); 64 | 65 | SSC_GET_MAM_INFO_VAL(remaining_capacity, 64); 66 | SSC_GET_MAM_INFO_VAL(max_capacity, 64); 67 | SSC_GET_MAM_INFO_VAL(TapeAlert, 64); 68 | SSC_GET_MAM_INFO_VAL(load_count, 64); 69 | SSC_GET_MAM_INFO_VAL(MAM_space_remaining, 64); 70 | 71 | SSC_GET_MAM_INFO_ARRAY(assigning_organization_1); 72 | SSC_GET_MAM_INFO_VAL(formatted_density_code, 8); 73 | SSC_GET_MAM_INFO_ARRAY(initialization_count); 74 | SSC_GET_MAM_INFO_ARRAY(dev_make_serial_last_load); 75 | 76 | SSC_GET_MAM_INFO_VAL(written_in_medium_life, 64); 77 | SSC_GET_MAM_INFO_VAL(read_in_medium_life, 64); 78 | SSC_GET_MAM_INFO_VAL(written_in_last_load, 64); 79 | SSC_GET_MAM_INFO_VAL(read_in_last_load, 64); 80 | 81 | SSC_GET_MAM_INFO_ARRAY(medium_manufacturer); 82 | SSC_GET_MAM_INFO_ARRAY(medium_serial_number); 83 | SSC_GET_MAM_INFO_VAL(medium_length, 32); 84 | SSC_GET_MAM_INFO_VAL(medium_width, 32); 85 | SSC_GET_MAM_INFO_ARRAY(assigning_organization_2); 86 | SSC_GET_MAM_INFO_VAL(medium_density_code, 8); 87 | SSC_GET_MAM_INFO_ARRAY(medium_manufacture_date); 88 | SSC_GET_MAM_INFO_VAL(MAM_capacity, 64); 89 | SSC_GET_MAM_INFO_VAL(medium_type, 8); 90 | SSC_GET_MAM_INFO_VAL(medium_type_information, 16); 91 | 92 | SSC_GET_MAM_INFO_ARRAY(application_vendor); 93 | SSC_GET_MAM_INFO_ARRAY(application_name); 94 | SSC_GET_MAM_INFO_ARRAY(application_version); 95 | SSC_GET_MAM_INFO_ARRAY(user_medium_text_label); 96 | SSC_GET_MAM_INFO_ARRAY(date_time_last_written); 97 | SSC_GET_MAM_INFO_VAL(localization_identifier, 8); 98 | SSC_GET_MAM_INFO_ARRAY(barcode); 99 | SSC_GET_MAM_INFO_ARRAY(owning_host_textual_name); 100 | SSC_GET_MAM_INFO_ARRAY(media_pool); 101 | 102 | SSC_GET_MAM_INFO_ARRAY(vendor_unique); 103 | 104 | SSC_GET_MAM_INFO_VAL(dirty, 8); 105 | 106 | return 0; 107 | } 108 | 109 | #define SSC_PUT_MAM_INFO_VAL(member, bits)\ 110 | {\ 111 | put_unaligned_be##bits((i)->member, &((m)->member));\ 112 | } 113 | 114 | #define SSC_PUT_MAM_INFO_ARRAY(member)\ 115 | {\ 116 | memcpy((m)->member, (i)->member, sizeof((m)->member));\ 117 | } 118 | 119 | static inline void put_unaligned_be8(uint8_t val, uint8_t *p) 120 | { 121 | *p = val; 122 | } 123 | 124 | int ssc_write_mam_info(int fd, struct MAM_info *i) 125 | { 126 | struct MAM mam, *m; 127 | int ret; 128 | 129 | m = &mam; 130 | memset(m, 0, sizeof(struct MAM)); 131 | 132 | SSC_PUT_MAM_INFO_VAL(tape_fmt_version, 32); 133 | 134 | SSC_PUT_MAM_INFO_VAL(remaining_capacity, 64); 135 | SSC_PUT_MAM_INFO_VAL(max_capacity, 64); 136 | SSC_PUT_MAM_INFO_VAL(TapeAlert, 64); 137 | SSC_PUT_MAM_INFO_VAL(load_count, 64); 138 | SSC_PUT_MAM_INFO_VAL(MAM_space_remaining, 64); 139 | 140 | SSC_PUT_MAM_INFO_ARRAY(assigning_organization_1); 141 | SSC_PUT_MAM_INFO_VAL(formatted_density_code, 8); 142 | SSC_PUT_MAM_INFO_ARRAY(initialization_count); 143 | SSC_PUT_MAM_INFO_ARRAY(dev_make_serial_last_load); 144 | 145 | SSC_PUT_MAM_INFO_VAL(written_in_medium_life, 64); 146 | SSC_PUT_MAM_INFO_VAL(read_in_medium_life, 64); 147 | SSC_PUT_MAM_INFO_VAL(written_in_last_load, 64); 148 | SSC_PUT_MAM_INFO_VAL(read_in_last_load, 64); 149 | 150 | SSC_PUT_MAM_INFO_ARRAY(medium_manufacturer); 151 | SSC_PUT_MAM_INFO_ARRAY(medium_serial_number); 152 | SSC_PUT_MAM_INFO_VAL(medium_length, 32); 153 | SSC_PUT_MAM_INFO_VAL(medium_width, 32); 154 | SSC_PUT_MAM_INFO_ARRAY(assigning_organization_2); 155 | SSC_PUT_MAM_INFO_VAL(medium_density_code, 8); 156 | SSC_PUT_MAM_INFO_ARRAY(medium_manufacture_date); 157 | SSC_PUT_MAM_INFO_VAL(MAM_capacity, 64); 158 | SSC_PUT_MAM_INFO_VAL(medium_type, 8); 159 | SSC_PUT_MAM_INFO_VAL(medium_type_information, 16); 160 | 161 | SSC_PUT_MAM_INFO_ARRAY(application_vendor); 162 | SSC_PUT_MAM_INFO_ARRAY(application_name); 163 | SSC_PUT_MAM_INFO_ARRAY(application_version); 164 | SSC_PUT_MAM_INFO_ARRAY(user_medium_text_label); 165 | SSC_PUT_MAM_INFO_ARRAY(date_time_last_written); 166 | SSC_PUT_MAM_INFO_VAL(localization_identifier, 8); 167 | SSC_PUT_MAM_INFO_ARRAY(barcode); 168 | SSC_PUT_MAM_INFO_ARRAY(owning_host_textual_name); 169 | SSC_PUT_MAM_INFO_ARRAY(media_pool); 170 | 171 | SSC_PUT_MAM_INFO_ARRAY(vendor_unique); 172 | 173 | SSC_PUT_MAM_INFO_VAL(dirty, 8); 174 | 175 | ret = pwrite(fd, m, sizeof(struct MAM), SSC_BLK_HDR_SIZE); 176 | if (ret != sizeof(struct MAM)) 177 | return 1; 178 | 179 | if (lseek(fd, SSC_1ST_HDR_OFFSET, SEEK_SET) != SSC_1ST_HDR_OFFSET) 180 | return 1; 181 | 182 | return 0; 183 | } 184 | 185 | int ssc_read_blkhdr(int fd, struct blk_header_info *i, loff_t offset) 186 | { 187 | size_t count; 188 | struct blk_header h, *m = &h; 189 | uint32_t crc = ~0; 190 | 191 | count = pread(fd, m, SSC_BLK_HDR_SIZE, offset); 192 | if (count != SSC_BLK_HDR_SIZE) 193 | return 1; 194 | 195 | crc = crc32c(crc, &m->ondisk_sz, SSC_BLK_HDR_SIZE - sizeof(m->h_csum)); 196 | 197 | if (*(uint32_t *)m->h_csum != ~crc) 198 | fprintf(stderr, "crc error\n"); 199 | 200 | SSC_GET_MAM_INFO_VAL(ondisk_sz, 32); 201 | SSC_GET_MAM_INFO_VAL(blk_sz, 32); 202 | SSC_GET_MAM_INFO_VAL(blk_type, 32); 203 | SSC_GET_MAM_INFO_VAL(blk_num, 64); 204 | SSC_GET_MAM_INFO_VAL(prev, 64); 205 | SSC_GET_MAM_INFO_VAL(curr, 64); 206 | SSC_GET_MAM_INFO_VAL(next, 64); 207 | 208 | return 0; 209 | } 210 | 211 | int ssc_write_blkhdr(int fd, struct blk_header_info *i, loff_t offset) 212 | { 213 | size_t count; 214 | struct blk_header h, *m = &h; 215 | uint32_t crc = ~0; 216 | 217 | SSC_PUT_MAM_INFO_VAL(ondisk_sz, 32); 218 | SSC_PUT_MAM_INFO_VAL(blk_sz, 32); 219 | SSC_PUT_MAM_INFO_VAL(blk_type, 32); 220 | SSC_PUT_MAM_INFO_VAL(blk_num, 64); 221 | SSC_PUT_MAM_INFO_VAL(prev, 64); 222 | SSC_PUT_MAM_INFO_VAL(curr, 64); 223 | SSC_PUT_MAM_INFO_VAL(next, 64); 224 | 225 | crc = crc32c(crc, &m->ondisk_sz, SSC_BLK_HDR_SIZE - sizeof(m->h_csum)); 226 | *(uint32_t *)m->h_csum = ~crc; 227 | 228 | count = pwrite(fd, m, SSC_BLK_HDR_SIZE, offset); 229 | if (count != SSC_BLK_HDR_SIZE) 230 | return 1; 231 | 232 | return 0; 233 | } 234 | -------------------------------------------------------------------------------- /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 | static inline void __list_add(struct list_head *new, 61 | struct list_head *prev, 62 | struct list_head *next) 63 | { 64 | next->prev = new; 65 | new->next = next; 66 | new->prev = prev; 67 | prev->next = new; 68 | } 69 | 70 | static inline void list_add(struct list_head *new, struct list_head *head) 71 | { 72 | __list_add(new, head, head->next); 73 | } 74 | 75 | static inline void list_add_tail(struct list_head *new, struct list_head *head) 76 | { 77 | __list_add(new, head->prev, head); 78 | } 79 | 80 | static inline void __list_del(struct list_head * prev, struct list_head * next) 81 | { 82 | next->prev = prev; 83 | prev->next = next; 84 | } 85 | 86 | static inline void list_del(struct list_head *entry) 87 | { 88 | __list_del(entry->prev, entry->next); 89 | entry->next = entry->prev = NULL; 90 | } 91 | 92 | static inline void list_del_init(struct list_head *entry) 93 | { 94 | __list_del(entry->prev, entry->next); 95 | INIT_LIST_HEAD(entry); 96 | } 97 | 98 | static inline void __list_splice(const struct list_head *list, 99 | struct list_head *prev, 100 | struct list_head *next) 101 | { 102 | struct list_head *first = list->next; 103 | struct list_head *last = list->prev; 104 | 105 | first->prev = prev; 106 | prev->next = first; 107 | 108 | last->next = next; 109 | next->prev = last; 110 | } 111 | 112 | static inline void list_splice_init(struct list_head *list, 113 | struct list_head *head) 114 | { 115 | if (!list_empty(list)) { 116 | __list_splice(list, head, head->next); 117 | INIT_LIST_HEAD(list); 118 | } 119 | } 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /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/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 | 6 | struct acl_entry { 7 | char *address; 8 | struct list_head aclent_list; 9 | }; 10 | 11 | struct iqn_acl_entry { 12 | char *name; 13 | struct list_head iqn_aclent_list; 14 | }; 15 | 16 | struct tgt_account { 17 | int out_aid; 18 | int nr_inaccount; 19 | int max_inaccount; 20 | int *in_aids; 21 | }; 22 | 23 | struct target { 24 | char *name; 25 | 26 | int tid; 27 | int lid; 28 | 29 | enum scsi_target_state target_state; 30 | 31 | struct list_head target_siblings; 32 | 33 | struct list_head device_list; 34 | 35 | struct list_head it_nexus_list; 36 | 37 | struct backingstore_template *bst; 38 | 39 | struct list_head acl_list; 40 | 41 | struct list_head iqn_acl_list; 42 | 43 | struct tgt_account account; 44 | 45 | struct list_head lld_siblings; 46 | }; 47 | 48 | struct it_nexus { 49 | uint64_t itn_id; 50 | long ctime; 51 | 52 | struct list_head cmd_list; 53 | 54 | struct target *nexus_target; 55 | 56 | /* the list of i_t_nexus belonging to a target */ 57 | struct list_head nexus_siblings; 58 | 59 | /* dirty hack for IBMVIO */ 60 | int host_no; 61 | 62 | struct list_head itn_itl_info_list; 63 | 64 | /* only used for show operation */ 65 | char *info; 66 | }; 67 | 68 | enum { 69 | TGT_QUEUE_BLOCKED, 70 | TGT_QUEUE_DELETED, 71 | }; 72 | 73 | #define QUEUE_FNS(bit, name) \ 74 | static inline void set_queue_##name(struct tgt_cmd_queue *q) \ 75 | { \ 76 | (q)->state |= (1UL << TGT_QUEUE_##bit); \ 77 | } \ 78 | static inline void clear_queue_##name(struct tgt_cmd_queue *q) \ 79 | { \ 80 | (q)->state &= ~(1UL << TGT_QUEUE_##bit); \ 81 | } \ 82 | static inline int queue_##name(const struct tgt_cmd_queue *q) \ 83 | { \ 84 | return ((q)->state & (1UL << TGT_QUEUE_##bit)); \ 85 | } 86 | 87 | static inline int queue_active(const struct tgt_cmd_queue *q) \ 88 | { \ 89 | return ((q)->active_cmd); \ 90 | } 91 | 92 | QUEUE_FNS(BLOCKED, blocked) 93 | QUEUE_FNS(DELETED, deleted) 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /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 stat 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 = fstat(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 | -------------------------------------------------------------------------------- /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 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "be_byteshift.h" 25 | 26 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 27 | #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) 28 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 29 | #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) 30 | 31 | #if __BYTE_ORDER == __LITTLE_ENDIAN 32 | #define __cpu_to_be16(x) bswap_16(x) 33 | #define __cpu_to_be32(x) bswap_32(x) 34 | #define __cpu_to_be64(x) bswap_64(x) 35 | #define __be16_to_cpu(x) bswap_16(x) 36 | #define __be32_to_cpu(x) bswap_32(x) 37 | #define __be64_to_cpu(x) bswap_64(x) 38 | #define __cpu_to_le32(x) (x) 39 | #else 40 | #define __cpu_to_be16(x) (x) 41 | #define __cpu_to_be32(x) (x) 42 | #define __cpu_to_be64(x) (x) 43 | #define __be16_to_cpu(x) (x) 44 | #define __be32_to_cpu(x) (x) 45 | #define __be64_to_cpu(x) (x) 46 | #define __cpu_to_le32(x) bswap_32(x) 47 | #endif 48 | 49 | #define DEFDMODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 50 | #define DEFFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 51 | 52 | #define min(x,y) ({ \ 53 | typeof(x) _x = (x); \ 54 | typeof(y) _y = (y); \ 55 | (void) (&_x == &_y); \ 56 | _x < _y ? _x : _y; }) 57 | 58 | #define max(x,y) ({ \ 59 | typeof(x) _x = (x); \ 60 | typeof(y) _y = (y); \ 61 | (void) (&_x == &_y); \ 62 | _x > _y ? _x : _y; }) 63 | 64 | #define min_t(type,x,y) \ 65 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) 66 | #define max_t(type,x,y) \ 67 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) 68 | 69 | extern int get_blk_shift(unsigned int size); 70 | extern int chrdev_open(char *modname, char *devpath, uint8_t minor, int *fd); 71 | extern int backed_file_open(char *path, int oflag, uint64_t *size, 72 | uint32_t *blksize); 73 | extern int set_non_blocking(int fd); 74 | extern int str_to_open_flags(char *buf); 75 | extern char *open_flags_to_str(char *dest, int flags); 76 | extern int spc_memcpy(uint8_t *dst, uint32_t *dst_remain_len, 77 | uint8_t *src, uint32_t src_len); 78 | 79 | #define zalloc(size) \ 80 | ({ \ 81 | void *ptr = malloc(size); \ 82 | if (ptr) \ 83 | memset(ptr, 0, size); \ 84 | else \ 85 | eprintf("%m\n"); \ 86 | ptr; \ 87 | }) 88 | 89 | static inline int before(uint32_t seq1, uint32_t seq2) 90 | { 91 | return (int32_t)(seq1 - seq2) < 0; 92 | } 93 | 94 | static inline int after(uint32_t seq1, uint32_t seq2) 95 | { 96 | return (int32_t)(seq2 - seq1) < 0; 97 | } 98 | 99 | /* is s2<=s1<=s3 ? */ 100 | static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3) 101 | { 102 | return seq3 - seq2 >= seq1 - seq2; 103 | } 104 | 105 | extern unsigned long pagesize, pageshift; 106 | 107 | /* convert string to integer, check for validity of the string numeric format 108 | * and the natural boundaries of the integer value type (first get a 64-bit 109 | * value and check that it fits the range of the destination integer). 110 | */ 111 | #define str_to_int(str, val) \ 112 | ({ \ 113 | int ret = 0; \ 114 | char *ptr; \ 115 | unsigned long long ull_val; \ 116 | ull_val = strtoull(str, &ptr, 0); \ 117 | val = (typeof(val)) ull_val; \ 118 | if (ull_val == ULLONG_MAX || ptr == str) \ 119 | ret = EINVAL; \ 120 | else if (val != ull_val) \ 121 | ret = ERANGE; \ 122 | ret; \ 123 | }) 124 | 125 | /* convert to int and check: strictly greater than */ 126 | #define str_to_int_gt(str, val, minv) \ 127 | ({ \ 128 | int ret = str_to_int(str, val); \ 129 | if (!ret && (val <= minv)) \ 130 | ret = ERANGE; \ 131 | ret; \ 132 | }) 133 | 134 | /* convert and check: greater than or equal */ 135 | #define str_to_int_ge(str, val, minv) \ 136 | ({ \ 137 | int ret = str_to_int(str, val); \ 138 | if (!ret && (val < minv)) \ 139 | ret = ERANGE; \ 140 | ret; \ 141 | }) 142 | 143 | /* convert and check: strictly less than */ 144 | #define str_to_int_lt(str, val, maxv) \ 145 | ({ \ 146 | int ret = str_to_int(str, val); \ 147 | if (!ret && (val >= maxv)) \ 148 | ret = ERANGE; \ 149 | ret; \ 150 | }) 151 | 152 | /* convert and check: range, ends inclusive */ 153 | #define str_to_int_range(str, val, minv, maxv) \ 154 | ({ \ 155 | int ret = str_to_int(str, val); \ 156 | if (!ret && (val < minv || val > maxv)) \ 157 | ret = ERANGE; \ 158 | ret; \ 159 | }) 160 | 161 | struct concat_buf { 162 | FILE *streamf; 163 | int err; 164 | int used; 165 | char *buf; 166 | size_t size; 167 | }; 168 | 169 | void concat_buf_init(struct concat_buf *b); 170 | int concat_printf(struct concat_buf *b, const char *format, ...); 171 | const char *concat_delim(struct concat_buf *b, const char *delim); 172 | int concat_buf_finish(struct concat_buf *b); 173 | int concat_write(struct concat_buf *b, int fd, int offset); 174 | void concat_buf_release(struct concat_buf *b); 175 | 176 | 177 | /* If we have recent enough glibc to support PUNCH HOLE we try to unmap 178 | * the region of file. 179 | * If supported BLKDISCARD, try to unmap the region of block device. 180 | */ 181 | static inline int unmap_file_region(int fd, off_t offset, off_t length) 182 | { 183 | struct stat st; 184 | if (fstat(fd, &st) < 0) 185 | return -1; 186 | if (S_ISREG(st.st_mode)) { 187 | #ifdef FALLOC_FL_PUNCH_HOLE 188 | if (fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, 189 | offset, length) == 0) 190 | return 0; 191 | #endif 192 | } else if (S_ISBLK(st.st_mode)) { 193 | #ifdef BLKDISCARD 194 | uint64_t range[] = { offset, length }; 195 | if (ioctl(fd, BLKDISCARD, &range) == 0) 196 | return 0; 197 | #endif 198 | } 199 | return -1; 200 | } 201 | 202 | #define BITS_PER_LONG LONG_BIT 203 | #define BITS_PER_BYTE 8 204 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 205 | 206 | static inline void set_bit(int nr, unsigned long *addr) 207 | { 208 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 209 | } 210 | 211 | static inline void clear_bit(int nr, unsigned long *addr) 212 | { 213 | addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG)); 214 | } 215 | 216 | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) 217 | { 218 | return ((1UL << (nr % BITS_PER_LONG)) & 219 | (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; 220 | } 221 | 222 | #define scsi_sprintf(str, size, format, ...) \ 223 | do { \ 224 | char buf[size + 1]; \ 225 | memset(buf, 0, sizeof(buf)); \ 226 | snprintf(buf, sizeof(buf), format, ## __VA_ARGS__); \ 227 | memcpy(str, buf, size); \ 228 | } while (0) 229 | 230 | #endif 231 | -------------------------------------------------------------------------------- /usr/work.c: -------------------------------------------------------------------------------- 1 | /* 2 | * work scheduler, loosely timer-based 3 | * 4 | * Copyright (C) 2006-2007 FUJITA Tomonori 5 | * Copyright (C) 2006-2007 Mike Christie 6 | * Copyright (C) 2011 Alexander Nezhinsky 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 | #include 26 | #include 27 | #include 28 | 29 | #include "list.h" 30 | #include "util.h" 31 | #include "log.h" 32 | #include "work.h" 33 | #include "tgtd.h" 34 | 35 | #define WORK_TIMER_INT_MSEC 500 36 | #define WORK_TIMER_INT_USEC (WORK_TIMER_INT_MSEC * 1000) 37 | 38 | static struct itimerval work_timer = { 39 | {0, WORK_TIMER_INT_USEC}, 40 | {0, WORK_TIMER_INT_USEC} 41 | }; 42 | 43 | static unsigned int elapsed_msecs; 44 | static int timer_pending; 45 | static int timer_fd[2] = {-1, -1}; 46 | 47 | static LIST_HEAD(active_work_list); 48 | static LIST_HEAD(inactive_work_list); 49 | 50 | static void execute_work(void); 51 | 52 | static inline unsigned int timeval_to_msecs(struct timeval t) 53 | { 54 | return t.tv_sec * 1000 + t.tv_usec / 1000; 55 | } 56 | 57 | static void work_timer_schedule_evt(void) 58 | { 59 | unsigned int n = 0; 60 | int err; 61 | 62 | if (timer_pending || timer_fd[1] < 0) 63 | return; 64 | 65 | timer_pending = 1; 66 | 67 | err = write(timer_fd[1], &n, sizeof(n)); 68 | if (err < 0) 69 | eprintf("Failed to write to pipe, %m\n"); 70 | } 71 | 72 | static void work_timer_sig_handler(int data) 73 | { 74 | work_timer_schedule_evt(); 75 | } 76 | 77 | static void work_timer_evt_handler(int fd, int events, void *data) 78 | { 79 | int err; 80 | static int first = 1; 81 | 82 | if (timer_fd[1] == -1) { 83 | unsigned long long s; 84 | struct timeval cur_time; 85 | 86 | err = read(timer_fd[0], &s, sizeof(s)); 87 | if (err < 0) { 88 | if (err != -EAGAIN) 89 | eprintf("failed to read from timerfd, %m\n"); 90 | return; 91 | } 92 | 93 | if (first) { 94 | first = 0; 95 | err = gettimeofday(&cur_time, NULL); 96 | if (err) { 97 | eprintf("gettimeofday failed, %m\n"); 98 | exit(1); 99 | } 100 | elapsed_msecs = timeval_to_msecs(cur_time); 101 | return; 102 | } 103 | 104 | elapsed_msecs += (unsigned int)s * WORK_TIMER_INT_MSEC; 105 | } else { 106 | unsigned int n; 107 | struct timeval cur_time; 108 | 109 | err = read(timer_fd[0], &n, sizeof(n)); 110 | if (err < 0) { 111 | eprintf("Failed to read from pipe, %m\n"); 112 | return; 113 | } 114 | 115 | timer_pending = 0; 116 | 117 | err = gettimeofday(&cur_time, NULL); 118 | if (err) { 119 | eprintf("gettimeofday failed, %m\n"); 120 | exit(1); 121 | } 122 | 123 | elapsed_msecs = timeval_to_msecs(cur_time); 124 | } 125 | 126 | execute_work(); 127 | } 128 | 129 | int work_timer_start(void) 130 | { 131 | struct timeval t; 132 | int err; 133 | 134 | if (elapsed_msecs) 135 | return 0; 136 | 137 | err = gettimeofday(&t, NULL); 138 | if (err) { 139 | eprintf("gettimeofday failed, %m\n"); 140 | exit(1); 141 | } 142 | elapsed_msecs = timeval_to_msecs(t); 143 | 144 | timer_fd[0] = __timerfd_create(WORK_TIMER_INT_USEC); 145 | if (timer_fd[0] >= 0) 146 | eprintf("use timer_fd based scheduler\n"); 147 | else { 148 | struct sigaction s; 149 | 150 | eprintf("use signal based scheduler\n"); 151 | 152 | sigemptyset(&s.sa_mask); 153 | sigaddset(&s.sa_mask, SIGALRM); 154 | s.sa_flags = 0; 155 | s.sa_handler = work_timer_sig_handler; 156 | err = sigaction(SIGALRM, &s, NULL); 157 | if (err) { 158 | eprintf("Failed to setup timer handler\n"); 159 | goto timer_err; 160 | } 161 | 162 | err = setitimer(ITIMER_REAL, &work_timer, 0); 163 | if (err) { 164 | eprintf("Failed to set timer\n"); 165 | goto timer_err; 166 | } 167 | 168 | err = pipe(timer_fd); 169 | if (err) { 170 | eprintf("Failed to open timer pipe\n"); 171 | goto timer_err; 172 | } 173 | } 174 | 175 | err = tgt_event_add(timer_fd[0], EPOLLIN, work_timer_evt_handler, NULL); 176 | if (err) { 177 | eprintf("failed to add timer event, fd:%d\n", timer_fd[0]); 178 | goto timer_err; 179 | } 180 | 181 | dprintf("started, timeout: %d msec\n", WORK_TIMER_INT_MSEC); 182 | return 0; 183 | 184 | timer_err: 185 | work_timer_stop(); 186 | return err; 187 | } 188 | 189 | void work_timer_stop(void) 190 | { 191 | if (!elapsed_msecs) 192 | return; 193 | 194 | elapsed_msecs = 0; 195 | 196 | tgt_event_del(timer_fd[0]); 197 | 198 | if (timer_fd[0] > 0) 199 | close(timer_fd[0]); 200 | 201 | if (timer_fd[1] > 0) { 202 | int ret; 203 | close(timer_fd[1]); 204 | 205 | ret = setitimer(ITIMER_REAL, 0, 0); 206 | if (ret) 207 | eprintf("Failed to stop timer\n"); 208 | else 209 | dprintf("Timer stopped\n"); 210 | } 211 | } 212 | 213 | void add_work(struct tgt_work *work, unsigned int second) 214 | { 215 | struct tgt_work *ent; 216 | struct timeval t; 217 | int err; 218 | 219 | if (second) { 220 | err = gettimeofday(&t, NULL); 221 | if (err) { 222 | eprintf("gettimeofday failed, %m\n"); 223 | exit(1); 224 | } 225 | work->when = timeval_to_msecs(t) + second * 1000; 226 | 227 | list_for_each_entry(ent, &inactive_work_list, entry) { 228 | if (before(work->when, ent->when)) 229 | break; 230 | } 231 | 232 | list_add_tail(&work->entry, &ent->entry); 233 | } else { 234 | list_add_tail(&work->entry, &active_work_list); 235 | work_timer_schedule_evt(); 236 | } 237 | } 238 | 239 | void del_work(struct tgt_work *work) 240 | { 241 | list_del_init(&work->entry); 242 | } 243 | 244 | static void execute_work() 245 | { 246 | struct tgt_work *work, *n; 247 | 248 | list_for_each_entry_safe(work, n, &inactive_work_list, entry) { 249 | if (before(elapsed_msecs, work->when)) 250 | break; 251 | 252 | list_del(&work->entry); 253 | list_add_tail(&work->entry, &active_work_list); 254 | } 255 | 256 | while (!list_empty(&active_work_list)) { 257 | work = list_first_entry(&active_work_list, 258 | struct tgt_work, entry); 259 | list_del_init(&work->entry); 260 | work->func(work->data); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /usr/work.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCHED_H 2 | #define __SCHED_H 3 | 4 | #if defined(__NR_timerfd_create) && defined(USE_TIMERFD) 5 | 6 | #include 7 | 8 | static inline int __timerfd_create(unsigned int usec) 9 | { 10 | struct itimerspec new_t, old_t; 11 | int fd, err; 12 | 13 | fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); 14 | if (fd < 0) 15 | return -1; 16 | 17 | new_t.it_value.tv_sec = 0; 18 | new_t.it_value.tv_nsec = 1; 19 | 20 | new_t.it_interval.tv_sec = 0; 21 | new_t.it_interval.tv_nsec = usec * 1000; 22 | 23 | err = timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_t, &old_t); 24 | if (err < 0) { 25 | close(fd); 26 | return -1; 27 | } 28 | return fd; 29 | } 30 | 31 | #else 32 | #define __timerfd_create(usec) (-1) 33 | #endif 34 | 35 | struct tgt_work { 36 | struct list_head entry; 37 | void (*func)(void *); 38 | void *data; 39 | unsigned int when; 40 | }; 41 | 42 | extern int work_timer_start(void); 43 | extern void work_timer_stop(void); 44 | 45 | extern void add_work(struct tgt_work *work, unsigned int second); 46 | extern void del_work(struct tgt_work *work); 47 | 48 | #endif 49 | --------------------------------------------------------------------------------