Skip to content

Commit cfe9cde

Browse files
committed
This is iSCSI sharing for ZoL (shareiscsi).
* Supports the following iSCSI implementations (in this order of discovery): + IET http://iscsitarget.sourceforge.net + STGT http://stgt.berlios.de + SCST http://scst.sourceforge.net + Requires that SCST was compiled with /sys support (the default). + LIO http://linux-iscsi.org * Will refuse to unshares an active target (one with sessions). * Supports the following options to the 'shareiscsi' property: + name/iqn Full iSCSI Qualified Name (IQN), including identifier. This is generated by iscsi_generate_target(): + Uses the content of an optional /etc/iscsi_target_id file: Example: iqn.YYYY-MM.tld.domain + If this file doesn't exist, it uses the current year, month and domain name to generate the iqn. + The dataset name is appended at the end of the iqn, with slashes replaced with dots. => <iqn>:<dataset> + lun LUN (0-16384) Default: 0 (1 for STGT) + type Share mode (fileio, blockio, nullio, disk, tape) STGT: ssc, pt Default: blockio (disk for STGT) + iomode IO mode (wb, wt, ro) STGT: rdwr, aio, mmap, sg, ssc Default: wt (rdwr for STGT) + blocksize Logical block size (512, 1024, 2048, 4096) Default: Volume blocksize, 4096 if not usable. NOTE: Currently not supported for STGT (doesn't seem to be an option for it in tgtadm). + initiator Allow only this initiator to bind to target. Currently only availible for LIO, STGT and SCST. + authname Global user to use in binds on targets. + authpass Password for global user. * If not called with a 'name/iqn' value, then force setting it. This so that the IQN doesn't change every month (when it is regenerated again). It will be generated by iscsi_generate_target() (see above). NOTE: + Moved nfs.c:foreach_nfs_shareopt() to libshare.c:foreach_shareopt() so that it can be (re)used in smb.c and iscsi.c. + Split iSCSI implementation into their own separate source files + Use the list_{create,insert}() etc for keeping tabs of the linked lists instead of using a home-made version. + A half second delay had to be added in lib/libzfs/libzfs_mount.c:zfs_unmount() after the successful unshare. This to avoid 'dataset busy' when destroying recursivly. = The 'initiator', 'authname' and 'authpass' option might have some issues: It will make the compatibility between the different iSCSI implementations questionable - can't switch between them easily (it will ONLY be availible in ZoL). I COULD make the option be silently ignored (instead of forcibly rejected if not availible). But that still doesn't solve the (possible) problem between ZoL and OpenZFS/Illumos (setting the option, will possibly introduce problems when importing the pool on something else than ZoL). So some more discussion might be needed..
1 parent b23d543 commit cfe9cde

33 files changed

+6150
-332
lines changed

cmd/zfs/zfs_main.c

Lines changed: 337 additions & 208 deletions
Large diffs are not rendered by default.

include/libzfs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ typedef enum zfs_error {
142142
EZFS_DIFF, /* general failure of zfs diff */
143143
EZFS_DIFFDATA, /* bad zfs diff data */
144144
EZFS_POOLREADONLY, /* pool is in read-only mode */
145+
EZFS_UNSHAREISCSIFAILED, /* failed to unshare over iSCSI */
146+
EZFS_SHAREISCSIFAILED, /* failed to share over iSCSI */
145147
EZFS_UNKNOWN
146148
} zfs_error_t;
147149

