Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iSCSI support for ZoL #1099

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
563 changes: 346 additions & 217 deletions cmd/zfs/zfs_main.c

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ typedef enum zfs_error {
EZFS_DIFF, /* general failure of zfs diff */
EZFS_DIFFDATA, /* bad zfs diff data */
EZFS_POOLREADONLY, /* pool is in read-only mode */
EZFS_UNSHAREISCSIFAILED, /* failed to unshare over iSCSI */
EZFS_SHAREISCSIFAILED, /* failed to share over iSCSI */
EZFS_UNKNOWN
} zfs_error_t;

Expand Down Expand Up @@ -565,6 +567,7 @@ typedef struct get_all_cb {
zfs_handle_t **cb_handles;
size_t cb_alloc;
size_t cb_used;
uint_t cb_types;
boolean_t cb_verbose;
int (*cb_getone)(zfs_handle_t *, void *);
} get_all_cb_t;
Expand Down Expand Up @@ -720,13 +723,17 @@ extern int zfs_unshare(zfs_handle_t *);
*/
extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **);
extern boolean_t zfs_is_shared_smb(zfs_handle_t *, char **);
extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *, char **);
extern int zfs_share_nfs(zfs_handle_t *);
extern int zfs_share_smb(zfs_handle_t *);
extern int zfs_share_iscsi(zfs_handle_t *);
extern int zfs_shareall(zfs_handle_t *);
extern int zfs_unshare_nfs(zfs_handle_t *, const char *);
extern int zfs_unshare_smb(zfs_handle_t *, const char *);
extern int zfs_unshare_iscsi(zfs_handle_t *, const char *);
extern int zfs_unshareall_nfs(zfs_handle_t *);
extern int zfs_unshareall_smb(zfs_handle_t *);
extern int zfs_unshareall_iscsi(zfs_handle_t *);
extern int zfs_unshareall_bypath(zfs_handle_t *, const char *);
extern int zfs_unshareall(zfs_handle_t *);
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *, char *,
Expand Down
6 changes: 4 additions & 2 deletions include/libzfs_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ struct zpool_handle {
typedef enum {
PROTO_NFS = 0,
PROTO_SMB = 1,
PROTO_END = 2
PROTO_ISCSI = 2,
PROTO_END = 3
} zfs_share_proto_t;

/*
Expand All @@ -133,7 +134,8 @@ typedef enum {
typedef enum {
SHARED_NOT_SHARED = 0x0,
SHARED_NFS = 0x2,
SHARED_SMB = 0x4
SHARED_SMB = 0x4,
SHARED_ISCSI = 0x8
} zfs_share_type_t;

int zfs_error(libzfs_handle_t *, int, const char *);
Expand Down
5 changes: 4 additions & 1 deletion include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ typedef enum {
ZFS_PROP_RELATIME,
ZFS_PROP_REDUNDANT_METADATA,
ZFS_PROP_OVERLAY,
ZFS_PROP_SHAREISCSI,
ZFS_NUM_PROPS
} zfs_prop_t;

Expand Down Expand Up @@ -326,7 +327,9 @@ typedef enum zfs_share_op {
ZFS_SHARE_NFS = 0,
ZFS_UNSHARE_NFS = 1,
ZFS_SHARE_SMB = 2,
ZFS_UNSHARE_SMB = 3
ZFS_UNSHARE_SMB = 3,
ZFS_SHARE_ISCSI = 4,
ZFS_UNSHARE_ISCSI = 5
} zfs_share_op_t;

typedef enum zfs_smb_acl_op {
Expand Down
11 changes: 10 additions & 1 deletion lib/libshare/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@ libshare_la_SOURCES = \
$(top_srcdir)/lib/libshare/nfs.c \
$(top_srcdir)/lib/libshare/nfs.h \
$(top_srcdir)/lib/libshare/smb.c \
$(top_srcdir)/lib/libshare/smb.h
$(top_srcdir)/lib/libshare/smb.h \
$(top_srcdir)/lib/libshare/iscsi.c \
$(top_srcdir)/lib/libshare/iscsi_iet.c \
$(top_srcdir)/lib/libshare/iscsi_lio.c \
$(top_srcdir)/lib/libshare/iscsi_scst.c \
$(top_srcdir)/lib/libshare/iscsi_stgt.c \
$(top_srcdir)/lib/libshare/iscsi.h

libshare_la_LIBADD = \
$(top_builddir)/lib/libspl/libspl.la
124 changes: 124 additions & 0 deletions lib/libshare/README_iscsi.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
This is iSCSI support for the IET, SCST and STGT iSCSI target implementations.

Implementation URL Package name(s)
IET http://iscsitarget.sourceforge.net iscsitarget + iscsitarget-dkms
SCST http://scst.sourceforge.net iscsi-scst + scst-dkms + scst-fileio-tgt + scstadmin
STGT http://stgt.berlios.de tgt
LIO http://linux-iscsi.org lio-utils + targetcli

It will call ietmadm (for IET), tgtadm (for STGT) or modify files in
/sys/kernel/scst_tgt (for SCST) or /sys/kernel/config/target (for LIO) to both
add or remove a iSCSI target from the call to 'zfs share':

zfs create -s -V10G mypool/test
zfs set shareiscsi=on mypool/test

There is no need to issue 'zfs share tank/test', because ZFS will
automatically issue the corresponding share command(s) when setting
(or modifying) the shareiscsi property.


The driver will execute the following commands to setup a target (example!):

* For IET:

/usr/sbin/ietadm --op new --tid TID --params Name=iqn.2010-09.org.zfsonlinux:mypool.test
/usr/sbin/ietadm --op new --tid TID --lun LUN --params Path=/dev/zvol/mypool/test,Type=fileio

* For STGT:

tgtadm --lld iscsi --op new --mode target --tid TID -T iqn.2010-09.org.zfsonlinux:share.test
tgtadm --lld iscsi --op new --mode logicalunit --tid TID --lun 1 -b /dev/zvol/mypool/test
tgtadm --lld iscsi --op bind --mode target --tid TID --initiator-address ALL

* For SCST:

SYSFS_SCST="/sys/kernel/scst_tgt"

echo "add_target iqn.2010-09.org.zfsonlinux:mypool.test" > $SYSFS_SCST/targets/iscsi/mgmt
echo "add_device DEVICE filename=/dev/zvol/mypool/test; blocksize=BLOCKSIZE" > $SYSFS_SCST/handlers/vdisk_blockio/mgmt
echo "add DEVICE LUN" > $SYSFS_SCST/targets/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/luns/mgmt
echo 1 > $SYSFS_SCST/targets/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/enabled

* For LIO

SYSFS_LIO="/sys/kernel/config/target"

# TEST DATA:
ip=$(ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | head -n1 | sed "s@.*addr:\(.*\) Bcast.*@\1@")
md5=$(date | md5sum | cut -f1 -d' ')

# SETUP Device
mkdir -p $SYSFS_LIO/core/iblock_TID/mypool.test
echo -n "/dev/zvol/mypool/test" > $SYSFS_LIO/core/iblock_TID/mypool.test/udev_path
echo -n "udev_path=/dev/zvol/mypool/test" > $SYSFS_LIO/core/iblock_TID/mypool.test/control
echo -n $md5 > $SYSFS_LIO/core/iblock_TID/mypool.test/wwn/vpd_unit_serial
echo 1 > $SYSFS_LIO/core/iblock_TID/mypool.test/enable
echo 4096 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/block_size
echo 0 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/emulate_tas
echo 0 > $SYSFS_LIO/core/iblock_TID/mypool.test/attrib/emulate_ua_intlck_ctrl

# SETUP IQN/Target
mkdir -p $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/np/$ip:3260
mkdir -p $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/lun/lun_LUN
ln -s $SYSFS_LIO/core/iblock_TID/mypool.test \
$SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/lun/lun_LUN/$md5
echo -n 0 > $SYSFS_LIO/iscsi/discovery_auth/enforce_discovery_auth
echo 0 > $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/attrib/authentication
echo 1 > $SYSFS_LIO/iscsi/iqn.2010-09.org.zfsonlinux:mypool.test/tpgt_TID/enable

Here the value DEVICE is generated by iscsi.c:iscsi_generate_scst_device_name()
and is a randomized value, based on the exact time of day when
called. This because SCST have a limit of 16 characters for the device
name, and the chances of have duplicates is large. The BLOCKSIZE that
is used depends on what blocksize the ZVOL was created with.

The LUN value is by default 0 (1 for STGT becase LUN0 is the controller),
but can be overridden using the 'lun' option to the 'shareiscsi' property.

It (the driver) will automatically calculate the TID and IQN and use
only the ZVOL (in this case 'share/test') in the command lines.

If autogenerating the IQN is not wanted (because each reboot or unshare/share,
if it's done in another month, will generate a new IQN), a hardcoded default
can be set in /etc/iscsi_target_id like so:

echo iqn.2010-09.org.zfsonlinux > /etc/iscsi_target_id

Then all targets will start with this value, only adding a colon
and the ZVOL/dataset name (slashes replaced with dots):

iqn.2010-09.org.zfsonlinux:mypool.test


In addition to executing ietadm, tgtadm or modifying files below
/sys/kernel/scst_tgt or /sys/kernel/config/target, zfs will execute
the following script (if it exist and is executable)
'/sbin/zfs_share_iscsi.sh', like so:

/sbin/zfs_share_iscsi TID

This is so that one can create custom commands to be done on the
share.

The only parameter to this script/executable is the TID and the
driver will 'execute and forget'. Meaning, it will not care about
exit code nor any output it gives.

Example scripts have been provided, on for each of the iSCSI
implementation supported:

zfs_share_iscsi.iet
zfs_share_iscsi.lio
zfs_share_iscsi.scst
zfs_share_iscsi.stgt

Simply copy the one for your iSCSI implementation to /sbin/zfs_share/iscsi
and then modify it to your requirenments.

PS. The domainname needs to be set (in /proc/sys/kernel/domainname
using either 'sysctl', 'echo' or the command 'domainname') for
the driver to be able to work out the iqn correctly.

NOTE: This is only required if the IQN haven't been set in the
/etc/iscsi_target_id file!
29 changes: 29 additions & 0 deletions lib/libshare/destroy_lio.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/sh

# This is a script to simply unshare all LIO targets, without going through
# ZFS. Mostly used for testing...

SYSFS=/sys/kernel/config/target

cd $SYSFS/iscsi/
if [ -z "$*" ]; then
targets=`echo iqn.*`
else
targets=`echo $*`
fi

for name in $targets; do
tid=`echo $SYSFS/core/iblock_*/$name | sed "s@.*iblock_\(.*\)/.*@\1@"`
lnk=`find $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*/* | egrep -v 'alua|statistics' | sed 's@.*/@@'`

echo 0 > $SYSFS/iscsi/$name/tpgt_$tid/enable

rmdir $SYSFS/iscsi/$name/tpgt_$tid/np/*
rm $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*/$lnk
rmdir $SYSFS/iscsi/$name/tpgt_$tid/lun/lun_*
rmdir $SYSFS/iscsi/$name/tpgt_$tid
rmdir $SYSFS/iscsi/$name

rmdir $SYSFS/core/iblock_$tid/$name
rmdir $SYSFS/core/iblock_$tid
done
32 changes: 32 additions & 0 deletions lib/libshare/destroy_scst.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

# This is a script to somply unshare all SCST targets, without going through
# ZFS. Mostly used for testing...

SYSFS=/sys/kernel/scst_tgt

cd $SYSFS/targets/iscsi/
if [ -z "$*" ]; then
targets=`echo iqn.*`
else
targets=`echo $*`
fi

for name in $targets; do
find $SYSFS/targets/iscsi/$name/sessions/* -type d > /dev/null 2>&1
if [ "$?" -eq "1" ]; then
[ ! -f "$SYSFS/targets/iscsi/$name/enabled" ] && continue

#scstadmin -noprompt -disable_target $name -driver iscsi
echo 0 > $SYSFS/targets/iscsi/$name/enabled

#scstadmin -noprompt -close_dev $dev -handler vdisk_blockio
dev=`/bin/ls -l $SYSFS/targets/iscsi/$name/luns/0/device | sed 's@.*/@@'`
echo "del_device $dev" > $SYSFS/handlers/vdisk_blockio/mgmt

#scstadmin -noprompt -rem_target $name -driver iscsi
echo "del_target $name" > $SYSFS/targets/iscsi/mgmt
else
echo "Can't destroy $name - have sessions"
fi
done
Loading