@@ -567,6 +569,7 @@ typedef struct get_all_cb {
567569
zfs_handle_t **cb_handles;
568570
size_t cb_alloc;
569571
size_t cb_used;
572+
uint_t cb_types;
570573
boolean_t cb_verbose;
571574
int (*cb_getone)(zfs_handle_t *, void *);
572575
} get_all_cb_t;
@@ -725,13 +728,17 @@ extern int zfs_unshare(zfs_handle_t *);
725728
*/
726729
extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **);
727730
extern boolean_t zfs_is_shared_smb(zfs_handle_t *, char **);
731+
extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *, char **);
728732
extern int zfs_share_nfs(zfs_handle_t *);
729733
extern int zfs_share_smb(zfs_handle_t *);
734+
extern int zfs_share_iscsi(zfs_handle_t *);
730735
extern int zfs_shareall(zfs_handle_t *);
731736
extern int zfs_unshare_nfs(zfs_handle_t *, const char *);
732737
extern int zfs_unshare_smb(zfs_handle_t *, const char *);
738+
extern int zfs_unshare_iscsi(zfs_handle_t *, const char *);
733739
extern int zfs_unshareall_nfs(zfs_handle_t *);
734740
extern int zfs_unshareall_smb(zfs_handle_t *);
741+
extern int zfs_unshareall_iscsi(zfs_handle_t *);
735742
extern int zfs_unshareall_bypath(zfs_handle_t *, const char *);
736743
extern int zfs_unshareall(zfs_handle_t *);
737744
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *, char *,

include/libzfs_impl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ struct zpool_handle {
123123
typedef enum {
124124
PROTO_NFS = 0,
125125
PROTO_SMB = 1,
126-
PROTO_END = 2
126+
PROTO_ISCSI = 2,
127+
PROTO_END = 3
127128
} zfs_share_proto_t;
128129

129130
/*
@@ -133,7 +134,8 @@ typedef enum {
133134
typedef enum {
134135
SHARED_NOT_SHARED = 0x0,
135136
SHARED_NFS = 0x2,
136-
SHARED_SMB = 0x4
137+
SHARED_SMB = 0x4,
138+
SHARED_ISCSI = 0x8
137139
} zfs_share_type_t;
138140

139141
int zfs_error(libzfs_handle_t *, int, const char *);

include/sys/fs/zfs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ typedef enum {
155155
ZFS_PROP_RELATIME,
156156
ZFS_PROP_REDUNDANT_METADATA,
157157
ZFS_PROP_OVERLAY,
158+
ZFS_PROP_SHAREISCSI,
158159
ZFS_NUM_PROPS
159160
} zfs_prop_t;
160161

@@ -331,7 +332,9 @@ typedef enum zfs_share_op {
331332
ZFS_SHARE_NFS = 0,
332333
ZFS_UNSHARE_NFS = 1,
333334
ZFS_SHARE_SMB = 2,
334-
ZFS_UNSHARE_SMB = 3
335+
ZFS_UNSHARE_SMB = 3,
336+
ZFS_SHARE_ISCSI = 4,
337+
ZFS_UNSHARE_ISCSI = 5
335338
} zfs_share_op_t;
336339

337340
typedef enum zfs_smb_acl_op {

lib/libshare/Makefile.am

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ USER_C = \
1212
nfs.c \
1313
nfs.h \
1414
smb.c \
15-
smb.h
15+
smb.h \
16+
iscsi.c \
17+
iscsi_iet.c \
18+
iscsi_lio.c \
19+
iscsi_scst.c \
20+
iscsi_stgt.c \
21+
iscsi.h
1622

1723
KERNEL_C =
1824

lib/libshare/README_iscsi.txt

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
This is iSCSI support for the IET, SCST and STGT iSCSI target implementations.
2+
3+
Implementation URL Package name(s)
4+
IET http://iscsitarget.sourceforge.net iscsitarget + iscsitarget-dkms
5+
SCST http://scst.sourceforge.net iscsi-scst + scst-dkms + scst-fileio-tgt + scstadmin
6+
STGT http://stgt.berlios.de tgt
7+
LIO http://linux-iscsi.org lio-utils + targetcli
8+
9+
It will call ietmadm (for IET), tgtadm (for STGT) or modify files in
10+
/sys/kernel/scst_tgt (for SCST) or /sys/kernel/config/target (for LIO) to both
11+
add or remove a iSCSI target from the call to 'zfs share':
12+
13+
zfs create -s -V10G mypool/test
14+
zfs set shareiscsi=on mypool/test
15+
16+
There is no need to issue 'zfs share tank/test', because ZFS will
17+
automatically issue the corresponding share command(s) when setting
18+
(or modifying) the shareiscsi property.
19+
20+
21+
The driver will execute the following commands to setup a target (example!):
22+
23+
* For IET:
24+
25+
/usr/sbin/ietadm --op new --tid TID --params Name=iqn.2010-09.org.zfsonlinux:mypool.test
26+
/usr/sbin/ietadm --op new --tid TID --lun LUN --params Path=/dev/zvol/mypool/test,Type=fileio
27+
28+
* For STGT:
29+
30+
tgtadm --lld iscsi --op new --mode target --tid TID -T iqn.2010-09.org.zfsonlinux:share.test
31+
tgtadm --lld iscsi --op new --mode logicalunit --tid TID --lun 1 -b /dev/zvol/mypool/test
32+
tgtadm --lld iscsi --op bind --mode target --tid TID --initiator-address ALL
33+
34+
* For SCST:
35+
36+
SYSFS_SCST="/sys/kernel/scst_tgt"
37+
38+
echo "add_target iqn.2010-09.org.zfsonlinux:mypool.test" > $SYSFS_SCST/targets/iscsi/mgmt
39+
echo "add_device DEVICE filename=/dev/zvol/mypool/test; blocksize=BLOCKSIZE" > $SYSFS_SCST/handlers/vdisk_blockio/mgmt
40+
echo "add DEVICE LUN" > $SYSFS_SCST/targets/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/luns/mgmt
41+
echo 1 > $SYSFS_SCST/targets/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/enabled
42+
43+
* For LIO
44+
45+
SYSFS_LIO="/sys/kernel/config/target"
46+
47+
# TEST DATA:
48+
ip=$(ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | head -n1 | sed "s@.*addr:\(.*\) Bcast.*@\1@")
49+
md5=$(date | md5sum | cut -f1 -d' ')
50+
51+
# SETUP Device
52+
mkdir -p $SYSFS_LIO/core/iblock_TID/mypool.test
53+
echo -n "/dev/zvol/mypool/test" > $SYSFS_LIO/core/iblock_TID/mypool.test/udev_path
54+
echo -n "udev_path=/dev/zvol/mypool/test" > $SYSFS_LIO/core/iblock_TID/mypool.test/control
55+
echo -n $md5 > $SYSFS_LIO/core/iblock_TID/mypool.test/wwn/vpd_unit_serial
56+
echo 1 > $SYSFS_LIO/core/iblock_TID/mypool.test/enable
57+
echo 4096 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/block_size
58+
echo 0 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/emulate_tas
59+
echo 0 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/emulate_ua_intlck_ctrl
60+
61+
# SETUP IQN/Target
62+
mkdir -p $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/np/$ip:3260
63+
mkdir -p $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/lun/lun_LUN
64+
ln -s $SYSFS_LIO/core/iblock_TID/mypool.test \
65+
$SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/lun/lun_LUN/$md5
66+
echo -n 0 > $SYSFS_LIO/iscsi/discovery_auth/enforce_discovery_auth
67+
echo 0 > $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/attrib/authentication
68+
echo 1 > $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/enable
69+
70+
Here the value DEVICE is generated by iscsi.c:iscsi_generate_scst_device_name()
71+
and is a randomized value, based on the exact time of day when
72+
called. This because SCST have a limit of 16 characters for the device
73+
name, and the chances of have duplicates is large. The BLOCKSIZE that
74+
is used depends on what blocksize the ZVOL was created with.
75+
76+
The LUN value is by default 0 (1 for STGT becase LUN0 is the controller),
77+
but can be overridden using the 'lun' option to the 'shareiscsi' property.
78+
79+
It (the driver) will automatically calculate the TID and IQN and use
80+
only the ZVOL (in this case 'share/test') in the command lines.
81+
82+
If autogenerating the IQN is not wanted (because each reboot or unshare/share,
83+
if it's done in another month, will generate a new IQN), a hardcoded default
84+
can be set in /etc/iscsi_target_id like so:
85+
86+
echo iqn.2010-09.org.zfsonlinux > /etc/iscsi_target_id
87+
88+
Then all targets will start with this value, only adding a colon
89+
and the ZVOL/dataset name (slashes replaced with dots):
90+
91+
iqn.2010-09.org.zfsonlinux:mypool.test
92+
93+
94+
In addition to executing ietadm, tgtadm or modifying files below
95+
/sys/kernel/scst_tgt or /sys/kernel/config/target, zfs will execute
96+
the following script (if it exist and is executable)
97+
'/sbin/zfs_share_iscsi.sh', like so:
98+
99+
/sbin/zfs_share_iscsi TID
100+
101+
This is so that one can create custom commands to be done on the
102+
share.
103+
104+
The only parameter to this script/executable is the TID and the
105+
driver will 'execute and forget'. Meaning, it will not care about
106+
exit code nor any output it gives.
107+
108+
Example scripts have been provided, on for each of the iSCSI
109+
implementation supported:
110+
111+
zfs_share_iscsi.iet
112+
zfs_share_iscsi.lio
113+
zfs_share_iscsi.scst
114+
zfs_share_iscsi.stgt
115+
116+
Simply copy the one for your iSCSI implementation to /sbin/zfs_share/iscsi
117+
and then modify it to your requirenments.
118+
119+
PS. The domainname needs to be set (in /proc/sys/kernel/domainname
120+
using either 'sysctl', 'echo' or the command 'domainname') for
121+
the driver to be able to work out the iqn correctly.
122+
123+
NOTE: This is only required if the IQN haven't been set in the
124+
/etc/iscsi_target_id file!

lib/libshare/destroy_lio.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/sh
2+
3+
# This is a script to simply unshare all LIO targets, without going through
4+
# ZFS. Mostly used for testing...
5+
6+
SYSFS=/sys/kernel/config/target
7+
8+
cd $SYSFS/iscsi/
9+
if [ -z "$*" ]; then
10+
targets=`echo iqn.*`
11+
else
12+
targets=`echo $*`
13+
fi
14+
15+
for name in $targets; do
16+
tid=`echo $SYSFS/core/iblock_*/$name | sed "s@.*iblock_\(.*\)/.*@\1@"`
17+
lnk=`find $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*/* | egrep -v 'alua|statistics' | sed 's@.*/@@'`
18+
19+
echo 0 > $SYSFS/iscsi/$name/tpgt_$tid/enable
20+
21+
rmdir $SYSFS/iscsi/$name/tpgt_$tid/np/*
22+
rm $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*/$lnk
23+
rmdir $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*
24+
rmdir $SYSFS/iscsi/$name/tpgt_$tid
25+
rmdir $SYSFS/iscsi/$name
26+
27+
rmdir $SYSFS/core/iblock_$tid/$name
28+
rmdir $SYSFS/core/iblock_$tid
29+
done

lib/libshare/destroy_scst.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
3+
# This is a script to somply unshare all SCST targets, without going through
4+
# ZFS. Mostly used for testing...
5+
6+
SYSFS=/sys/kernel/scst_tgt
7+
8+
cd $SYSFS/targets/iscsi/
9+
if [ -z "$*" ]; then
10+
targets=`echo iqn.*`
11+
else
12+
targets=`echo $*`
13+
fi
14+
15+
for name in $targets; do
16+
find $SYSFS/targets/iscsi/$name/sessions/* -type d > /dev/null 2>&1
17+
if [ "$?" -eq "1" ]; then
18+
[ ! -f "$SYSFS/targets/iscsi/$name/enabled" ] && continue
19+
20+
#scstadmin -noprompt -disable_target $name -driver iscsi
21+
echo 0 > $SYSFS/targets/iscsi/$name/enabled
22+
23+
#scstadmin -noprompt -close_dev $dev -handler vdisk_blockio
24+
dev=`/bin/ls -l $SYSFS/targets/iscsi/$name/luns/0/device | sed 's@.*/@@'`
25+
echo "del_device $dev" > $SYSFS/handlers/vdisk_blockio/mgmt
26+
27+
#scstadmin -noprompt -rem_target $name -driver iscsi
28+
echo "del_target $name" > $SYSFS/targets/iscsi/mgmt
29+
else
30+
echo "Can't destroy $name - have sessions"
31+
fi
32+
done

0 commit comments

Comments
 (0)