From 16def0fe3d383e4d3056b4f034a85c3f5f31552e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 10 Jan 2014 08:27:48 +0000 Subject: [PATCH] scstadmin: Merge r4875:5189 from trunk git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@5192 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scstadmin/Makefile | 50 +- scstadmin/init.d/scst | 3 +- scstadmin/scstadmin.procfs/Makefile | 13 +- .../scst-0.8.22/lib/SCST/SCST.pm | 2 +- scstadmin/scstadmin.spec.in | 80 + scstadmin/scstadmin.sysfs/Makefile | 13 +- .../scst-0.9.10/lib/SCST/SCST.pm | 3103 ++++++++--------- .../scst-0.9.10/t/01-start-scst.t | 27 + .../scst-0.9.10/t/02-scst-attr.t | 46 + .../scst-0.9.10/t/03-targets.t | 365 ++ .../scstadmin.sysfs/scst-0.9.10/t/04-alua.t | 143 + .../scst-0.9.10/t/05-dynattr.t | 160 + .../scst-0.9.10/t/06-cont-on-err.t | 67 + .../scst-0.9.10/t/99-stop-scst.t | 21 + .../scst-0.9.10/t/after-restore.conf | 56 + .../scst-0.9.10/t/to-be-restored.conf | 62 + scstadmin/scstadmin.sysfs/scstadmin | 618 ++-- 17 files changed, 3000 insertions(+), 1829 deletions(-) create mode 100644 scstadmin/scstadmin.spec.in create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/01-start-scst.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/02-scst-attr.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/03-targets.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/04-alua.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/05-dynattr.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/99-stop-scst.t create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf create mode 100644 scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf diff --git a/scstadmin/Makefile b/scstadmin/Makefile index f874bae06..53821b3a8 100644 --- a/scstadmin/Makefile +++ b/scstadmin/Makefile @@ -1,10 +1,21 @@ +ifndef PREFIX + PREFIX=/usr/local +endif + +VERSION = $(shell echo -n "$$(sed -n 's/^[[:blank:]]*\$$VERSION[[:blank:]]*=[[:blank:]]*[\"'"'"']\([0-9.]*\)[\"'"'"'];$$/\1/p' scstadmin/scst-*/lib/SCST/SCST.pm)."; \ + if svn info >/dev/null 2>&1; \ + then svn info | sed -n 's/^Revision:[[:blank:]]*/r/p';\ + else git show | sed -n 's/^commit[[:blank:]]*\(.......\).*/\1/p'; \ + fi) + SCSTADMIN_DIR = $(shell if [ ! -h scstadmin ]; then \ rm -f scstadmin; \ ln -s scstadmin.sysfs scstadmin; \ fi; \ echo scstadmin) -MANDIR := $(DESTDIR)/usr/local/man +MANDIR ?= $(DESTDIR)$(PREFIX)/man + INITDIR := $(shell if [ -f /etc/slackware-version ]; then \ echo /etc/rc.d; \ else \ @@ -57,15 +68,12 @@ DEFAULTDIR := $(shell if [ -f /etc/gentoo-release ]; then \ all: cd $(SCSTADMIN_DIR) && $(MAKE) $@ -install: +install install_vendor: + @if [ -z "$(DESTDIR)" ] && rpm -q scstadmin >/dev/null 2>&1; then \ + echo Error: the scstadmin RPM must be uninstalled first; false; fi @if ! perl -MExtUtils::MakeMaker -e '' >/dev/null 2>&1; then \ echo Error: the Perl module ExtUtils::MakeMaker must be installed \ first; false; fi - @if [ ! -e /etc/slackware-version -a ! -e /etc/gentoo-release \ - -a ! -e /lib/lsb/init-functions ]; then \ - echo "Error: the lsb-core (Debian, Ubuntu), redhat-lsb (RHEL, CentOS,"\ - "Scientific Linux, Fedora) or insserv (SLES, openSUSE) package must" \ - "be installed first"; false; fi cd $(SCSTADMIN_DIR) && $(MAKE) $@ for m in scstadmin/man*/*.[1-9]; do \ if [ -e $$m ]; then \ @@ -111,6 +119,34 @@ uninstall: perl-module: cd $(SCSTADMIN_DIR) && $(MAKE) $@ +test: + $(MAKE) -C scstadmin test + +dist-gzip: + name=$(shell basename $$PWD) && \ + mkdir $${name}-$(VERSION) && \ + { ../scripts/list-source-files | tar -T- -cf- | \ + tar -C $${name}-$(VERSION) -xf-; } && \ + rm -f $${name}-$(VERSION).tar.bz2 && \ + tar -cjf $${name}-$(VERSION).tar.bz2 $${name}-$(VERSION) && \ + rm -rf $${name}-$(VERSION) + +rpm: + name=$(shell basename $$PWD) && \ + rpmtopdir="$$(if [ $$(id -u) = 0 ]; then echo /usr/src/packages;\ + else echo $$PWD/rpmbuilddir; fi)" && \ + $(MAKE) dist-gzip && \ + rm -rf $${rpmtopdir} && \ + for d in BUILD RPMS SOURCES SPECS SRPMS; do \ + mkdir -p $${rpmtopdir}/$$d; \ + done && \ + cp $${name}-$(VERSION).tar.bz2 $${rpmtopdir}/SOURCES && \ + sed "s/@rpm_version@/$(VERSION)/g" \ + <$${name}.spec.in >$${name}.spec && \ + MAKE="$(MAKE)" \ + rpmbuild --define="%_topdir $${rpmtopdir}" -ba $${name}.spec && \ + rm -f $${name}-$(VERSION).tar.bz2 + clean: cd $(SCSTADMIN_DIR) && $(MAKE) $@ diff --git a/scstadmin/init.d/scst b/scstadmin/init.d/scst index abeaa46e2..d4b1e4f33 100755 --- a/scstadmin/init.d/scst +++ b/scstadmin/init.d/scst @@ -79,6 +79,7 @@ fi cat <<"EOF" SCST_CFG=/etc/scst.conf +ISCSI_DAEMON="$(which iscsi-scstd)" show_status() { _rc_status_ret=$? @@ -159,7 +160,7 @@ parse_scst_conf() { SCST_OPT_MODULES="crc32c-intel $SCST_OPT_MODULES";; esac SCST_OPT_MODULES="crc32c $SCST_OPT_MODULES" - SCST_DAEMONS="/usr/local/sbin/iscsi-scstd $SCST_DAEMONS" + SCST_DAEMONS="${ISCSI_DAEMON} $SCST_DAEMONS" fi } diff --git a/scstadmin/scstadmin.procfs/Makefile b/scstadmin/scstadmin.procfs/Makefile index 715fed166..5d7a4626f 100644 --- a/scstadmin/scstadmin.procfs/Makefile +++ b/scstadmin/scstadmin.procfs/Makefile @@ -1,12 +1,16 @@ +ifndef PREFIX + PREFIX=/usr/local +endif + MODULE_VERSION = 0.8.22 TOOL = scstadmin -SBINDIR := $(PREFIX)/usr/local/sbin +SBINDIR := $(PREFIX)/sbin all: perl-module -install: all - $(MAKE) -C scst-$(MODULE_VERSION) install +install install_vendor: all + $(MAKE) -C scst-$(MODULE_VERSION) $@ DESTDIR=$(DESTDIR) install -d $(DESTDIR)$(SBINDIR) install -m 755 $(TOOL) $(DESTDIR)$(SBINDIR) @@ -19,6 +23,9 @@ perl-module: perl Makefile.PL; $(MAKE) -C scst-$(MODULE_VERSION) +test: + $(MAKE) -C scst-$(MODULE_VERSION) test + clean: -$(MAKE) -C scst-$(MODULE_VERSION) clean diff --git a/scstadmin/scstadmin.procfs/scst-0.8.22/lib/SCST/SCST.pm b/scstadmin/scstadmin.procfs/scst-0.8.22/lib/SCST/SCST.pm index 2533a9f30..e69905653 100644 --- a/scstadmin/scstadmin.procfs/scst-0.8.22/lib/SCST/SCST.pm +++ b/scstadmin/scstadmin.procfs/scst-0.8.22/lib/SCST/SCST.pm @@ -43,7 +43,7 @@ $IOTYPE_PHYSICAL = 100; $IOTYPE_VIRTUAL = 101; $IOTYPE_PERFORMANCE = 102; -$VERSION = 0.8.22; +$VERSION = '0.8.22'; my $_SCST_MIN_MAJOR_ = 2; my $_SCST_MIN_MINOR_ = 0; diff --git a/scstadmin/scstadmin.spec.in b/scstadmin/scstadmin.spec.in new file mode 100644 index 000000000..e1c57cf7f --- /dev/null +++ b/scstadmin/scstadmin.spec.in @@ -0,0 +1,80 @@ +%define rpm_version @rpm_version@ +%define make %{expand:%%(echo ${MAKE:-make})} + +Name: scstadmin +Version: %{rpm_version} +Release: 1 +Summary: SCST configuration tool +Group: Productivity/Networking/Other +License: GPLv2 +Vendor: http://scst.sourceforge.net/ +URL: http://scst.sourceforge.net/ + +Source: %{name}-%{version}.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +AutoReqProv: yes + +%description +A tool for configuring SCST via the SCST sysfs interface. Allows to save, +restore and modify any aspect of the SCST configuration. An extensive set of +commands is available to modify any configurable parameter of target drivers, +target ports, SCST devices, LUNs, initiator groups and ALUA configuration +information. + +Authors: +-------- + Mark R. Buechler, Bart Van Assche and others + +%define scstadmin_perl_installvendorman3dir \ + %(perl -V:installvendorman3dir | sed "s|.*='||;s|'.*||") +%define scstadmin_perl_process_packlist \ +set -x;\ +if test -n "$RPM_BUILD_ROOT" -a -d $RPM_BUILD_ROOT%perl_vendorarch/auto; then \ + find $RPM_BUILD_ROOT%perl_vendorarch/auto -name .packlist -print0 | \ + xargs -0 -r rm; \ + if [ %{_target_cpu} == noarch ]; then \ + find $RPM_BUILD_ROOT%perl_vendorarch/auto -depth -type d -print0 | \ + xargs -0 -r rmdir; \ + fi; \ + fi; \ + rm -f $RPM_BUILD_ROOT%{perl_archlib}/perllocal.pod; set +x + +%prep + +%setup -q + +%build +export PREFIX=%{_prefix} DESTDIR=%{buildroot} MANDIR=%{buildroot}%{_mandir} +%{make} + +%install +export PREFIX=%{_prefix} DESTDIR=%{buildroot} MANDIR=%{buildroot}%{_mandir} +%{make} install_vendor +%scstadmin_perl_process_packlist +rm -rf %{buildroot}/var/adm/perl-modules/scst + +%clean +rm -rf %{buildroot} + +%pre +rm -f /usr/local/sbin/scstadmin +rm -f /usr/local/man/man1/scstadmin.1* +rm -f /usr/local/man/man3/SCST::SCST.3pm* +rm -f /usr/local/man/man5/scst.5* +rm -f /usr/local/man/man5/scst.conf.5* + +%files +%defattr(-,root,root) +%config(noreplace) /etc/default/scst +/etc/init.d/scst +%{_sbindir}/scstadmin +%{perl_vendorlib}/SCST +%{perl_vendorarch}/auto/SCST-SCST +%{_mandir}/man1/scstadmin.1* +%{scstadmin_perl_installvendorman3dir}/SCST::SCST.3pm* +%{_mandir}/man5/scst.5* +%{_mandir}/man5/scst.conf.5* + +%changelog +* Fri Oct 04 2013 Bart Van Assche +- Initial spec file. diff --git a/scstadmin/scstadmin.sysfs/Makefile b/scstadmin/scstadmin.sysfs/Makefile index a2ce58a60..d6e9ee34c 100644 --- a/scstadmin/scstadmin.sysfs/Makefile +++ b/scstadmin/scstadmin.sysfs/Makefile @@ -1,12 +1,16 @@ +ifndef PREFIX + PREFIX=/usr/local +endif + MODULE_VERSION = 0.9.10 TOOL = scstadmin -SBINDIR := /usr/local/sbin +SBINDIR := $(PREFIX)/sbin all: perl-module -install: all - $(MAKE) -C scst-$(MODULE_VERSION) install +install install_vendor: all + $(MAKE) -C scst-$(MODULE_VERSION) $@ DESTDIR=$(DESTDIR) install -d $(DESTDIR)$(SBINDIR) install -m 755 $(TOOL) $(DESTDIR)$(SBINDIR) @@ -19,6 +23,9 @@ perl-module: perl Makefile.PL; $(MAKE) -C scst-$(MODULE_VERSION) +test: + $(MAKE) -C scst-$(MODULE_VERSION) test + clean: -$(MAKE) -C scst-$(MODULE_VERSION) clean diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/lib/SCST/SCST.pm b/scstadmin/scstadmin.sysfs/scst-0.9.10/lib/SCST/SCST.pm index f519ddeed..dc2748c40 100644 --- a/scstadmin/scstadmin.sysfs/scst-0.9.10/lib/SCST/SCST.pm +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/lib/SCST/SCST.pm @@ -143,6 +143,10 @@ SCST_C_DEV_GRP_EXISTS => 121, SCST_C_DEV_GRP_ADD_FAIL => 122, SCST_C_DEV_GRP_REM_FAIL => 123, +SCST_C_ALUA_BAD_ATTRIBUTES => 125, +SCST_C_ALUA_ATTRIBUTE_STATIC => 126, +SCST_C_ALUA_SETATTR_FAIL => 127, + SCST_C_DGRP_ADD_DEV_FAIL => 130, SCST_C_DGRP_REM_DEV_FAIL => 131, SCST_C_DGRP_NO_DEVICE => 132, @@ -175,7 +179,7 @@ my %VERBOSE_ERROR = ( (SCST_C_FATAL_ERROR) => 'A fatal error occured. See "dmesg" for more information.', (SCST_C_BAD_ATTRIBUTES) => 'Bad attributes given for SCST.', (SCST_C_ATTRIBUTE_STATIC) => 'SCST attribute specified is static', -(SCST_C_SETATTR_FAIL) => 'Failed to set a SCST attribute. See "demsg" for more information.', +(SCST_C_SETATTR_FAIL) => 'Failed to set a SCST attribute. See "dmesg" for more information.', (SCST_C_HND_NO_HANDLER) => 'No such handler exists.', (SCST_C_HND_BAD_ATTRIBUTES) => 'Bad attributes given for handler.', @@ -285,7 +289,7 @@ use vars qw(@ISA @EXPORT $VERSION); use vars qw($TGT_TYPE_HARDWARE $TGT_TYPE_VIRTUAL); -$VERSION = 0.9.10; +$VERSION = '0.9.10'; $TGT_TYPE_HARDWARE = 1; $TGT_TYPE_VIRTUAL = 2; @@ -296,52 +300,82 @@ my $_SCST_MIN_MAJOR_ = 2; my $_SCST_MIN_MINOR_ = 0; my $_SCST_MIN_RELEASE_ = 0; +my $_new_sysfs_interface; sub new_sysfs_interface { - return !(-d SCST_ROOT_OLD); + if (!defined($_new_sysfs_interface)) { + $_new_sysfs_interface = !(-d SCST_ROOT_OLD) ? TRUE : FALSE; + } + return $_new_sysfs_interface; } +my $_scst_root_dir; sub SCST_ROOT_DIR { - return -d SCST_ROOT_OLD ? SCST_ROOT_OLD : SCST_ROOT_NEW; + if (!defined($_scst_root_dir)) { + $_scst_root_dir = (-d SCST_ROOT_OLD ? SCST_ROOT_OLD : + SCST_ROOT_NEW); + } + return $_scst_root_dir; } +my $_scst_sgv_dir; sub SCST_SGV_DIR { - return SCST_ROOT_DIR() . '/sgv' + if (!defined($_scst_sgv_dir)) { + $_scst_sgv_dir = SCST_ROOT_DIR() . '/sgv'; + } + return $_scst_sgv_dir; } +my $_scst_queue_res_path = ""; sub SCST_QUEUE_RES_PATH { - return -d SCST_ROOT_OLD ? SCST_ROOT_OLD . '/' . SCST_QUEUE_RES : undef; + if ($_scst_queue_res_path eq "") { + $_scst_queue_res_path = (-d SCST_ROOT_OLD ? + SCST_ROOT_OLD . '/' . SCST_QUEUE_RES : + undef); + } + return $_scst_queue_res_path; } # Device handlers. +my $_scst_handlers_dir; sub SCST_HANDLERS_DIR { - if (-d SCST_ROOT_OLD) { - return SCST_ROOT_OLD . '/' . SCST_HANDLERS; - } else { - return '/sys/bus/scst_tgt_dev/drivers'; + if (!defined($_scst_handlers_dir)) { + $_scst_handlers_dir = (-d SCST_ROOT_OLD ? + SCST_ROOT_OLD . '/' . SCST_HANDLERS : + '/sys/bus/scst_tgt_dev/drivers'); } + return $_scst_handlers_dir; } # Device instances. +my $_scst_devices_dir; sub SCST_DEVICES_DIR { - if (-d SCST_ROOT_OLD) { - return SCST_ROOT_OLD . '/' . SCST_DEVICES; - } else { - return '/sys/bus/scst_tgt_dev/devices'; + if (!defined($_scst_devices_dir)) { + $_scst_devices_dir = (-d SCST_ROOT_OLD ? + SCST_ROOT_OLD . '/' . SCST_DEVICES : + '/sys/bus/scst_tgt_dev/devices'); } + return $_scst_devices_dir; } # Target drivers. +my $_scst_targets_dir; sub SCST_TARGETS_DIR { - if (-d SCST_ROOT_OLD) { - return SCST_ROOT_OLD . '/' . SCST_TARGETS; - } else { - return '/sys/bus/scst_target/drivers'; + if (!defined($_scst_targets_dir)) { + $_scst_targets_dir = (-d SCST_ROOT_OLD ? + SCST_ROOT_OLD . '/' . SCST_TARGETS : + '/sys/bus/scst_target/drivers'); } + return $_scst_targets_dir; } # ALUA Device groups. +my $_scst_dev_group_dir; sub SCST_DEV_GROUP_DIR { - return make_path(SCST_ROOT_DIR(), SCST_DEV_GROUPS); + if (!defined($_scst_dev_group_dir)) { + $_scst_dev_group_dir = make_path(SCST_ROOT_DIR(), + SCST_DEV_GROUPS); + } + return $_scst_dev_group_dir; } sub new { @@ -380,7 +414,7 @@ sub new { sub scstVersion { my $self = shift; - my $attributes = $self->scstAttributes(); + my ($attributes, $errorString) = $self->scstAttributes(); return undef if (!defined($attributes)); return $$attributes{'version'}->{'value'}; @@ -393,8 +427,7 @@ sub scstAttributes { my $pHandle = new IO::Handle; my $_path = SCST_ROOT_DIR(); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "scstAttributes(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "scstAttributes(): Unable to read directory '$_path': $!"); } foreach my $attribute (readdir($pHandle)) { @@ -420,23 +453,22 @@ sub scstAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "scsiAttributes(): Unable to read ". - "scst attribute '$attribute': $!"; - return undef; + return (undef, "scsiAttributes(): Unable to read ". + "scst attribute '$attribute': $!"); } my $value = <$io>; - chomp $value; + chomp $value if (defined($value)); my $is_key = <$io>; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -467,13 +499,24 @@ sub scstAttributes { $attributes{$attribute}->{'value'} = $value; } } + close $io; $attributes{$attribute}->{'static'} = $is_static; } } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); +} + +sub setAttrFailed { + my $path = shift; + my $no_such_attr = shift; + my $is_static = shift; + + return (-f $path) && (-r $path) ? $is_static : $no_such_attr; } sub setScstAttribute { @@ -483,123 +526,116 @@ sub setScstAttribute { return TRUE if (!defined($attribute) || !defined($value)); - my $attributes = $self->scstAttributes(); - - return SCST_C_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my $path = make_path(SCST_ROOT_DIR(), $attribute); - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_BAD_ATTRIBUTES, + SCST_C_ATTRIBUTE_STATIC); } +my @_drivers; sub drivers { my $self = shift; - my @drivers; - my $dHandle = new IO::Handle; - my $_path = SCST_TARGETS_DIR(); - if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "drivers(): Unable to read directory '$_path': $!"; - return undef; - } + if (!@_drivers) { + my $dHandle = new IO::Handle; + my $_path = SCST_TARGETS_DIR(); + if (opendir $dHandle, $_path) { + foreach my $driver (readdir($dHandle)) { + next if (($driver eq '.') || ($driver eq '..')); - foreach my $driver (readdir($dHandle)) { - next if (($driver eq '.') || ($driver eq '..')); - - if (-d make_path(SCST_TARGETS_DIR(), $driver)) { - push @drivers, $driver; + if (-d make_path(SCST_TARGETS_DIR(), $driver)) { + push @_drivers, $driver; + } + } + close $dHandle; + } else { + return (undef, "drivers(): Unable to read directory '$_path': $!"); } } - close $dHandle; - - return \@drivers; + return (\@_drivers, undef); } sub targets { my $self = shift; my $driver = shift; - my @targets; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "targets(): Driver '$driver' is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver)); my $tHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver); - if (!(opendir $tHandle, $_path)) { - $self->{'err_string'} = "targets(): Unable to read directory '$_path': $!"; - return undef; - } + if (opendir $tHandle, $_path) { + my @targets; - foreach my $target (readdir($tHandle)) { - next if ($target eq '.' || $target eq '..' || - $target eq 'module'); + foreach my $target (readdir($tHandle)) { + next if ($target eq '.' || $target eq '..' || + $target eq 'module'); - if (-d make_path(SCST_TARGETS_DIR(), $driver, $target)) { - push @targets, $target; + if (-d make_path(SCST_TARGETS_DIR(), $driver, + $target)) { + push @targets, $target; + } } + close $tHandle; + @targets = sort(@targets); + return (\@targets, undef); + } + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "targets(): Driver '$driver' is not available"; + } else { + $errorString = "targets(): Unable to read directory '$_path': $!"; } - close $tHandle; - - return \@targets; + return (undef, $errorString); } sub groups { my $self = shift; my $driver = shift; my $target = shift; - my @groups; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "groups(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "groups(): Target '$target' is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver) || !defined($target)); my $gHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS); - if (!(opendir $gHandle, $_path)) { - $self->{'err_string'} = "groups(): Unable to read directory '$_path': $!"; - return undef; - } - foreach my $group (readdir($gHandle)) { - next if (($group eq '.') || ($group eq '..')); + if (opendir $gHandle, $_path) { + my @groups; - if (-d make_path(SCST_TARGETS_DIR(), $driver, - $target, SCST_GROUPS, $group)) { - push @groups, $group; + foreach my $group (readdir($gHandle)) { + next if ($group eq '.' || $group eq '..'); + + if (-d make_path(SCST_TARGETS_DIR(), $driver, + $target, SCST_GROUPS, $group)) { + push @groups, $group; + } } + close $gHandle; + return (\@groups, undef); } - close $gHandle; - - return \@groups; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "groups(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "groups(): Target '$target' is not available"; + } else { + $errorString = "groups(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } sub initiators { @@ -609,27 +645,24 @@ sub initiators { my $group = shift; my @initiators; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "initiators(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "initiators(): Target '$target' is not available"; - return undef; - } - - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "initiators(): Group '$group' does not exist"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver) || !defined($target) || + !defined($group)); my $iHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_INITIATORS); if (!(opendir $iHandle, $_path)) { - $self->{'err_string'} = "initiators(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "initiators(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "initiators(): Target '$target' is not available"; + } elsif ($self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "initiators(): Group '$group' does not exist"; + } else { + $errorString = "initiators(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $initiator (readdir($iHandle)) { @@ -641,7 +674,7 @@ sub initiators { close $iHandle; - return \@initiators; + return (\@initiators, undef); } sub luns { @@ -649,26 +682,12 @@ sub luns { my $driver = shift; my $target = shift; my $group = shift; - my %luns; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "luns(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "luns(): Target '$target' is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver) || !defined($target)); my $_path; if (defined($group)) { - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "initiators(): Group '$group' does not exist"; - return undef; - } - $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_LUNS); } else { @@ -679,10 +698,21 @@ sub luns { my $lHandle = new IO::Handle; if (!(opendir $lHandle, $_path)) { - $self->{'err_string'} = "luns(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if (defined($group) && $self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "initiators(): Group '$group' does not exist"; + } elsif ($self->driverExists($driver) != TRUE) { + $errorString = "luns(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "luns(): Target '$target' is not available"; + } else { + $errorString = "luns(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } + my %luns; + foreach my $lun (readdir($lHandle)) { next if (($lun eq '.') || ($lun eq '..')); @@ -692,8 +722,7 @@ sub luns { my $_lHandle = new IO::Handle; if (!(opendir $_lHandle, $lPath)) { - $self->{'err_string'} = "luns(): Unable to read directory '$lPath': $!"; - return undef; + return (undef, "luns(): Unable to read directory '$lPath': $!"); } foreach my $attribute (readdir($_lHandle)) { @@ -705,12 +734,67 @@ sub luns { $luns{$lun} = $linked; } } + + close $_lHandle; } } close $lHandle; - return \%luns; + return (\%luns, undef); +} + +sub aluaAttributes { + my $self = shift; + my %attributes; + + my $pHandle = new IO::Handle; + my $_path = SCST_DEV_GROUP_DIR(); + if (!(opendir $pHandle, $_path)) { + return (undef, "deviceGroupsAttributes(): Unable to read directory '$_path': $!"); + } + + foreach my $attribute (readdir($pHandle)) { + next if ($attribute eq '.' || $attribute eq '..' || + $attribute eq SCST_MGMT_IO || $attribute eq 'uevent'); + my $pPath = make_path(SCST_DEV_GROUP_DIR(), $attribute); + my $mode = (stat($pPath))[2]; + + if (!($mode & S_IRUSR)) { + $attributes{$attribute}->{'static'} = FALSE; + $attributes{$attribute}->{'value'} = undef; + } else { + my $is_static = !($mode & S_IWUSR); + my $io = new IO::File $pPath, O_RDONLY; + + if (!$io) { + return (undef, "deviceGroupsAttributes(): Unable to read device attribute '$attribute': $!"); + } + + my $value = <$io>; + chomp $value; + + my $second_line = <$io>; + if (new_sysfs_interface() && !$is_static + || ($second_line =~ /\[key\]/)) { + my $key = 0; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; + } + $attributes{$attribute}->{'keys'}->{$key}->{'value'} = $value; + } else { + $attributes{$attribute}->{'value'} = $value; + } + close $io; + + $attributes{$attribute}->{'static'} = $is_static; + } + } + + close $pHandle; + + return (\%attributes, undef); } sub deviceGroups { @@ -720,8 +804,7 @@ sub deviceGroups { my $dHandle = new IO::Handle; my $_path = SCST_DEV_GROUP_DIR(); if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "deviceGroups(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "deviceGroups(): Unable to read directory '$_path': $!"); } foreach my $group (readdir($dHandle)) { @@ -734,7 +817,7 @@ sub deviceGroups { close $dHandle; - return \@groups; + return (\@groups, undef); } sub deviceGroupDevices { @@ -742,16 +825,18 @@ sub deviceGroupDevices { my $group = shift; my @devices; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "deviceGroupDevices(): Device group '$group' does not exist"; - return undef; - } + return (undef, "Too few arguments") if (!defined($group)); my $dHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_DEVICES); if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "deviceGroupDevices(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "deviceGroupDevices(): Device group '$group' does not exist"; + } else { + $errorString = "deviceGroupDevices(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $device (readdir($dHandle)) { @@ -764,7 +849,7 @@ sub deviceGroupDevices { close $dHandle; - return \@devices; + return (\@devices, undef); } sub targetGroups { @@ -772,16 +857,18 @@ sub targetGroups { my $group = shift; my @tgroups; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroups(): Device group '$group' does not exist"; - return undef; - } + return (undef, "Too few arguments") if (!defined($group)); my $dHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS); if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "targetGroups(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "targetGroups(): Device group '$group' does not exist"; + } else { + $errorString = "targetGroups(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $tgroup (readdir($dHandle)) { @@ -794,7 +881,7 @@ sub targetGroups { close $dHandle; - return \@tgroups; + return (\@tgroups, undef); } sub targetGroupTargets { @@ -803,21 +890,20 @@ sub targetGroupTargets { my $tgroup = shift; my @targets; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupTargets(): Device group '$group' does not exist"; - return undef; - } - - if ($self->targetGroupExists($group, $tgroup) != TRUE) { - $self->{'err_string'} = "targetGroupTargets(): Target group '$tgroup' does not exist"; - return undef; - } + return (undef, "Too few arguments") if (!defined($group) || !defined($tgroup)); my $dHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, $tgroup); if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "targetGroupTargets(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "targetGroupTargets(): Device group '$group' does not exist"; + } elsif ($self->targetGroupExists($group, $tgroup) != TRUE) { + $errorString = "targetGroupTargets(): Target group '$tgroup' does not exist"; + } else { + $errorString = "targetGroupTargets(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $tgt (readdir($dHandle)) { @@ -830,14 +916,18 @@ sub targetGroupTargets { close $dHandle; - return \@targets; + @targets = sort(@targets); + + return (\@targets, undef); } sub driverExists { my $self = shift; my $driver = shift; - my $drivers = $self->drivers(); + return FALSE if (!defined($driver)); + + my ($drivers, $errorString) = $self->drivers(); return SCST_C_FATAL_ERROR if (!defined($drivers)); @@ -854,11 +944,7 @@ sub driverDynamicAttributes { my %attributes; my $available; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "driverDynamicAttributes(): Driver '$driver' ". - "is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver)); if (new_sysfs_interface()) { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, @@ -868,15 +954,22 @@ sub driverDynamicAttributes { chomp($attribute); $attributes{$attribute} = ''; } + close $io; } } else { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, SCST_MGMT_IO), O_RDONLY; if (!$io) { - $self->{'err_string'} = "driverDynamicAttributes(): Unable to open mgmt ". - "interface for driver '$driver': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "driverDynamicAttributes(): Driver '$driver' ". + "is not available"; + } else { + $errorString = "driverDynamicAttributes(): Unable to open mgmt ". + "interface for driver '$driver': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -885,6 +978,7 @@ sub driverDynamicAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -895,7 +989,7 @@ sub driverDynamicAttributes { } } - return \%attributes; + return (\%attributes, undef); } sub checkDriverDynamicAttributes { @@ -903,16 +997,18 @@ sub checkDriverDynamicAttributes { my $driver = shift; my $check = shift; + my ($available, $errorString) = $self->driverDynamicAttributes($driver); + + if (!defined($available)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if (!$rc > 1); + + return SCST_C_FATAL_ERROR; + } + return FALSE if (!defined($check)); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if (!$rc > 1); - - my $available = $self->driverDynamicAttributes($driver); - - return SCST_C_FATAL_ERROR if (!defined($available)); - if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { if (!defined($$available{$attribute})) { @@ -934,15 +1030,8 @@ sub addDriverDynamicAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); - - $rc = $self->checkDriverDynamicAttributes($driver, $attribute); - return SCST_C_DRV_BAD_ATTRIBUTES if ($rc == 1); - return $rc if ($rc > 1); + return SCST_C_DRV_ADDATTR_FAIL + if (!defined($driver) || !defined($attribute) || !defined($value)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -954,30 +1043,17 @@ sub addDriverDynamicAttribute { $cmd .= "add_attribute $attribute $value"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DRV_ADDATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DRV_ADDATTR_FAIL; - -} - -sub removeDriverDynamicAttribute { - my $self = shift; - my $driver = shift; - my $attribute = shift; - my $value = shift; - my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -988,6 +1064,18 @@ sub removeDriverDynamicAttribute { return SCST_C_DRV_BAD_ATTRIBUTES if ($rc == 1); return $rc if ($rc > 1); + return SCST_C_DRV_ADDATTR_FAIL; +} + +sub removeDriverDynamicAttribute { + my $self = shift; + my $driver = shift; + my $attribute = shift; + my $value = shift; + + return SCST_C_DRV_REMATTR_FAIL + if (!defined($driver) || !defined($attribute) || !defined($value)); + my ($path, $cmd); if (new_sysfs_interface()) { $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); @@ -998,20 +1086,27 @@ sub removeDriverDynamicAttribute { $cmd .= "del_attribute $attribute $value"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DRV_REMATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); + + $rc = $self->checkDriverDynamicAttributes($driver, $attribute); + return SCST_C_DRV_BAD_ATTRIBUTES if ($rc == 1); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_DRV_REMATTR_FAIL; } @@ -1020,37 +1115,21 @@ sub targetExists { my $driver = shift; my $target = shift; - return FALSE if (!defined($target)); - - my $rc = $self->driverExists($driver); - - return FALSE if (!$rc); - return $rc if ($rc > 1); - - my $targets = $self->targets($driver); - - return SCST_C_FATAL_ERROR if (!defined($targets)); - - foreach my $_target (@{$targets}) { - return TRUE if ($target eq $_target); - } - - return FALSE; + return defined($driver) && defined($target) && + $target ne '.' && $target ne '..' && $target ne 'module' && + (-d make_path(SCST_TARGETS_DIR(), $driver, $target)) ? TRUE : FALSE; } sub driverIsVirtualCapable { my $self = shift; my $driver = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - if (new_sysfs_interface()) { my $path = make_path(SCST_TARGETS_DIR(), $driver, SCST_ADD_TGT); my $io = new IO::File $path, O_RDONLY; if ($io) { my $line = <$io>; + close $io; chomp($line); return $line eq '1'; } @@ -1066,8 +1145,10 @@ sub targetType { my $driver = shift; my $target = shift; + return (undef, "Too few arguments") if (!defined($driver) || !defined($target)); + if ($self->driverIsVirtualCapable($driver)) { - my $attribs = $self->targetAttributes($driver, $target); + my ($attribs, $errorString) = $self->targetAttributes($driver, $target); if (defined($$attribs{'hw_target'}) && ($$attribs{'hw_target'}->{'value'} == TRUE)) { @@ -1086,21 +1167,7 @@ sub addVirtualTarget { my $target = shift; my $attributes = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_EXISTS if ($rc); - return $rc if ($rc > 1); - - return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); - - $rc = $self->checkTargetCreateAttributes($driver, $attributes); - return SCST_C_TGT_BAD_ATTRIBUTES if ($rc == TRUE); - return $rc if ($rc > 1); - - my $o_string; + my $o_string = ""; foreach my $attribute (keys %{$attributes}) { if (ref($$attributes{$attribute}) eq 'ARRAY') { foreach my $value (@{$$attributes{$attribute}}) { @@ -1124,20 +1191,31 @@ sub addVirtualTarget { $cmd .= "add_target $target $o_string"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGT_ADD_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_EXISTS if ($rc); + return $rc if ($rc > 1); + + return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); + + $rc = $self->checkTargetCreateAttributes($driver, $attributes); + return SCST_C_TGT_BAD_ATTRIBUTES if ($rc == TRUE); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_TGT_ADD_FAIL; } @@ -1147,11 +1225,7 @@ sub targetDynamicAttributes { my %attributes; my $available; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "targetDynamicAttributes(): Driver '$driver' ". - "is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver)); if (new_sysfs_interface()) { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, @@ -1161,15 +1235,22 @@ sub targetDynamicAttributes { chomp($attribute); $attributes{$attribute} = ''; } + close $io; } } else { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, SCST_MGMT_IO), O_RDONLY; if (!$io) { - $self->{'err_string'} = "targetDynamicAttributes(): Unable to open mgmt ". - "interface for driver '$driver': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "targetDynamicAttributes(): Driver '$driver' ". + "is not available"; + } else { + $errorString = "targetDynamicAttributes(): Unable to open mgmt ". + "interface for driver '$driver': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -1178,6 +1259,7 @@ sub targetDynamicAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -1188,7 +1270,7 @@ sub targetDynamicAttributes { } } - return \%attributes; + return (\%attributes, undef); } sub checkTargetDynamicAttributes { @@ -1196,16 +1278,18 @@ sub checkTargetDynamicAttributes { my $driver = shift; my $check = shift; + my ($available, $errorString) = $self->targetDynamicAttributes($driver); + + if (!defined($available)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if (!$rc > 1); + + return SCST_C_FATAL_ERROR; + } + return FALSE if (!defined($check)); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if (!$rc > 1); - - my $available = $self->targetDynamicAttributes($driver); - - return SCST_C_FATAL_ERROR if (!defined($available)); - if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { if (!defined($$available{$attribute})) { @@ -1228,19 +1312,9 @@ sub addTargetDynamicAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); - - $rc = $self->checkTargetDynamicAttributes($driver, $attribute); - return SCST_C_TGT_BAD_ATTRIBUTES if ($rc == 1); - return $rc if ($rc > 1); + return SCST_C_TGT_ADDATTR_FAIL + if (!defined($driver) || !defined($target) || + !defined($attribute) || !defined($value)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1252,30 +1326,17 @@ sub addTargetDynamicAttribute { $cmd .= "add_target_attribute $target $attribute $value"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGT_ADDATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGT_ADDATTR_FAIL; -} - -sub removeTargetDynamicAttribute { - my $self = shift; - my $driver = shift; - my $target = shift; - my $attribute = shift; - my $value = shift; - my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -1290,6 +1351,20 @@ sub removeTargetDynamicAttribute { return SCST_C_TGT_BAD_ATTRIBUTES if ($rc == 1); return $rc if ($rc > 1); + return SCST_C_TGT_ADDATTR_FAIL; +} + +sub removeTargetDynamicAttribute { + my $self = shift; + my $driver = shift; + my $target = shift; + my $attribute = shift; + my $value = shift; + + return SCST_C_TGT_REMATTR_FAIL + if (!defined($driver) || !defined($target) || + !defined($attribute) || !defined($value)); + my ($path, $cmd); if (new_sysfs_interface()) { $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); @@ -1300,28 +1375,17 @@ sub removeTargetDynamicAttribute { $cmd .= "del_target_attribute $target $attribute $value"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGT_REMATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGT_REMATTR_FAIL; -} - -sub removeVirtualTarget { - my $self = shift; - my $driver = shift; - my $target = shift; - my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -1332,9 +1396,23 @@ sub removeVirtualTarget { return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); + $rc = $self->checkTargetDynamicAttributes($driver, $attribute); + return SCST_C_TGT_BAD_ATTRIBUTES if ($rc == 1); + return $rc if ($rc > 1); + + return SCST_C_TGT_REMATTR_FAIL; +} + +sub removeVirtualTarget { + my $self = shift; + my $driver = shift; + my $target = shift; + + # May fail if the target does not have an 'enabled' attribute as is the + # case for e.g. the 'scst_local' driver. $self->enableTarget($driver, $target, FALSE); - my $sessions = $self->sessions($driver, $target); + my ($sessions, $errorString) = $self->sessions($driver, $target); my %can_close; foreach my $session (keys %{$sessions}) { @@ -1349,7 +1427,7 @@ sub removeVirtualTarget { my $has_sessions = 1; my $now = time(); while ($has_sessions && (($now + $TIMEOUT) > time())) { - $sessions = $self->sessions($driver, $target); + ($sessions, $errorString) = $self->sessions($driver, $target); foreach my $session (keys %can_close) { if (!defined($$sessions{$session})) { @@ -1374,21 +1452,27 @@ sub removeVirtualTarget { $cmd .= "del_target $target"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGT_REM_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + return SCST_C_DRV_NOTVIRT if (!$self->driverIsVirtualCapable($driver)); - return SCST_C_TGT_BUSY if ($bytes == -1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_TGT_REM_FAIL; } @@ -1398,16 +1482,17 @@ sub groupExists { my $target = shift; my $group = shift; - return FALSE if (!defined($group)); + return FALSE if (!defined($driver) || !defined($target) || !defined($group)); - my $rc = $self->targetExists($driver, $target); + my ($groups, $errorString) = $self->groups($driver, $target); - return FALSE if (!$rc); - return $rc if ($rc > 1); + if (!defined($groups)) { + my $rc = $self->targetExists($driver, $target); + return FALSE if (!$rc); + return $rc if ($rc > 1); - my $groups = $self->groups($driver, $target); - - return SCST_C_FATAL_ERROR if (!defined($groups)); + return SCST_C_FATAL_ERROR; + } foreach my $_group (@{$groups}) { return TRUE if ($group eq $_group); @@ -1423,16 +1508,18 @@ sub initiatorExists { my $group = shift; my $initiator = shift; - return FALSE if (!defined($initiator)); + return FALSE if (!defined($driver) || !defined($target) || + !defined($group) || !defined($initiator)); - my $rc = $self->groupExists($driver, $target, $group); + my ($initiators, $errorString) = $self->initiators($driver, $target, $group); - return FALSE if (!$rc); - return $rc if ($rc > 1); + if (!defined($initiators)) { + my $rc = $self->groupExists($driver, $target, $group); + return FALSE if (!$rc); + return $rc if ($rc > 1); - my $initiators = $self->initiators($driver, $target, $group); - - return SCST_C_FATAL_ERROR if (!defined($initiators)); + return SCST_C_FATAL_ERROR; + } foreach my $_initiator (@{$initiators}) { return TRUE if ($initiator eq $_initiator); @@ -1448,27 +1535,28 @@ sub lunExists { my $lun = shift; my $group = shift; - return FALSE if (!defined($lun)); + return FALSE if (!defined($driver) || !defined($target) || + !defined($lun)); + my ($luns, $errorString) = $self->luns($driver, $target, $group); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_EXISTS if (!$rc); - return $rc if ($rc > 1); - - if (defined($group)) { - my $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); + if (!defined($luns)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + if (defined($group)) { + my $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + return SCST_C_FATAL_ERROR; } - my $luns = $self->luns($driver, $target, $group); - - return SCST_C_FATAL_ERROR if (!defined($luns)); - foreach my $_lun (keys %{$luns}) { return TRUE if ($lun == $_lun); } @@ -1482,17 +1570,8 @@ sub addGroup { my $target = shift; my $group = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_EXISTS if ($rc == TRUE); - return $rc if ($rc > 1); + return SCST_C_GRP_ADD_FAIL if (!defined($driver) || !defined($target) || + !defined($group)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1506,20 +1585,29 @@ sub addGroup { $cmd .= "create $group"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_ADD_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_EXISTS if ($rc == TRUE); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_GRP_ADD_FAIL; } @@ -1529,6 +1617,32 @@ sub removeGroup { my $target = shift; my $group = shift; + return SCST_C_GRP_REM_FAIL if (!defined($driver) || !defined($target) || + !defined($group)); + + my ($path, $cmd); + if (new_sysfs_interface()) { + $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); + $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, + SCST_GROUPS) . " "; + } else { + $path = make_path(SCST_TARGETS_DIR(), $driver, $target, + SCST_GROUPS, SCST_MGMT_IO); + } + $cmd .= "del $group"; + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -1541,32 +1655,6 @@ sub removeGroup { return SCST_C_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); - my ($path, $cmd); - if (new_sysfs_interface()) { - $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); - $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, - SCST_GROUPS) . " "; - } else { - $path = make_path(SCST_TARGETS_DIR(), $driver, $target, - SCST_GROUPS, SCST_MGMT_IO); - } - $cmd .= "del $group"; - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_REM_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_GRP_REM_FAIL; } @@ -1574,9 +1662,7 @@ sub addDeviceGroup { my $self = shift; my $group = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_EXISTS if ($rc == TRUE); - return $rc if ($rc > 1); + return SCST_C_DEV_GRP_ADD_FAIL if (!defined($group)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1588,30 +1674,27 @@ sub addDeviceGroup { $cmd .= "create $group"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DEV_GRP_ADD_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DEV_GRP_ADD_FAIL; + my $rc = $self->deviceGroupExists($group); + return $rc == TRUE ? SCST_C_DEV_GRP_EXISTS : $rc > 1 ? $rc : + SCST_C_DEV_GRP_ADD_FAIL; } sub removeDeviceGroup { my $self = shift; my $group = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); + return SCST_C_DEV_GRP_REM_FAIL if (!defined($group)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1623,20 +1706,21 @@ sub removeDeviceGroup { $cmd .= "del $group"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DEV_GRP_REM_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceGroupExists($group); + return SCST_C_DEV_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_DEV_GRP_REM_FAIL; } @@ -1645,6 +1729,30 @@ sub addDeviceGroupDevice { my $group = shift; my $device = shift; + return SCST_C_DGRP_ADD_DEV_FAIL if (!defined($group) || !defined($device)); + + my ($path, $cmd); + if (new_sysfs_interface()) { + $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); + $cmd = "in " . make_path(IN_SCST_DEV_GROUPS, $group, + SCST_DG_DEVICES) . " "; + } else { + $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_DEVICES, SCST_MGMT_IO); + } + $cmd .= "add $device"; + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->deviceGroupExists($group); return SCST_C_DEV_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); @@ -1658,41 +1766,16 @@ sub addDeviceGroupDevice { return $rc if ($rc > 1); # Check all device groups for this device - my $dgroups = $self->deviceGroups(); + my ($dgroups, $errorString) = $self->deviceGroups(); foreach my $dgroup (@{$dgroups}) { - my $devs = $self->deviceGroupDevices($dgroup); + my ($devs, $errorString) = $self->deviceGroupDevices($dgroup); foreach my $dev (@{$devs}) { return SCST_C_DGRP_DEVICE_OTHER if ($dev eq $device); } } - my ($path, $cmd); - if (new_sysfs_interface()) { - $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); - $cmd = "in " . make_path(IN_SCST_DEV_GROUPS, $group, - SCST_DG_DEVICES) . " "; - } else { - $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_DEVICES, SCST_MGMT_IO); - } - $cmd .= "add $device"; - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DGRP_ADD_DEV_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_DGRP_ADD_DEV_FAIL; } @@ -1701,13 +1784,8 @@ sub addTargetGroup { my $group = shift; my $tgroup = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetGroupExists($group, $tgroup); - return SCST_C_DGRP_GROUP_EXISTS if ($rc == TRUE); - return $rc if ($rc > 1); + return SCST_C_DGRP_ADD_GRP_FAIL if (!defined($group) || + !defined($tgroup)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1720,21 +1798,24 @@ sub addTargetGroup { $cmd .= "add $tgroup"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DGRP_ADD_GRP_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceGroupExists($group); + return SCST_C_DEV_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DGRP_ADD_GRP_FAIL; + $rc = $self->targetGroupExists($group, $tgroup); + return SCST_C_DGRP_GROUP_EXISTS if ($rc == TRUE); + return $rc > 1 ? $rc : SCST_C_DGRP_ADD_GRP_FAIL; } sub addTargetGroupTarget { @@ -1743,17 +1824,9 @@ sub addTargetGroupTarget { my $tgroup = shift; my $tgt = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetGroupExists($group, $tgroup); - return SCST_C_DGRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetGroupTargetExists($group, $tgroup, $tgt); - return SCST_C_TGRP_TGT_EXISTS if ($rc == TRUE); - return $rc if ($rc > 1); + return SCST_C_TGRP_ADD_TGT_FAIL if (!defined($group) || + !defined($tgroup) || + !defined($tgt)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1767,21 +1840,27 @@ sub addTargetGroupTarget { $cmd .= "add $tgt"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGRP_ADD_TGT_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceGroupExists($group); + return SCST_C_DEV_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGRP_ADD_TGT_FAIL; + $rc = $self->targetGroupExists($group, $tgroup); + return SCST_C_DGRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetGroupTargetExists($group, $tgroup, $tgt); + return $rc == TRUE ? SCST_C_TGRP_TGT_EXISTS : $rc > 1 ? $rc : SCST_C_TGRP_ADD_TGT_FAIL; } sub removeDeviceGroupDevice { @@ -1789,6 +1868,30 @@ sub removeDeviceGroupDevice { my $group = shift; my $device = shift; + return SCST_C_DGRP_REM_DEV_FAIL if (!defined($group) || !defined($device)); + + my ($path, $cmd); + if (new_sysfs_interface()) { + $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); + $cmd = "in " . make_path(IN_SCST_DEV_GROUPS, $group, + SCST_DG_DEVICES) . " "; + } else { + $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_DEVICES, SCST_MGMT_IO); + } + $cmd .= "del $device"; + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->deviceGroupExists($group); return SCST_C_DEV_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); @@ -1801,31 +1904,6 @@ sub removeDeviceGroupDevice { return SCST_C_DGRP_NO_DEVICE if (!$rc); return $rc if ($rc > 1); - my ($path, $cmd); - if (new_sysfs_interface()) { - $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); - $cmd = "in " . make_path(IN_SCST_DEV_GROUPS, $group, - SCST_DG_DEVICES) . " "; - } else { - $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_DEVICES, SCST_MGMT_IO); - } - $cmd .= "del $device"; - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DGRP_REM_DEV_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_DGRP_REM_DEV_FAIL; } @@ -1834,13 +1912,7 @@ sub removeTargetGroup { my $group = shift; my $tgroup = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetGroupExists($group, $tgroup); - return SCST_C_DGRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); + return SCST_C_DGRP_REM_GRP_FAIL if (!defined($group) || !defined($tgroup)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1853,29 +1925,17 @@ sub removeTargetGroup { $cmd .= "del $tgroup"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DGRP_REM_GRP_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DGRP_REM_GRP_FAIL; -} - -sub removeTargetGroupTarget { - my $self = shift; - my $group = shift; - my $tgroup = shift; - my $tgt = shift; - my $rc = $self->deviceGroupExists($group); return SCST_C_DEV_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); @@ -1884,9 +1944,16 @@ sub removeTargetGroupTarget { return SCST_C_DGRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); - $rc = $self->targetGroupTargetExists($group, $tgroup, $tgt); - return SCST_C_TGRP_NO_TGT if (!$rc); - return $rc if ($rc > 1); + return SCST_C_DGRP_REM_GRP_FAIL; +} + +sub removeTargetGroupTarget { + my $self = shift; + my $group = shift; + my $tgroup = shift; + my $tgt = shift; + + return SCST_C_TGRP_REM_TGT_FAIL if (!defined($group) || !defined($tgroup) || !defined($tgt)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -1900,20 +1967,29 @@ sub removeTargetGroupTarget { $cmd .= "del $tgt"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGRP_REM_TGT_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceGroupExists($group); + return SCST_C_DEV_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetGroupExists($group, $tgroup); + return SCST_C_DGRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetGroupTargetExists($group, $tgroup, $tgt); + return SCST_C_TGRP_NO_TGT if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_TGRP_REM_TGT_FAIL; } @@ -1924,6 +2000,39 @@ sub addInitiator { my $group = shift; my $initiator = shift; + return SCST_C_GRP_ADD_INI_FAIL + if (!defined($driver) || !defined($target) || + !defined($group) || !defined($initiator)); + + my ($path, $cmd); + if (new_sysfs_interface()) { + $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); + $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, + SCST_GROUPS, $group, SCST_INITIATORS) . + " "; + } else { + $path = make_path(SCST_TARGETS_DIR(), $driver, $target, + SCST_GROUPS, $group, SCST_INITIATORS, + SCST_MGMT_IO); + } + $cmd .= "add $initiator"; + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + + return SCST_C_GRP_REM_INI_FAIL if (!defined($driver) || + !defined($target) || + !defined($initiator)); + my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -1940,6 +2049,18 @@ sub addInitiator { return SCST_C_GRP_INI_EXISTS if ($rc == TRUE); return $rc if ($rc > 1); + return SCST_C_GRP_ADD_INI_FAIL; +} + +sub removeInitiator { + my $self = shift; + my $driver = shift; + my $target = shift; + my $group = shift; + my $initiator = shift; + + return SCST_C_GRP_REM_INI_FAIL if (!defined($driver) || !defined($target) || !defined($group) || !defined($initiator)); + my ($path, $cmd); if (new_sysfs_interface()) { $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); @@ -1951,33 +2072,20 @@ sub addInitiator { SCST_GROUPS, $group, SCST_INITIATORS, SCST_MGMT_IO); } - $cmd .= "add $initiator"; + $cmd .= "del $initiator"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_ADD_INI_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_GRP_ADD_INI_FAIL; -} - -sub removeInitiator { - my $self = shift; - my $driver = shift; - my $target = shift; - my $group = shift; - my $initiator = shift; - my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -1994,34 +2102,6 @@ sub removeInitiator { return SCST_C_GRP_NO_INI if (!$rc); return $rc if ($rc > 1); - my ($path, $cmd); - if (new_sysfs_interface()) { - $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); - $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, - SCST_GROUPS, $group, SCST_INITIATORS) . - " "; - } else { - $path = make_path(SCST_TARGETS_DIR(), $driver, $target, - SCST_GROUPS, $group, SCST_INITIATORS, - SCST_MGMT_IO); - } - $cmd .= "del $initiator"; - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_REM_INI_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_GRP_REM_INI_FAIL; } @@ -2033,6 +2113,31 @@ sub moveInitiator { my $to = shift; my $initiator = shift; + my ($path, $cmd); + if (new_sysfs_interface()) { + $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); + $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, + SCST_GROUPS, $from, SCST_INITIATORS) . + " "; + } else { + $path = make_path(SCST_TARGETS_DIR(), $driver, $target, + SCST_GROUPS, $from, SCST_INITIATORS, + SCST_MGMT_IO); + } + $cmd .= "move $initiator $to"; + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -2057,34 +2162,6 @@ sub moveInitiator { return SCST_C_GRP_INI_EXISTS if ($rc == TRUE); return $rc if ($rc > 1); - my ($path, $cmd); - if (new_sysfs_interface()) { - $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); - $cmd = "in " . make_path(IN_SCST_TARGETS, $driver, $target, - SCST_GROUPS, $from, SCST_INITIATORS) . - " "; - } else { - $path = make_path(SCST_TARGETS_DIR(), $driver, $target, - SCST_GROUPS, $from, SCST_INITIATORS, - SCST_MGMT_IO); - } - $cmd .= "move $initiator $to"; - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_MOV_INI_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_GRP_MOV_INI_FAIL; } @@ -2094,18 +2171,6 @@ sub clearInitiators { my $target = shift; my $group = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - my ($path, $cmd); if (new_sysfs_interface()) { $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); @@ -2120,20 +2185,29 @@ sub clearInitiators { $cmd .= "clear"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_CLR_INI_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_GRP_CLR_INI_FAIL; } @@ -2146,45 +2220,14 @@ sub addLun { my $attributes = shift; my $group = shift; - my $err; - my $err2; + my $err = defined($group) ? SCST_C_GRP_ADD_LUN_FAIL : + SCST_C_TGT_ADD_LUN_FAIL; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); + return $err if (!defined($driver) || !defined($target) || + !defined($device) || !defined($lun) || + !defined($attributes)); - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->deviceOpen($device); - return SCST_C_DEV_NO_DEVICE if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->checkLunCreateAttributes($driver, $target, $attributes, $group); - return SCST_C_LUN_BAD_ATTRIBUTES if ($rc == TRUE); - return $rc if ($rc > 1); - - if (defined($group)) { - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $err = SCST_C_GRP_ADD_LUN_FAIL; - $err2 = SCST_C_GRP_LUN_EXISTS; - - } else { - $err = SCST_C_TGT_ADD_LUN_FAIL; - $err2 = SCST_C_TGT_LUN_EXISTS; - } - - return $err if (!defined($lun)); - - $rc = $self->lunExists($driver, $target, $lun, $group); - return $err2 if ($rc == TRUE); - return $rc if ($rc > 1); - - my $o_string; + my $o_string = ""; foreach my $attribute (keys %{$attributes}) { my $value = $$attributes{$attribute}; $o_string .= "$attribute=$value; "; @@ -2217,20 +2260,44 @@ sub addLun { $cmd .= "add $device $lun $o_string"; my $io = new IO::File $path, O_WRONLY; - - return $err if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + if (defined($group)) { + my $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + + my $rc = $self->lunExists($driver, $target, $lun, $group); + return (defined($group) ? SCST_C_GRP_LUN_EXISTS : + SCST_C_TGT_LUN_EXISTS) if ($rc == TRUE); + return $rc if ($rc > 1); + + $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->deviceOpen($device); + return SCST_C_DEV_NO_DEVICE if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->checkLunCreateAttributes($driver, $target, $attributes, $group); + return SCST_C_LUN_BAD_ATTRIBUTES if ($rc == TRUE); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return $err; } @@ -2241,34 +2308,11 @@ sub removeLun { my $lun = shift; my $group = shift; - my $err; - my $err2; + my $err = defined($group) ? SCST_C_GRP_REM_LUN_FAIL : + SCST_C_TGT_ADD_LUN_FAIL; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - if (defined($group)) { - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $err = SCST_C_GRP_REM_LUN_FAIL; - $err2 = SCST_C_GRP_NO_LUN; - } else { - $err = SCST_C_TGT_ADD_LUN_FAIL; - $err2 = SCST_C_TGT_NO_LUN; - } - - return $err if (!defined($lun)); - - $rc = $self->lunExists($driver, $target, $lun, $group); - return $err2 if (!$rc); - return $rc if ($rc > 1); + return $err if (!defined($driver) || !defined($target) || + !defined($lun)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -2294,20 +2338,36 @@ sub removeLun { $cmd .= "del $lun"; my $io = new IO::File $path, O_WRONLY; - - return $err if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + if (defined($group)) { + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + + $rc = $self->lunExists($driver, $target, $lun, $group); + return (defined($group) ? SCST_C_GRP_NO_LUN : SCST_C_TGT_NO_LUN) + if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); return $err; } @@ -2354,11 +2414,11 @@ sub replaceLun { return SCST_C_LUN_BAD_ATTRIBUTES if ($rc == TRUE); return $rc if ($rc > 1); - my $luns = $self->luns($driver, $target, $group); + my ($luns, $errorString) = $self->luns($driver, $target, $group); return SCST_C_LUN_DEV_EXISTS if ($$luns{$lun} eq $device); - my $o_string; + my $o_string = ""; foreach my $attribute (keys %{$attributes}) { my $value = $$attributes{$attribute}; $o_string .= "$attribute=$value; "; @@ -2390,20 +2450,17 @@ sub replaceLun { $cmd .= "replace $device $lun $o_string"; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_LUN_RPL_DEV_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_LUN_RPL_DEV_FAIL; } @@ -2413,25 +2470,10 @@ sub clearLuns { my $target = shift; my $group = shift; - my $err; + my $err = defined($group) ? SCST_C_GRP_CLR_LUN_FAIL : + SCST_C_TGT_CLR_LUN_FAIL; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - if (defined($group)) { - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - - $err = SCST_C_GRP_CLR_LUN_FAIL; - } else { - $err = SCST_C_TGT_CLR_LUN_FAIL - } + return $err if (!defined($driver) || !defined($target)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -2457,21 +2499,32 @@ sub clearLuns { $cmd .= "clear"; my $io = new IO::File $path, O_WRONLY; - - return $err if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_GRP_CLR_LUN_FAIL; + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + if (defined($group)) { + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + + return $err; } sub deviceHandler { @@ -2493,8 +2546,7 @@ sub devices { my $_path = new_sysfs_interface() || !defined($handler) ? SCST_DEVICES_DIR() : make_path(SCST_HANDLERS_DIR(), $handler); if (!(opendir $dHandle, $_path)) { - $self->{'err_string'} = "devices(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "devices(): Unable to read directory '$_path': $!"); } foreach my $device (readdir($dHandle)) { @@ -2510,7 +2562,7 @@ sub devices { close $dHandle; - return \@devices; + return (\@devices, undef); } sub deviceOpen { @@ -2519,7 +2571,7 @@ sub deviceOpen { return FALSE if (!defined($device)); - my $devices = $self->devices(); + my ($devices, $errorString) = $self->devices(); return SCST_C_FATAL_ERROR if (!defined($devices)); @@ -2535,19 +2587,19 @@ sub deviceAttributes { my $device = shift; my %attributes; - if ($self->deviceOpen($device) != TRUE) { - $self->{'err_string'} = "deviceAttributes(): Device '$device' is not open"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_DEVICES_DIR(), $device); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "deviceAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceOpen($device) != TRUE) { + $errorString = "deviceAttributes(): Device '$device' is not open"; + } else { + $errorString = "deviceAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } - my $dca = $self->deviceCreateAttributes($self->deviceHandler($device)); + my ($dca, $errorString) = $self->deviceCreateAttributes($self->deviceHandler($device)); foreach my $attribute (readdir($pHandle)) { next if ($attribute eq '.' || $attribute eq '..' || @@ -2579,6 +2631,7 @@ sub deviceAttributes { $attributes{$attribute}->{'static'} = TRUE; } + close $eHandle; } elsif ($attribute eq 'handler') { my $linked = readlink $pPath; @@ -2610,24 +2663,23 @@ sub deviceAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "deviceAttributes(): Unable to read ". - "device attribute '$attribute': $!"; - return undef; + return (undef, "deviceAttributes(): Unable to read ". + "device attribute '$attribute': $!"); } my ($value, $is_key) = split("\n", _sysread($io) , 2); - + close $io; chomp $value; $is_key = new_sysfs_interface() && (!$is_static || defined($$dca{$attribute})) - || ($is_key =~ /\[key\]/) ? TRUE : FALSE; + || $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -2651,7 +2703,9 @@ sub deviceAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub driverAttributes { @@ -2659,16 +2713,16 @@ sub driverAttributes { my $driver = shift; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "driverAttributes(): Driver '$driver' is not available"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "driverAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "driverAttributes(): Driver '$driver' is not available"; + } else { + $errorString = "driverAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -2694,9 +2748,8 @@ sub driverAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "driverAttributes(): Unable to read ". - "driver attribute '$attribute': $!"; - return undef; + return (undef, "driverAttributes(): Unable to read ". + "driver attribute '$attribute': $!"); } my $value = <$io>; @@ -2704,13 +2757,13 @@ sub driverAttributes { my $is_key = <$io>; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -2743,13 +2796,16 @@ sub driverAttributes { $attributes{$attribute}->{'value'} = $value; } } + close $io; $attributes{$attribute}->{'static'} = $is_static; } } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub setDriverAttribute { @@ -2758,35 +2814,28 @@ sub setDriverAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - my $attributes = $self->driverAttributes($driver); - - return SCST_C_DRV_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_DRV_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my $path = make_path(SCST_TARGETS_DIR(), $driver, $attribute); my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DRV_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DRV_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_DRV_BAD_ATTRIBUTES, + SCST_C_DRV_ATTRIBUTE_STATIC); } sub targetAttributes { @@ -2795,21 +2844,20 @@ sub targetAttributes { my $target = shift; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "targetAttributes(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "targetAttributes(): Target '$target' is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver) || !defined($target)); my $pHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "targetAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "targetAttributes(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "targetAttributes(): Target '$target' is not available"; + } else { + $errorString = "targetAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -2829,8 +2877,7 @@ sub targetAttributes { my $_session_path = make_path($_path, $attribute); my $pSessHandle = new IO::Handle; if (!(opendir $pSessHandle, $_session_path)) { - $self->{'err_string'} = "targetAttributes(): Unable to read directory '$_session_path': $!"; - return undef; + return (undef, "targetAttributes(): Unable to read directory '$_session_path': $!"); } my $key = 0; foreach my $e (readdir($pSessHandle)) { @@ -2857,23 +2904,23 @@ sub targetAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "targetAttributes(): Unable to read ". - "target attribute '$attribute': $!"; - return undef; + return (undef, "targetAttributes(): Unable to read ". + "target attribute '$attribute': $!"); } my $value = <$io>; - chomp $value; + chomp $value if (defined($value)); my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -2890,7 +2937,9 @@ sub targetAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub setTargetAttribute { @@ -2900,21 +2949,8 @@ sub setTargetAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - my $attributes = $self->targetAttributes($driver, $target); - - return SCST_C_TGT_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_TGT_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my ($path, $cmd); if (new_sysfs_interface() && ($attribute eq 'enabled' || $attribute eq 'cpu_mask')) { @@ -2930,21 +2966,27 @@ sub setTargetAttribute { } my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGT_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $cmd > $path\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd > $path\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGT_SETATTR_FAIL; + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + return setAttrFailed($path, SCST_C_TGT_BAD_ATTRIBUTES, + SCST_C_TGT_ATTRIBUTE_STATIC); } sub groupAttributes { @@ -2954,27 +2996,21 @@ sub groupAttributes { my $group = shift; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "groupAttributes(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "groupAttributes(): Target '$target' is not available"; - return undef; - } - - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "groupAttributes(): Group '$group' does not exist"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "groupAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "groupAttributes(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "groupAttributes(): Target '$target' is not available"; + } elsif ($self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "groupAttributes(): Group '$group' does not exist"; + } else { + $errorString = "groupAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3002,23 +3038,23 @@ sub groupAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "groupAttributes(): Unable to read ". - "group attribute '$attribute': $!"; - return undef; + return (undef, "groupAttributes(): Unable to read ". + "group attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3035,7 +3071,9 @@ sub groupAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub setGroupAttribute { @@ -3046,25 +3084,8 @@ sub setGroupAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - my $attributes = $self->groupAttributes($driver, $target, $group); - - return SCST_C_GRP_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_GRP_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my ($path, $cmd); if (new_sysfs_interface() && $attribute eq 'cpu_mask') { $path = make_path(SCST_ROOT_DIR(), SCST_MGMT_IO); @@ -3078,21 +3099,31 @@ sub setGroupAttribute { $cmd .= $value; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_GRP_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $cmd > $path\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd > $path\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_GRP_SETATTR_FAIL; + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + + return setAttrFailed($path, SCST_C_GRP_BAD_ATTRIBUTES, + SCST_C_GRP_ATTRIBUTE_STATIC); } sub lunAttributes { @@ -3101,45 +3132,36 @@ sub lunAttributes { my $target = shift; my $lun = shift; my $group = shift; + my $errorString; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "lunAttributes(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "lunAttributes(): Target '$target' is not available"; - return undef; - } - my ($_path, $luncrattr); if (defined($group)) { - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "lunAttributes(): Group '$group' does not exist"; - return undef; - } - $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_LUNS, $lun); - $luncrattr = $self->lunCreateAttributes($driver, $target, - $group); + ($luncrattr, $errorString) = + $self->lunCreateAttributes($driver, $target, $group); } else { $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_LUNS, $lun); - $luncrattr = $self->lunCreateAttributes($driver, $target); - } - - if ($self->lunExists($driver, $target, $lun, $group) != TRUE) { - $self->{'err_string'} = "lunAttributes(): LUN '$lun' does not exist"; - return undef; + ($luncrattr, $errorString) = $self->lunCreateAttributes($driver, $target); } my $pHandle = new IO::Handle; if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "lunAttributes(): Unable to read directory '$_path': $!"; - return undef; + if ($self->driverExists($driver) != TRUE) { + $errorString = "lunAttributes(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "lunAttributes(): Target '$target' is not available"; + } elsif (defined($group) && $self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "lunAttributes(): Group '$group' does not exist"; + } elsif ($self->lunExists($driver, $target, $lun, $group) != TRUE) { + $errorString = "lunAttributes(): LUN '$lun' does not exist"; + } else { + $errorString = "lunAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3171,25 +3193,25 @@ sub lunAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "lunAttributes(): Unable to read ". - "lun attribute '$attribute': $!"; - return undef; + return (undef, "lunAttributes(): Unable to read ". + "lun attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && (!$is_static || defined($$luncrattr{$attribute})) || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3206,7 +3228,9 @@ sub lunAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub setLunAttribute { @@ -3218,21 +3242,13 @@ sub setLunAttribute { my $value = shift; my $group = shift; - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); + return SCST_C_LUN_SETATTR_FAIL + if (!defined($driver) || !defined($target) || !defined($lun) || + !defined($attribute) || !defined($value)); my $path; if (defined($group)) { - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - $path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_LUNS, $lun, $attribute); @@ -3241,32 +3257,42 @@ sub setLunAttribute { SCST_LUNS, $lun, $attribute); } - $rc = $self->lunExists($driver, $target, $lun, $group); - return SCST_C_GRP_NO_LUN if (!$rc); + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); - my $attributes = $self->lunAttributes($driver, $target, $group, $lun); + if (defined($group)) { + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + + $rc = $self->lunExists($driver, $target, $lun, $group); + return (defined($group) ? SCST_C_GRP_NO_LUN : SCST_C_TGT_NO_LUN) + if (!$rc); + return $rc if ($rc > 1); + + my ($attributes, $errorString) = $self->lunAttributes($driver, $target, $lun, $group); return SCST_C_LUN_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); return SCST_C_LUN_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_LUN_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_LUN_SETATTR_FAIL; } @@ -3278,32 +3304,23 @@ sub initiatorAttributes { my $initiator = shift; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "initiatorAttributes(): Driver '$driver' is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "initiatorAttributes(): Target '$target' is not available"; - return undef; - } - - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "initiatorAttributes(): Group '$group' does not exist"; - return undef; - } - - if ($self->initiatorExists($driver, $target, $group, $initiator) != TRUE) { - $self->{'err_string'} = "initiatorAttributes(): Initiator '$initiator' does not exist"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_INITIATORS, $initiator); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "initiatorAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "initiatorAttributes(): Driver '$driver' is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "initiatorAttributes(): Target '$target' is not available"; + } elsif ($self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "initiatorAttributes(): Group '$group' does not exist"; + } elsif ($self->initiatorExists($driver, $target, $group, $initiator) != TRUE) { + $errorString = "initiatorAttributes(): Initiator '$initiator' does not exist"; + } else { + $errorString = "initiatorAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3330,23 +3347,23 @@ sub initiatorAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "initiatorAttributes(): Unable to read ". - "initiator attribute '$attribute': $!"; - return undef; + return (undef, "initiatorAttributes(): Unable to read ". + "initiator attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3363,7 +3380,9 @@ sub initiatorAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub setInitiatorAttribute { @@ -3375,6 +3394,23 @@ sub setInitiatorAttribute { my $attribute = shift; my $value = shift; + return TRUE if (!defined($attribute) || !defined($value)); + + my $path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, + $group, SCST_LUNS, $initiator, $attribute); + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->driverExists($driver); return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); @@ -3391,31 +3427,6 @@ sub setInitiatorAttribute { return SCST_C_GRP_NO_INI if (!$rc); return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - - my $attributes = $self->initiatorAttributes($driver, $target, $group, $initiator); - - return SCST_C_INI_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_INI_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - - my $path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, - $group, SCST_LUNS, $initiator, $attribute); - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_INI_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_INI_SETATTR_FAIL; } @@ -3424,16 +3435,16 @@ sub deviceGroupAttributes { my $group = shift; my %attributes; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupAttributes(): Device group '$group' does not exist"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "deviceGroupAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "deviceGroupAttributes(): Device group '$group' does not exist"; + } else { + $errorString = "deviceGroupAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3458,23 +3469,23 @@ sub deviceGroupAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "deviceGroupAttributes(): Unable to read ". - "device group attribute '$attribute': $!"; - return undef; + return (undef, "deviceGroupAttributes(): Unable to read ". + "device group attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3491,7 +3502,9 @@ sub deviceGroupAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub targetGroupAttributes { @@ -3500,21 +3513,18 @@ sub targetGroupAttributes { my $tgroup = shift; my %attributes; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupAttributes(): Device group '$group' does not exist"; - return undef; - } - - if ($self->targetGroupExists($group, $tgroup) != TRUE) { - $self->{'err_string'} = "targetGroupAttributes(): Target Group '$tgroup' does not exist"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, $tgroup); if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "targetGroupAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "targetGroupAttributes(): Device group '$group' does not exist"; + } elsif ($self->targetGroupExists($group, $tgroup) != TRUE) { + $errorString = "targetGroupAttributes(): Target Group '$tgroup' does not exist"; + } else { + $errorString = "targetGroupAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3539,23 +3549,23 @@ sub targetGroupAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "targetGroupAttributes(): Unable to read ". - "target group attribute '$attribute': $!"; - return undef; + return (undef, "targetGroupAttributes(): Unable to read ". + "target group attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3572,7 +3582,9 @@ sub targetGroupAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); } sub targetGroupTargetAttributes { @@ -3580,28 +3592,27 @@ sub targetGroupTargetAttributes { my $group = shift; my $tgroup = shift; my $tgt = shift; + my $local_tgt = shift; my %attributes; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupTargetAttributes(): Device group '$group' does not exist"; - return undef; - } - - if ($self->targetGroupExists($group, $tgroup) != TRUE) { - $self->{'err_string'} = "targetGroupTargetAttributes(): Target Group '$tgroup' does not exist"; - return undef; - } - - if ($self->targetGroupTargetExists($group, $tgroup, $tgt) != TRUE) { - $self->{'err_string'} = "targetGroupTargetAttributes(): Target '$tgt' does not exist"; - return undef; - } - my $pHandle = new IO::Handle; my $_path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, $tgroup, $tgt); + if (-l $_path && !$local_tgt) { + return (\%attributes, undef); + } + if (!(opendir $pHandle, $_path)) { - $self->{'err_string'} = "targetGroupTargetAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->deviceGroupExists($group) != TRUE) { + $errorString = "targetGroupTargetAttributes(): Device group '$group' does not exist"; + } elsif ($self->targetGroupExists($group, $tgroup) != TRUE) { + $errorString = "targetGroupTargetAttributes(): Target Group '$tgroup' does not exist"; + } elsif ($self->targetGroupTargetExists($group, $tgroup, $tgt) != TRUE) { + $errorString = "targetGroupTargetAttributes(): Target '$tgt' does not exist"; + } else { + $errorString = "targetGroupTargetAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($pHandle)) { @@ -3627,23 +3638,23 @@ sub targetGroupTargetAttributes { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "targetGroupTargetAttributes(): Unable to read ". - "target group target attribute '$attribute': $!"; - return undef; + return (undef, "targetGroupTargetAttributes(): Unable to read ". + "target group target attribute '$attribute': $!"); } my $value = <$io>; chomp $value; my $is_key = <$io>; + close $io; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3660,7 +3671,33 @@ sub targetGroupTargetAttributes { } } - return \%attributes; + close $pHandle; + + return (\%attributes, undef); +} + +sub setAluaAttribute { + my $self = shift; + my $attribute = shift; + my $value = shift; + + return TRUE if (!defined($attribute) || !defined($value)); + + my $path = make_path(SCST_DEV_GROUP_DIR(), $attribute); + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $value > $path\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + + return setAttrFailed($path, SCST_C_ALUA_BAD_ATTRIBUTES, + SCST_C_ALUA_ATTRIBUTE_STATIC); } sub setDeviceGroupAttribute { @@ -3669,35 +3706,28 @@ sub setDeviceGroupAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->deviceGroupExists($group); - return SCST_C_DEV_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - my $attributes = $self->deviceGroupAttributes($group); - - return SCST_C_DGRP_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_DGRP_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my $path = make_path(SCST_DEV_GROUP_DIR(), $group, $attribute); my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DGRP_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceGroupExists($group); + return SCST_C_DEV_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DGRP_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_DGRP_BAD_ATTRIBUTES, + SCST_C_DGRP_ATTRIBUTE_STATIC); } sub setTargetGroupAttribute { @@ -3707,6 +3737,23 @@ sub setTargetGroupAttribute { my $attribute = shift; my $value = shift; + return TRUE if (!defined($group) || !defined($tgroup) || + !defined($attribute) || !defined($value)); + + my $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, $tgroup, $attribute); + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->deviceGroupExists($group); return SCST_C_DEV_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); @@ -3715,31 +3762,8 @@ sub setTargetGroupAttribute { return SCST_C_DGRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - - my $attributes = $self->targetGroupAttributes($group, $tgroup); - - return SCST_C_TGRP_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_TGRP_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - - my $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, $tgroup, $attribute); - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGRP_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGRP_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_TGRP_BAD_ATTRIBUTES, + SCST_C_TGRP_ATTRIBUTE_STATIC); } sub setTargetGroupTargetAttribute { @@ -3750,6 +3774,25 @@ sub setTargetGroupTargetAttribute { my $attribute = shift; my $value = shift; + return TRUE if (!defined($group) || !defined($tgroup) || + !defined($tgt) || !defined($attribute) || + !defined($value)); + + my $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, + $tgroup, $tgt, $attribute); + + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->deviceGroupExists($group); return SCST_C_DEV_GRP_NO_GROUP if (!$rc); return $rc if ($rc > 1); @@ -3762,32 +3805,8 @@ sub setTargetGroupTargetAttribute { return SCST_C_TGRP_NO_TGT if (!$rc); return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - - my $attributes = $self->targetGroupTargetAttributes($group, $tgroup, $tgt); - - return SCST_C_TGRP_TGT_BAD_ATTR if (!defined($$attributes{$attribute})); - return SCST_C_TGRP_TGT_ATTR_STATIC if ($$attributes{$attribute}->{'static'}); - - my $path = make_path(SCST_DEV_GROUP_DIR(), $group, SCST_DG_TGROUPS, - $tgroup, $tgt, $attribute); - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_TGRP_TGT_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_TGRP_TGT_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_TGRP_TGT_BAD_ATTR, + SCST_C_TGRP_TGT_ATTR_STATIC); } sub handlers { @@ -3797,8 +3816,7 @@ sub handlers { my $hHandle = new IO::Handle; my $_path = SCST_HANDLERS_DIR(); if (!(opendir $hHandle, $_path)) { - $self->{'err_string'} = "handlers(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "handlers(): Unable to read directory '$_path': $!"); } foreach my $handler (readdir($hHandle)) { @@ -3811,7 +3829,7 @@ sub handlers { close $hHandle; - return \@handlers; + return (\@handlers, undef); } sub handlerExists { @@ -3820,7 +3838,7 @@ sub handlerExists { return FALSE if (!defined($handler)); - my $handlers = $self->handlers(); + my ($handlers, $errorString) = $self->handlers(); return SCST_C_FATAL_ERROR if (!defined($handlers)); @@ -3837,35 +3855,27 @@ sub setHandlerAttribute { my $attribute = shift; my $value = shift; + return TRUE if (!defined($attribute) || !defined($value)); + + my $path = make_path(SCST_HANDLERS_DIR(), $handler, $attribute); + my $io = new IO::File $path, O_WRONLY; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $path -> $attribute = $value\n"; + } else { + $bytes = _syswrite($io, $value, length($value)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); + } + my $rc = $self->handlerExists($handler); return SCST_C_HND_NO_HANDLER if (!$rc); return $rc if ($rc > 1); - return TRUE if (!defined($attribute) || !defined($value)); - - my $attributes = $self->handlerAttributes($handler); - - return SCST_C_HND_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_HND_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - - my $path = make_path(SCST_HANDLERS_DIR(), $handler, $attribute); - - my $io = new IO::File $path, O_WRONLY; - - return SCST_C_HND_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $path -> $attribute = $value\n"; - } else { - $bytes = _syswrite($io, $value, length($value)); - } - - close $io; - - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_HND_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_HND_BAD_ATTRIBUTES, + SCST_C_HND_ATTRIBUTE_STATIC); } sub handlerAttributes { @@ -3873,18 +3883,19 @@ sub handlerAttributes { my $handler = shift; my %attributes; - if ($self->handlerExists($handler) != TRUE) { - $self->{'err_string'} = "handlerAttributes(): Handler '$handler' is not available"; - return undef; - } - - $attributes{'devices'}->{'value'} = devices($self, $handler); + my ($a, $errorString) = devices($self, $handler); + $attributes{'devices'}->{'value'} = $a; my $hHandle = new IO::Handle; my $_path = make_path(SCST_HANDLERS_DIR(), $handler); if (!(opendir $hHandle, $_path)) { - $self->{'err_string'} = "handlerAttributes(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->handlerExists($handler) != TRUE) { + $errorString = "handlerAttributes(): Handler '$handler' is not available"; + } else { + $errorString = "handlerAttributes(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $attribute (readdir($hHandle)) { @@ -3906,23 +3917,22 @@ sub handlerAttributes { my $io = new IO::File $path, O_RDONLY; if (!$io) { - $self->{'err_string'} = "handlerAttributes(): Unable to read handler attribute ". - "'$attribute': $!"; - return undef; + return (undef, "handlerAttributes(): Unable to read handler attribute ". + "'$attribute': $!"); } my $value = <$io>; - chomp $value; + chomp $value if (defined($value)); my $is_key = <$io>; $is_key = new_sysfs_interface() && !$is_static || - ($is_key =~ /\[key\]/) ? TRUE : FALSE; + $is_key && $is_key =~ /\[key\]/; my $key = 0; if ($is_key) { - if ($attribute =~ /.*(\d+)$/) { - $key = $1; - $attribute =~ s/\d+$//; + if ($attribute =~ /^([^\d]+)(\d+)$/) { + $attribute = $1; + $key = $2; } } @@ -3969,16 +3979,18 @@ sub handlerAttributes { close $io; } + close $hHandle; + $attributes{'devices'}->{'static'} = TRUE; - return \%attributes; + return (\%attributes, undef); } sub deviceExists { my $self = shift; my $device = shift; - my $handlers = $self->handlers(); + my ($handlers, $errorString) = $self->handlers(); return SCST_C_FATAL_ERROR if (!defined($handlers)); @@ -3994,14 +4006,15 @@ sub handlerDeviceExists { my $handler = shift; my $device = shift; - my $rc = $self->handlerExists($handler); + my ($devices, $errorString) = $self->devicesByHandler($handler); - return FALSE if (!$rc); - return $rc if ($rc > 1); + if (!defined($devices)) { + my $rc = $self->handlerExists($handler); + return FALSE if (!$rc); + return $rc if ($rc > 1); - my $devices = $self->devicesByHandler($handler); - - return SCST_C_FATAL_ERROR if (!defined($devices)); + return SCST_C_FATAL_ERROR; + } foreach my $_device (@{$devices}) { return TRUE if ($_device eq $device); @@ -4014,15 +4027,19 @@ sub devicesByHandler { my $self = shift; my $handler = shift; - if ($self->handlerExists($handler) != TRUE) { - $self->{'err_string'} = "devicesByHandler(): Handler '$handler' is not available"; - return undef; + my ($attributes, $errorString) = $self->handlerAttributes($handler); + + if (!defined($attributes)) { + my $errorString; + if ($self->handlerExists($handler) != TRUE) { + $errorString = "devicesByHandler(): Handler '$handler' is not available"; + } else { + $errorString = "devicesByHandler() failed"; + } + return (undef, $errorString); } - my $attributes = $self->handlerAttributes($handler); - - return undef if (!defined($attributes)); - return \@{$$attributes{'devices'}->{'value'}}; + return (\@{$$attributes{'devices'}->{'value'}}, undef); } sub checkDeviceCreateAttributes { @@ -4032,13 +4049,14 @@ sub checkDeviceCreateAttributes { return FALSE if (!defined($check)); - my $rc = $self->handlerExists($handler); - return SCST_C_HND_NO_HANDLER if (!$rc); - return $rc if (!$rc > 1); + my ($available, $errorString) = $self->deviceCreateAttributes($handler); - my $available = $self->deviceCreateAttributes($handler); - - return SCST_C_FATAL_ERROR if (!defined($available)); + if (!defined($available)) { + my $rc = $self->handlerExists($handler); + return SCST_C_HND_NO_HANDLER if (!$rc); + return $rc if (!$rc > 1); + return SCST_C_FATAL_ERROR; + } if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { @@ -4061,12 +4079,6 @@ sub deviceCreateAttributes { my $available; my %attributes; - if ($self->handlerExists($handler) != TRUE) { - $self->{'err_string'} = "deviceCreateAttributes(): Handler '$handler' ". - "is not available"; - return undef; - } - if (new_sysfs_interface()) { my $io = new IO::File make_path(SCST_HANDLERS_DIR(), $handler, SCST_ADD_DEV_PARAMS), O_RDONLY; @@ -4075,14 +4087,21 @@ sub deviceCreateAttributes { chomp($attribute); $attributes{$attribute} = ''; } + close $io; } else { my $io = new IO::File make_path(SCST_HANDLERS_DIR(), $handler, SCST_MGMT_IO), O_RDONLY; if (!$io) { - $self->{'err_string'} = "deviceCreateAttributes(): Unable to open mgmt ". - "interface for handler '$handler': $!"; - return undef; + my $errorString; + if ($self->handlerExists($handler) != TRUE) { + $errorString = "deviceCreateAttributes(): Handler '$handler' ". + "is not available"; + } else { + $errorString = "deviceCreateAttributes(): Unable to open mgmt ". + "interface for handler '$handler': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -4091,6 +4110,7 @@ sub deviceCreateAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -4101,7 +4121,7 @@ sub deviceCreateAttributes { } } - return \%attributes; + return (\%attributes, undef); } sub openDevice { @@ -4110,19 +4130,11 @@ sub openDevice { my $device = shift; my $attributes = shift; - my $rc = $self->handlerExists($handler); - return SCST_C_HND_NO_HANDLER if (!$rc); - return $rc if ($rc > 1); + return SCST_C_DEV_OPEN_FAIL if (!defined($handler) || + !defined($device) || + !defined($attributes)); - $rc = $self->checkDeviceCreateAttributes($handler, $attributes); - return SCST_C_DEV_BAD_ATTRIBUTES if ($rc == TRUE); - return $rc if ($rc > 1); - - $rc = $self->handlerDeviceExists($handler, $device); - return SCST_C_DEV_EXISTS if ($rc == TRUE); - return $rc if ($rc > 1); - - my $o_string; + my $o_string = ""; foreach my $attribute (keys %{$attributes}) { my $value = $$attributes{$attribute}; $o_string .= "$attribute=$value; "; @@ -4140,23 +4152,34 @@ sub openDevice { $cmd .= "add_device $device $o_string"; my $io = new IO::File $path, O_WRONLY; - - if (!$io) { - $self->{'err_string'} = "openDevice(): Unable to open mgmt interface for ". - "handler '$handler': $!"; - return SCST_C_FATAL_ERROR; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - my $bytes; + my $errno = $!; - if ($self->{'debug'}) { - print "DBG($$): $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } + my $rc = $self->handlerExists($handler); + return SCST_C_HND_NO_HANDLER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DEV_OPEN_FAIL; + $rc = $self->checkDeviceCreateAttributes($handler, $attributes); + return SCST_C_DEV_BAD_ATTRIBUTES if ($rc == TRUE); + return $rc if ($rc > 1); + + $rc = $self->handlerDeviceExists($handler, $device); + return SCST_C_DEV_EXISTS if ($rc == TRUE); + return $rc if ($rc > 1); + + return SCST_C_DEV_OPEN_FAIL if ($errno == EINVAL); + + return SCST_C_FATAL_ERROR; } sub closeDevice { @@ -4164,13 +4187,8 @@ sub closeDevice { my $handler = shift; my $device = shift; - my $rc = $self->handlerExists($handler); - return SCST_C_HND_NO_HANDLER if (!$rc); - return $rc if ($rc > 1); - - $rc = $self->handlerDeviceExists($handler, $device); - return SCST_C_DEV_NO_DEVICE if ($rc != TRUE); - return $rc if ($rc > 1); + return SCST_C_DEV_CLOSE_FAIL if (!defined($handler) || + !defined($device)); my ($path, $cmd); if (new_sysfs_interface()) { @@ -4182,23 +4200,28 @@ sub closeDevice { $cmd .= "del_device $device"; my $io = new IO::File $path, O_WRONLY; - - if (!$io) { - $self->{'err_string'} = "closeDevice(): Unable to open mgmt interface for handler ". - "'$handler': $!"; - return SCST_C_FATAL_ERROR; + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - my $bytes; + my $errno = $!; - if ($self->{'debug'}) { - print "DBG($$): $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); - } + my $rc = $self->handlerExists($handler); + return SCST_C_HND_NO_HANDLER if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DEV_CLOSE_FAIL; + $rc = $self->handlerDeviceExists($handler, $device); + return SCST_C_DEV_NO_DEVICE if ($rc != TRUE); + return $rc if ($rc > 1); + + return SCST_C_FATAL_ERROR; } sub setDeviceAttribute { @@ -4207,17 +4230,6 @@ sub setDeviceAttribute { my $attribute = shift; my $value = shift; - my $rc = $self->deviceOpen($device); - return SCST_C_DEV_NO_DEVICE if (!$rc); - return $rc if ($rc > 1); - - my $attributes = $self->deviceAttributes($device); - - return SCST_C_FATAL_ERROR if (!defined($attributes)); - - return SCST_C_DEV_BAD_ATTRIBUTES if (!defined($$attributes{$attribute})); - return SCST_C_DEV_ATTRIBUTE_STATIC if ($$attributes{$attribute}->{'static'}); - my ($path, $cmd); if (new_sysfs_interface() && ($attribute eq 'filename' || @@ -4231,21 +4243,23 @@ sub setDeviceAttribute { $cmd .= $value; my $io = new IO::File $path, O_WRONLY; - - return SCST_C_DEV_SETATTR_FAIL if (!$io); - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $cmd > $path\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd > $path\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - close $io; + my $rc = $self->deviceOpen($device); + return SCST_C_DEV_NO_DEVICE if (!$rc); + return $rc if ($rc > 1); - return FALSE if ($self->{'debug'} || $bytes); - return SCST_C_DEV_SETATTR_FAIL; + return setAttrFailed($path, SCST_C_DEV_BAD_ATTRIBUTES, + SCST_C_DEV_ATTRIBUTE_STATIC); } sub checkTargetCreateAttributes { @@ -4255,13 +4269,14 @@ sub checkTargetCreateAttributes { return FALSE if (!defined($check)); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); + my ($available, $errorString) = $self->targetCreateAttributes($driver); - my $available = $self->targetCreateAttributes($driver); - - return SCST_C_FATAL_ERROR if (!defined($available)); + if (!defined($available)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); + return SCST_C_FATAL_ERROR; + } if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { @@ -4284,12 +4299,6 @@ sub targetCreateAttributes { my $available; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "targetCreateAttributes(): Driver '$driver' ". - "is not available"; - return undef; - } - if (new_sysfs_interface()) { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, SCST_ADD_TGT_PARAMS), O_RDONLY; @@ -4297,14 +4306,21 @@ sub targetCreateAttributes { chomp($attribute); $attributes{$attribute} = ''; } + close $io; } else { my $io = new IO::File make_path(SCST_TARGETS_DIR(), $driver, SCST_MGMT_IO), O_RDONLY; if (!$io) { - $self->{'err_string'} = "targetCreateAttributes(): Unable to open driver mgmt ". - "interface for driver '$driver': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "targetCreateAttributes(): Driver '$driver' ". + "is not available"; + } else { + $errorString = "targetCreateAttributes(): Unable to open driver mgmt ". + "interface for driver '$driver': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -4313,6 +4329,7 @@ sub targetCreateAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -4323,7 +4340,7 @@ sub targetCreateAttributes { } } - return \%attributes; + return (\%attributes, undef); } sub enableTarget { @@ -4356,7 +4373,7 @@ sub deviceGroupExists { my $self = shift; my $group = shift; - my $groups = $self->deviceGroups(); + my ($groups, $errorString) = $self->deviceGroups(); return SCST_C_FATAL_ERROR if (!defined($groups)); @@ -4372,15 +4389,12 @@ sub deviceGroupDeviceExists { my $group = shift; my $device = shift; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "deviceGroupDeviceExists(): Device group '$group' does not exist"; - return undef; + my ($devices, $errorString) = $self->deviceGroupDevices($group); + + if (!defined($devices)) { + return SCST_C_FATAL_ERROR; } - my $devices = $self->deviceGroupDevices($group); - - return SCST_C_FATAL_ERROR if (!defined($devices)); - foreach my $_device (@{$devices}) { return TRUE if ($device eq $_device); } @@ -4393,15 +4407,12 @@ sub targetGroupExists { my $group = shift; my $tgroup = shift; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupExists(): Device group '$group' does not exist"; - return undef; + my ($tgroups, $errorString) = $self->targetGroups($group); + + if (!defined($tgroups)) { + return SCST_C_FATAL_ERROR; } - my $tgroups = $self->targetGroups($group); - - return SCST_C_FATAL_ERROR if (!defined($tgroups)); - foreach my $_tgroup (@{$tgroups}) { return TRUE if ($tgroup eq $_tgroup); } @@ -4415,20 +4426,12 @@ sub targetGroupTargetExists { my $tgroup = shift; my $tgt = shift; - if ($self->deviceGroupExists($group) != TRUE) { - $self->{'err_string'} = "targetGroupTargetExists(): Device group '$group' does not exist"; - return undef; + my ($targets, $errorString) = $self->targetGroupTargets($group, $tgroup); + + if (!defined($targets)) { + return SCST_C_FATAL_ERROR; } - if ($self->targetGroupExists($group, $tgroup) != TRUE) { - $self->{'err_string'} = "targetGroupTargetExists(): Target group '$tgroup' does not exist"; - return undef; - } - - my $targets = $self->targetGroupTargets($group, $tgroup); - - return SCST_C_FATAL_ERROR if (!defined($targets)); - foreach my $_tgt (@{$targets}) { return TRUE if ($tgt eq $_tgt); } @@ -4445,24 +4448,26 @@ sub checkLunCreateAttributes { return FALSE if (!defined($check)); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); + my ($available, $errorString) = $self->lunCreateAttributes($driver, $target, $group); - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); - - if ($group) { - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); + if (!defined($available)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); return $rc if ($rc > 1); + + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); + + if ($group) { + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); + } + + return SCST_C_FATAL_ERROR; } - my $available = $self->lunCreateAttributes($driver, $target, $group); - - return SCST_C_FATAL_ERROR if (!defined($available)); - if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { if (!defined($$available{$attribute})) { @@ -4486,26 +4491,13 @@ sub lunCreateAttributes { my $available; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "lunCreateAttributes(): Driver '$driver' ". - "is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "lunCreateAttributes(): Target '$target' ". - "is not available"; - return undef; - } - my $_path; if (new_sysfs_interface()) { if (defined($group)) { if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "lunCreateAttributes(): Group '$group' ". - "does not exist"; - return undef; + return ("lunCreateAttributes(): Group '$group' ". + "does not exist"); } $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, @@ -4521,14 +4513,9 @@ sub lunCreateAttributes { chomp($attribute); $attributes{$attribute} = ''; } + close $io; } else { if (defined($group)) { - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "lunCreateAttributes(): Group '$group' ". - "does not exist"; - return undef; - } - $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_GROUPS, $group, SCST_LUNS, SCST_MGMT_IO); @@ -4540,9 +4527,21 @@ sub lunCreateAttributes { my $io = new IO::File $_path, O_RDONLY; if (!$io) { - $self->{'err_string'} = "lunCreateAttributes(): Unable to open luns mgmt ". - "interface for group '$group': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "lunCreateAttributes(): Driver '$driver' ". + "is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "lunCreateAttributes(): Target '$target' ". + "is not available"; + } elsif (defined($group) && $self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "lunCreateAttributes(): Group '$group' ". + "does not exist"; + } else { + $errorString = "lunCreateAttributes(): Unable to open luns mgmt ". + "interface for group '$group': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -4551,6 +4550,7 @@ sub lunCreateAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -4560,7 +4560,7 @@ sub lunCreateAttributes { } } } - return \%attributes; + return (\%attributes, undef); } sub checkInitiatorCreateAttributes { @@ -4572,21 +4572,23 @@ sub checkInitiatorCreateAttributes { return FALSE if (!defined($check)); - my $rc = $self->driverExists($driver); - return SCST_C_DRV_NO_DRIVER if (!$rc); - return $rc if ($rc > 1); + my ($available, $errorString) = $self->initiatorCreateAttributes($driver, $target, $group); - $rc = $self->targetExists($driver, $target); - return SCST_C_TGT_NO_TARGET if (!$rc); - return $rc if ($rc > 1); + if (!defined($available)) { + my $rc = $self->driverExists($driver); + return SCST_C_DRV_NO_DRIVER if (!$rc); + return $rc if ($rc > 1); - $rc = $self->groupExists($driver, $target, $group); - return SCST_C_GRP_NO_GROUP if (!$rc); - return $rc if ($rc > 1); + $rc = $self->targetExists($driver, $target); + return SCST_C_TGT_NO_TARGET if (!$rc); + return $rc if ($rc > 1); - my $available = $self->initiatorCreateAttributes($driver, $target, $group); + $rc = $self->groupExists($driver, $target, $group); + return SCST_C_GRP_NO_GROUP if (!$rc); + return $rc if ($rc > 1); - return SCST_C_FATAL_ERROR if (!defined($available)); + return SCST_C_FATAL_ERROR; + } if (ref($check) eq 'HASH') { foreach my $attribute (keys %{$check}) { @@ -4611,24 +4613,6 @@ sub initiatorCreateAttributes { my $available; my %attributes; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "initiatorCreateAttributes(): Driver '$driver' ". - "is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "initiatorCreateAttributes(): Target '$target' ". - "is not available"; - return undef; - } - - if ($self->groupExists($driver, $target, $group) != TRUE) { - $self->{'err_string'} = "initiatorCreateAttributes(): Group '$group' ". - "does not exist"; - return undef; - } - if (new_sysfs_interface()) { # Do nothing - there are no initiator attributes (yet). } else { @@ -4638,9 +4622,21 @@ sub initiatorCreateAttributes { O_RDONLY; if (!$io) { - $self->{'err_string'} = "initiatorCreateAttributes(): Unable to open initiators mgmt ". - "interface for group '$group': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "initiatorCreateAttributes(): Driver '$driver' ". + "is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "initiatorCreateAttributes(): Target '$target' ". + "is not available"; + } elsif ($self->groupExists($driver, $target, $group) != TRUE) { + $errorString = "initiatorCreateAttributes(): Group '$group' ". + "does not exist"; + } else { + $errorString = "initiatorCreateAttributes(): Unable to open initiators mgmt ". + "interface for group '$group': $!"; + } + return (undef, $errorString); } while (my $in = <$io>) { @@ -4649,6 +4645,7 @@ sub initiatorCreateAttributes { $available =~ s/\.$//; } } + close $io; if ($available) { foreach my $attribute (split(/\,/, $available)) { @@ -4659,7 +4656,7 @@ sub initiatorCreateAttributes { } } - return \%attributes; + return (\%attributes, undef); } sub sessions { @@ -4668,24 +4665,23 @@ sub sessions { my $target = shift; my %_sessions; - if ($self->driverExists($driver) != TRUE) { - $self->{'err_string'} = "sessions(): Driver '$driver' ". - "is not available"; - return undef; - } - - if ($self->targetExists($driver, $target) != TRUE) { - $self->{'err_string'} = "sessions(): Target '$target' ". - "is not available"; - return undef; - } + return (undef, "Too few arguments") if (!defined($driver) || !defined($target)); my $sHandle = new IO::Handle; my $_path = make_path(SCST_TARGETS_DIR(), $driver, $target, SCST_SESSIONS); if (!(opendir $sHandle, $_path)) { - $self->{'err_string'} = "sessions(): Unable to read directory '$_path': $!"; - return undef; + my $errorString; + if ($self->driverExists($driver) != TRUE) { + $errorString = "sessions(): Driver '$driver' ". + "is not available"; + } elsif ($self->targetExists($driver, $target) != TRUE) { + $errorString = "sessions(): Target '$target' ". + "is not available"; + } else { + $errorString = "sessions(): Unable to read directory '$_path': $!"; + } + return (undef, $errorString); } foreach my $session (readdir($sHandle)) { @@ -4693,8 +4689,7 @@ sub sessions { my $pHandle = new IO::Handle; my $sPath = make_path($_path, $session); if (!(opendir $pHandle, $sPath)) { - $self->{'err_string'} = "sessions(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "sessions(): Unable to read directory '$_path': $!"); } foreach my $attribute (readdir($pHandle)) { @@ -4730,12 +4725,13 @@ sub sessions { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "sessions(): Unable to read ". - "session attribute '$attribute': $!"; - return undef; + return (undef, + "sessions(): Unable to read ". + "session attribute '$attribute': $!"); } my $value = <$io>; + close $io; chomp $value; $_sessions{$session}->{$attribute}->{'value'} = $value; @@ -4744,9 +4740,11 @@ sub sessions { } } } + close $pHandle; } + close $sHandle; - return \%_sessions; + return (\%_sessions, undef); } sub closeSession { @@ -4755,7 +4753,7 @@ sub closeSession { my $target = shift; my $session = shift; - my $sessions = $self->sessions($driver, $target); + my ($sessions, $errorString) = $self->sessions($driver, $target); return SCST_C_NO_SESSION if (!defined($$sessions{$session})); @@ -4766,18 +4764,17 @@ sub closeSession { SCST_SESSIONS, $session, 'force_close'); my $io = new IO::File $path, O_WRONLY; - - my $cmd = "1"; - - my $bytes; - - if ($self->{'debug'}) { - print "DBG($$): $cmd\n"; - } else { - $bytes = _syswrite($io, $cmd, length($cmd)); + if ($io) { + my $cmd = "1"; + my $bytes; + if ($self->{'debug'}) { + print "DBG($$): $cmd\n"; + } else { + $bytes = _syswrite($io, $cmd, length($cmd)); + } + close $io; + return FALSE if ($self->{'debug'} || $bytes); } - - return FALSE if ($self->{'debug'} || $bytes); return SCST_C_SESSION_CLOSE_FAIL; } @@ -4788,8 +4785,7 @@ sub sgvStats { my $sHandle = new IO::Handle; my $_path = SCST_SGV_DIR(); if (!(opendir $sHandle, $_path)) { - $self->{'err_string'} = "svgStats(): Unable to read directory '$_path': $!"; - return undef; + return (undef, "svgStats(): Unable to read directory '$_path': $!"); } foreach my $stat (readdir($sHandle)) { @@ -4800,8 +4796,7 @@ sub sgvStats { if (-d $sPath) { my $lHandle = new IO::Handle; if (!(opendir $lHandle, $sPath)) { - $self->{'err_string'} = "svgStats(): Unable to read directory '$sPath': $!"; - return undef; + return (undef, "svgStats(): Unable to read directory '$sPath': $!"); } foreach my $lief (readdir($lHandle)) { @@ -4810,50 +4805,46 @@ sub sgvStats { my $io = new IO::File $pPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "sgvStats(): Unable to read ". - "sgv stat '$stat/$lief': $!"; - return undef; + return (undef, "sgvStats(): Unable to read ". + "sgv stat '$stat/$lief': $!"); } my $buffer; while (my $value = <$io>) { $buffer .= $value; } + close $io; $stats{$stat}->{$lief} = $buffer; } + close $lHandle; } else { my $io = new IO::File $sPath, O_RDONLY; if (!$io) { - $self->{'err_string'} = "sgvStats(): Unable to read ". - "sgv stat '$stat': $!"; - return undef; + return (undef, "sgvStats(): Unable to read ". + "sgv stat '$stat': $!"); } my $buffer; while (my $value = <$io>) { $buffer .= $value; } + close $io; $stats{$stat} = $buffer; } } + close $sHandle; - return \%stats; + return (\%stats, undef); } sub errorString { my $self = shift; my $rc = shift; - return $VERBOSE_ERROR{$rc} if (defined($rc)); - return undef if (!$self->{'err_string'}); - - my $string = $self->{'err_string'}; - $self->{'err_string'} = undef; - - return $string; + return defined($rc) ? $VERBOSE_ERROR{$rc} : undef; } # Read from the SCST sysfs file $1. Return either the data read or undef if diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/01-start-scst.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/01-start-scst.t new file mode 100644 index 000000000..cc857c0e7 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/01-start-scst.t @@ -0,0 +1,27 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => ($> == 0) ? 3 : 0; +} + +if ($> == 0) { + ok(system("killall iscsi-scstd >/dev/null 2>&1; " . + "modprobe -r scst_local; " . + "modprobe -r iscsi-scst; " . + "modprobe -r ib_srpt; " . + "modprobe -r qla2x00tgt; " . + "modprobe -r qla2xxx_scst; " . + "modprobe -r scst_vdisk"), 0); + + ok(!(-d "/sys/module/scst")); + + ok(system("modprobe scst_local add_default_tgt=0 && " . + "modprobe iscsi-scst && " . + "modprobe ib_srpt && " . + "modprobe qla2x00tgt && " . + "modprobe scst_vdisk && " . + "iscsi-scstd"), 0); +} diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/02-scst-attr.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/02-scst-attr.t new file mode 100644 index 000000000..267423138 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/02-scst-attr.t @@ -0,0 +1,46 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => 6 + ($> == 0 ? 4 : 0); +} + +use SCST::SCST; + +sub getScstThreadCount { + my $SCST = shift; + my ($scstAttributes, $errorString) = $SCST->scstAttributes(); + my $threadHash = $scstAttributes->{'threads'}; + return exists($threadHash->{'keys'}) ? $threadHash->{'keys'}->{'0'}->{'value'} : $threadHash->{'value'}; +} + +my $_DEBUG_ = 0; + +my $SCST = eval { new SCST::SCST($_DEBUG_) }; +die("Creation of SCST object failed") if (!defined($SCST)); + +ok($SCST->setScstAttribute(), 1); + +ok($SCST->setScstAttribute('no-such-attribute'), 1); + +ok($SCST->setScstAttribute('no-such-attribute', '1'), + $SCST->SCST_C_BAD_ATTRIBUTES); + +ok($SCST->setScstAttribute('last_sysfs_mgmt_res', '1'), + $SCST->SCST_C_ATTRIBUTE_STATIC); + +my $threads = getScstThreadCount($SCST); +ok(ref(\$threads), "SCALAR"); +ok(defined($threads)); + +if ($> == 0) { + ok($SCST->setScstAttribute('threads', $threads + 1), 0); + + ok(getScstThreadCount($SCST), $threads + 1); + + ok($SCST->setScstAttribute('threads', $threads), 0); + + ok(getScstThreadCount($SCST), $threads); +} diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/03-targets.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/03-targets.t new file mode 100644 index 000000000..28db54d06 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/03-targets.t @@ -0,0 +1,365 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => 177; +} + +use Data::Dumper; +use SCST::SCST; + +sub addTargets { + my $SCST = shift; + + ok(Dumper($SCST->targets('no-such-driver')), + Dumper(undef, "targets(): Driver 'no-such-driver' is not available")); + + my ($drivers, $errorString) = $SCST->drivers(); + my %drivers = map { $_ => 1 } @{$drivers}; + ok(exists($drivers{'iscsi'})); + ok(exists($drivers{'scst_local'})); + + my $all_hw_tgt = 1; + for my $driver (@{$drivers}) { + my ($targets, $errorString) = $SCST->targets($driver); + for my $target (@{$targets}) { + if ($SCST->targetType($driver, $target) != + $SCST::SCST::TGT_TYPE_HARDWARE) { + $all_hw_tgt = undef; + } + } + } + ok($all_hw_tgt); + + ok(Dumper($SCST->targets()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targets('no-such-driver')), + Dumper(undef, "targets(): Driver 'no-such-driver' is not available")); + ok(Dumper($SCST->targets('scst_local')), Dumper([], undef)); + ok(Dumper($SCST->targets('iscsi')), Dumper([], undef)); + + ok($SCST->addVirtualTarget('no-such-driver', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeVirtualTarget('no-such-driver', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->addVirtualTarget('scst_local', 'local1'), 0); + ok(Dumper($SCST->targetType()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targetType('scst_local')), + Dumper(undef, "Too few arguments")); + ok($SCST->targetType('scst_local', 'no-such-target'), + $SCST::SCST::TGT_TYPE_VIRTUAL); + ok($SCST->targetType('scst_local', 'local1'), + $SCST::SCST::TGT_TYPE_VIRTUAL); + ok(Dumper($SCST->targets('scst_local')), Dumper(['local1'], undef)); + ok($SCST->removeVirtualTarget('scst_local', 'local2'), + $SCST->SCST_C_TGT_NO_TARGET); + ok(Dumper($SCST->targets('scst_local')), Dumper(['local1'], undef)); + ok($SCST->removeVirtualTarget('scst_local', 'local1'), 0); + ok(Dumper($SCST->targets('scst_local')), Dumper([], undef)); + ok($SCST->addVirtualTarget('scst_local', 'local1', + { 'session_name' => 'local1' }), 0); + ok($SCST->addVirtualTarget('scst_local', 'local2', + { 'session_name' => 'local2' }), 0); + ok(Dumper($SCST->targets('scst_local')), + Dumper(['local1', 'local2'], undef)); + + ok($SCST->targetExists(), 0); + ok($SCST->targetExists('no-such-driver'), 0); + ok($SCST->targetExists('no-such-driver', ''), 0); + ok($SCST->targetExists('scst_local', 'no-such-target'), 0); + ok($SCST->targetExists('scst_local', '.'), 0); + ok($SCST->targetExists('scst_local', '..'), 0); + ok($SCST->targetExists('scst_local', 'module'), 0); + ok($SCST->targetExists('scst_local', 'local1'), 1); +} + +sub sessTest { + my $SCST = shift; + + ok(Dumper($SCST->sessions()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->sessions('scst_local')), + Dumper(undef, "Too few arguments")); + my ($s, $errorString) = $SCST->sessions('scst_local', 'local1'); + ok(Dumper(sort(keys(%$s))), Dumper('local1')); + ok($s->{'local1'}->{'commands'}->{'value'}, '0'); +} + +sub driverDynamicAttributesTest { + my $SCST = shift; + + ok(Dumper($SCST->driverDynamicAttributes()), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->driverDynamicAttributes('no-such-driver')), + Dumper(undef, "driverDynamicAttributes(): Driver 'no-such-driver' is " . + "not available")); + ok(Dumper($SCST->driverDynamicAttributes('scst_local')), + Dumper({}, undef)); +} + +sub iniGrpTest { + my $SCST = shift; + + ok(Dumper($SCST->groups()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->groups('scst_local')), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->groups('scst_local', 'local1')), Dumper([], undef)); + + ok($SCST->addGroup(), $SCST->SCST_C_GRP_ADD_FAIL); + ok($SCST->addGroup('no-such-driver', 'local1', 'group1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->addGroup('scst_local', 'no-such-target', 'group1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->addGroup('scst_local', 'local1', 'group1'), 0); + ok($SCST->addGroup('scst_local', 'local1', 'group1'), + $SCST->SCST_C_GRP_EXISTS); + ok($SCST->addGroup('scst_local', 'local1', 'group2'), 0); + ok($SCST->addGroup('scst_local', 'local1', 'group3'), 0); + ok(Dumper($SCST->groups('scst_local', 'local1')), + Dumper(['group1', 'group2', 'group3'], undef)); + + ok($SCST->groupExists(), 0); + ok($SCST->groupExists('no-such-driver', '', ''), 0); + ok($SCST->groupExists('scst_local', 'no-such-target', ''), 0); + ok($SCST->groupExists('scst_local', 'local1', 'no-such-group'), 0); + ok($SCST->groupExists('scst_local', 'local1', 'group1'), 1); + + ok($SCST->removeGroup(), $SCST->SCST_C_GRP_REM_FAIL); + ok($SCST->removeGroup('no-such-driver', 'local1', 'group1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeGroup('scst_local', 'no-such-target', 'group1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->removeGroup('scst_local', 'local1', 'group1'), 0); + ok($SCST->removeGroup('scst_local', 'local1', 'group1'), + $SCST->SCST_C_GRP_NO_GROUP); + ok($SCST->removeGroup('scst_local', 'local1', 'group2'), 0); + ok($SCST->removeGroup('scst_local', 'local1', 'group3'), 0); + ok(Dumper($SCST->groups('scst_local', 'local1')), Dumper([], undef)); + + ok($SCST->addGroup('scst_local', 'local1', 'group1'), 0); + ok($SCST->addInitiator('scst_local', 'local1', 'group1'), + $SCST->SCST_C_GRP_ADD_INI_FAIL); + ok($SCST->addInitiator('no-such-driver', 'local1', 'group1', 'ini1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->addInitiator('scst_local', 'no-such-target', 'group1', 'ini1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->addInitiator('scst_local', 'local1', 'no-such-group', 'ini1'), + $SCST->SCST_C_GRP_NO_GROUP); + ok($SCST->addInitiator('scst_local', 'local1', 'group1', 'ini1'), 0); + ok($SCST->addInitiator('scst_local', 'local1', 'group1', 'ini2'), 0); + ok($SCST->addInitiator('scst_local', 'local1', 'group1', 'ini1'), + $SCST->SCST_C_GRP_INI_EXISTS); + ok(Dumper($SCST->initiators()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->initiators('scst_local')), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->initiators('scst_local', 'local1')), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->initiators('scst_local', 'local1', 'group1')), + Dumper(['ini1', 'ini2'], undef)); + + ok($SCST->initiatorExists(), 0); + ok($SCST->initiatorExists('no-such-driver', '', '', ''), 0); + ok($SCST->initiatorExists('scst_local', 'no-such-target', '', ''), 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'no-such-group', ''), 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'group1', 'no-such-ini'), + 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'group1', 'ini1'), 1); + + ok($SCST->addGroup('scst_local', 'local1', 'group2'), 0); + ok($SCST->moveInitiator('scst_local', 'local1', 'group1', 'group2', 'ini1'), + 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'group1', 'ini1'), 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'group2', 'ini1'), 1); + ok($SCST->moveInitiator('scst_local', 'local1', 'group2', 'group1', 'ini1'), + 0); + ok($SCST->initiatorExists('scst_local', 'local1', 'group1', 'ini1'), 1); + ok($SCST->initiatorExists('scst_local', 'local1', 'group2', 'ini1'), 0); + + ok($SCST->removeGroup('scst_local', 'local1', 'group2'), 0); + ok($SCST->removeInitiator('no-such-driver', 'local1', 'group1'), + $SCST->SCST_C_GRP_REM_INI_FAIL); + ok($SCST->removeInitiator('no-such-driver', 'local1', 'group1', 'ini1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeInitiator('scst_local', 'no-such-target', 'group1', 'ini1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->removeInitiator('scst_local', 'local1', 'no-such-group', 'ini1'), + $SCST->SCST_C_GRP_NO_GROUP); + ok($SCST->removeInitiator('scst_local', 'local1', 'group1', 'ini1'), 0); + ok($SCST->removeInitiator('scst_local', 'local1', 'group1', 'ini2'), 0); + ok($SCST->removeInitiator('scst_local', 'local1', 'group1', 'ini2'), + $SCST->SCST_C_GRP_NO_INI); + ok(Dumper($SCST->initiators('scst_local', 'local1', 'group1')), + Dumper([], undef)); + ok($SCST->removeGroup('scst_local', 'local1', 'group1'), 0); +} + +sub lunReadOnly { + my $SCST = shift; + my $driver = shift; + my $target = shift; + my $lun = shift; + + my ($a, $errorString) = $SCST->lunAttributes($driver, $target, $lun); + my $roHash = $a->{'read_only'}; + return exists($roHash->{'keys'}) ? $roHash->{'keys'}->{'0'}->{'value'} : + $roHash->{'value'}; +} + +sub lunTest { + my $SCST = shift; + + ok($SCST->openDevice("no-such-handler", "disk01", { }), + $SCST->SCST_C_HND_NO_HANDLER); + ok($SCST->openDevice("vdisk_fileio", "disk01", undef), + $SCST->SCST_C_DEV_OPEN_FAIL); + ok($SCST->openDevice("vdisk_fileio", "disk01", { }), + $SCST->SCST_C_DEV_OPEN_FAIL); + ok($SCST->openDevice("vdisk_fileio", "disk01", + { 'filename' => '/proc/cpuinfo' }), 0); + ok(Dumper($SCST->devicesByHandler("vdisk_fileio")), + Dumper(["disk01"], undef)); + ok($SCST->openDevice("vdisk_fileio", "disk01", + { 'filename' => '/proc/cpuinfo' }), + $SCST->SCST_C_DEV_EXISTS); + ok($SCST->openDevice("vdisk_fileio", "disk02", + { 'filename' => '/proc/cpuinfo' }), 0); + + ok($SCST->addLun('scst_local', 'local1', 'disk01', 0), + $SCST->SCST_C_TGT_ADD_LUN_FAIL); + ok($SCST->addLun('scst_local', 'local3', 'disk01', 0, { }), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 0, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk02', 1, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 2, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk02', 3, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 3, { }), + $SCST->SCST_C_TGT_LUN_EXISTS); + + ok($SCST->lunExists(), 0); + ok($SCST->lunExists('scst_local'), 0); + ok($SCST->lunExists('scst_local', 'local1'), 0); + ok($SCST->lunExists('no-such-driver', 'local1', 0), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->lunExists('scst_local', 'no-such-target', 0), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->lunExists('scst_local', 'local1', 99), 0); + ok($SCST->lunExists('scst_local', 'local1', 0), 1); + + ok($SCST->addGroup('scst_local', 'local1', 'group1'), 0); + ok($SCST->addInitiator('scst_local', 'local1', 'group1', 'ini1'), 0); + + ok($SCST->addLun('scst_local', 'local1', 'disk01', 0, undef, 'group1'), + $SCST->SCST_C_GRP_ADD_LUN_FAIL); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 0, { }, 'group1'), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk02', 2, { }, 'group1'), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 4, { }, 'group1'), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk02', 6, { }, 'group1'), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk01', 6, { }, 'group1'), + $SCST->SCST_C_GRP_LUN_EXISTS); + + ok($SCST->lunExists('no-such-driver', 'local1', 0, 'group1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->lunExists('scst_local', 'no-such-target', 0, 'group1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->lunExists('scst_local', 'local1', 99, 'group1'), 0); + ok($SCST->lunExists('scst_local', 'local1', 0, 'no-such-group'), + $SCST->SCST_C_GRP_NO_GROUP); + ok($SCST->lunExists('scst_local', 'local1', 0, 'group1'), 1); + + ok(Dumper($SCST->luns()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->luns('scst_local')), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->luns('no-such-driver', 'local1')), + Dumper(undef, "luns(): Driver 'no-such-driver' is not available")); + ok(Dumper($SCST->luns('scst_local', 'no-such-target')), + Dumper(undef, "luns(): Target 'no-such-target' is not available")); + ok(Dumper($SCST->luns('scst_local', 'local1')), + Dumper({ '0' => 'disk01', '1' => 'disk02', '2' => 'disk01', + '3' => 'disk02' }, undef)); + ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')), + Dumper({ '0' => 'disk01', '2' => 'disk02', '4' => 'disk01', + '6' => 'disk02' }, undef)); + + ok(lunReadOnly($SCST, 'scst_local', 'local1', 0), '0'); + ok($SCST->setLunAttribute(), $SCST->SCST_C_LUN_SETATTR_FAIL); + ok($SCST->setLunAttribute('no-such-driver', 'local1', 0, 'read_only', '1'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->setLunAttribute('scst_local', 'no-such-target', 0, 'read_only', '1'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->setLunAttribute('scst_local', 'local1', 99, 'read_only', '1'), + $SCST->SCST_C_TGT_NO_LUN); + ok($SCST->setLunAttribute('scst_local', 'local1', 0, 'read_only', '1'), + $SCST->SCST_C_LUN_ATTRIBUTE_STATIC); + ok(lunReadOnly($SCST, 'scst_local', 'local1', 0), '0'); + ok(lunReadOnly($SCST, 'scst_local', 'local1', 0, 'group1'), '0'); + ok($SCST->setLunAttribute('scst_local', 'local1', 0, 'read_only', '1', 'no-such-group'), + $SCST->SCST_C_GRP_NO_GROUP); + ok($SCST->setLunAttribute('scst_local', 'local1', 99, 'read_only', '1', 'group1'), + $SCST->SCST_C_GRP_NO_LUN); + ok($SCST->setLunAttribute('scst_local', 'local1', 0, 'read_only', '1', 'group1'), + $SCST->SCST_C_LUN_ATTRIBUTE_STATIC); + ok(lunReadOnly($SCST, 'scst_local', 'local1', 0, 'group1'), '0'); + + ok($SCST->replaceLun('scst_local', 'local1', 0, 'disk02', {}), 0); + ok(Dumper($SCST->luns('scst_local', 'local1')), + Dumper({ '0' => 'disk02', '1' => 'disk02', '2' => 'disk01', + '3' => 'disk02' }, undef)); + ok($SCST->replaceLun('scst_local', 'local1', 0, 'disk01', {}), 0); + ok(Dumper($SCST->luns('scst_local', 'local1')), + Dumper({ '0' => 'disk01', '1' => 'disk02', '2' => 'disk01', + '3' => 'disk02' }, undef)); + + ok($SCST->clearLuns(undef, undef), $SCST->SCST_C_TGT_CLR_LUN_FAIL); + ok($SCST->clearLuns(undef, undef, 'group1'), + $SCST->SCST_C_GRP_CLR_LUN_FAIL); + ok($SCST->removeLun(undef, undef, undef), $SCST->SCST_C_TGT_ADD_LUN_FAIL); + ok($SCST->removeLun('no-such-driver', 'local1', '0'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeLun('scst_local', 'no-such-target', '0'), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->removeLun(undef, undef, undef, 'group1'), + $SCST->SCST_C_GRP_REM_LUN_FAIL); + ok($SCST->removeLun('scst_local', 'local1', '4'), $SCST->SCST_C_TGT_NO_LUN); + ok($SCST->removeLun('scst_local', 'local1', '8', 'group1'), + $SCST->SCST_C_GRP_NO_LUN); + ok($SCST->clearLuns('scst_local', 'local1'), 0); + ok(Dumper($SCST->luns('scst_local', 'local1')), Dumper({ }, undef)); + ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')), + Dumper({ '0' => 'disk01', '2' => 'disk02', '4' => 'disk01', + '6' => 'disk02' }, undef)); + ok($SCST->removeLun('scst_local', 'local1', '4', 'group1'), 0); + ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')), + Dumper({ '0' => 'disk01', '2' => 'disk02', '6' => 'disk02' }, undef)); + ok($SCST->clearLuns('scst_local', 'local1', 'group1'), 0); + ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')), + Dumper({ }, undef)); + + ok($SCST->removeInitiator('scst_local', 'local1', 'group1', 'ini1'), 0); + ok($SCST->removeGroup('scst_local', 'local1', 'group1'), 0); + + ok($SCST->closeDevice("no-such-handler", "disk01"), + $SCST->SCST_C_HND_NO_HANDLER); + ok($SCST->closeDevice("vdisk_fileio", "disk02"), 0); + ok($SCST->closeDevice("vdisk_fileio", "disk01"), 0); + ok($SCST->closeDevice("vdisk_fileio", "disk01"), + $SCST->SCST_C_DEV_NO_DEVICE); +} + +sub remTargets { + my $SCST = shift; + + ok($SCST->removeVirtualTarget('scst_local', 'local2'), 0); + ok($SCST->removeVirtualTarget('scst_local', 'local1'), 0); + ok(Dumper($SCST->targets('scst_local')), Dumper([], undef)); +} + +my $_DEBUG_ = 0; + +my $SCST = eval { new SCST::SCST($_DEBUG_) }; +die("Creation of SCST object failed") if (!defined($SCST)); + +addTargets($SCST); +sessTest($SCST); +driverDynamicAttributesTest($SCST); +iniGrpTest($SCST); +lunTest($SCST); +remTargets($SCST); diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/04-alua.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/04-alua.t new file mode 100644 index 000000000..c2b39a7d1 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/04-alua.t @@ -0,0 +1,143 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => 62; +} + +use Data::Dumper; +use SCST::SCST; + +sub setup { + my $SCST = shift; + + my ($drivers, $errorString) = $SCST->drivers(); + my %drivers = map { $_ => 1 } @{$drivers}; + ok(exists($drivers{'iscsi'})); + ok(exists($drivers{'scst_local'})); + + ok($SCST->openDevice("vdisk_fileio", "disk01", + { 'filename' => '/proc/cpuinfo' }), 0); + ok($SCST->openDevice("vdisk_fileio", "disk02", + { 'filename' => '/proc/cpuinfo' }), 0); + ok($SCST->openDevice("vdisk_fileio", "disk03", + { 'filename' => '/proc/cpuinfo' }), 0); + ok($SCST->openDevice("vdisk_fileio", "disk04", + { 'filename' => '/proc/cpuinfo' }), 0); + + ok($SCST->addVirtualTarget('scst_local', 'local1'), 0); + + ok($SCST->addLun('scst_local', 'local1', 'disk01', 0, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk02', 1, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk03', 2, { }), 0); + ok($SCST->addLun('scst_local', 'local1', 'disk04', 3, { }), 0); +} + +sub test { + my $SCST = shift; + + ok(Dumper($SCST->deviceGroups()), Dumper([], undef)); + + ok($SCST->addDeviceGroup('dg1'), 0); + ok($SCST->addDeviceGroup('dg2'), 0); + ok($SCST->addDeviceGroup('dg3'), 0); + ok($SCST->addDeviceGroup('dg4'), 0); + + ok(Dumper($SCST->deviceGroups()), + Dumper(['dg1', 'dg2', 'dg3', 'dg4'], undef)); + + ok(Dumper($SCST->deviceGroupDevices()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->deviceGroupDevices('dg1')), Dumper([], undef)); + ok($SCST->addDeviceGroupDevice('dg1', 'disk01'), 0); + ok($SCST->addDeviceGroupDevice('dg1', 'disk01'), + $SCST->SCST_C_DGRP_DEVICE_EXISTS); + ok($SCST->addDeviceGroupDevice('dg2', 'disk02'), 0); + ok($SCST->addDeviceGroupDevice('dg2', 'disk01'), + $SCST->SCST_C_DGRP_DEVICE_OTHER); + ok($SCST->addDeviceGroupDevice('dg3', 'disk03'), 0); + ok($SCST->addDeviceGroupDevice('dg4', 'disk04'), 0); + ok(Dumper($SCST->deviceGroupDevices('dg1')), Dumper(['disk01'], undef)); + ok(Dumper($SCST->deviceGroupDevices('dg2')), Dumper(['disk02'], undef)); + ok(Dumper($SCST->deviceGroupDevices('dg3')), Dumper(['disk03'], undef)); + ok(Dumper($SCST->deviceGroupDevices('dg4')), Dumper(['disk04'], undef)); + + ok(Dumper($SCST->targetGroups()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targetGroups('no-such-device-group')), + Dumper(undef, "targetGroups(): Device group 'no-such-device-group'" . + " does not exist")); + ok(Dumper($SCST->targetGroups('dg1')), Dumper([], undef)); + + ok(Dumper($SCST->targetGroupTargets()), Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targetGroupTargets('no-such-device-group')), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targetGroupTargets('no-such-device-group', 'tg1')), + Dumper(undef, "targetGroupTargets(): Device group 'no-such-device-". + "group' does not exist")); + ok(Dumper($SCST->targetGroupTargets('dg1', 'no-such-target-group')), + Dumper(undef, "targetGroupTargets(): Target group 'no-such-target-". + "group' does not exist")); + ok(Dumper($SCST->targetGroupTargets('dg1', 'tg1')), Dumper(undef, + "targetGroupTargets(): Target group 'tg1' does not exist")); + ok($SCST->addTargetGroup(), $SCST->SCST_C_DGRP_ADD_GRP_FAIL); + ok($SCST->addTargetGroup('no-such-device-group', 'tg1'), + $SCST->SCST_C_DEV_GRP_NO_GROUP); + ok($SCST->addTargetGroup('dg1', 'tg1'), 0); + ok($SCST->addTargetGroup('dg1', 'tg1'), $SCST->SCST_C_DGRP_GROUP_EXISTS); + ok($SCST->addTargetGroup('dg1', 'tg2'), 0); + + my ($tga, $errorString) = $SCST->targetGroupAttributes('dg1', 'tg1'); + ok(Dumper($tga->{'group_id'}), + Dumper({ 'keys' => { '0' => { 'value' => '0' } }, 'static' => 0 })); + ok($SCST->setTargetGroupAttribute('dg1', 'tg1', 'group_id', 7), 0); + ($tga, $errorString) = $SCST->targetGroupAttributes('dg1', 'tg1'); + ok(Dumper($tga->{'group_id'}), + Dumper({ 'keys' => { '0' => { 'value' => '7' } }, 'static' => 0 })); + + ok($SCST->addTargetGroupTarget(), $SCST->SCST_C_TGRP_ADD_TGT_FAIL); + ok($SCST->addTargetGroupTarget('no-such-device-group', 'tg1', 'tgt1'), + $SCST->SCST_C_DEV_GRP_NO_GROUP); + ok($SCST->addTargetGroupTarget('dg1', 'no-such-target-group', 'tgt1'), + $SCST->SCST_C_DGRP_NO_GROUP); + ok($SCST->addTargetGroupTarget('dg1', 'tg1', 'tgt1'), 0); + ok($SCST->addTargetGroupTarget('dg1', 'tg1', 'tgt1'), + $SCST->SCST_C_TGRP_TGT_EXISTS); + ok($SCST->addTargetGroupTarget('dg1', 'tg2', 'tgt2'), 0); + + my $tgta; + ($tgta, $errorString) = + $SCST->targetGroupTargetAttributes('dg1', 'tg1', 'tgt1'); + ok(Dumper($tgta->{'rel_tgt_id'}), + Dumper({ 'keys' => { '0' => { 'value' => '0' } }, 'static' => 0 })); + ok($SCST->setTargetGroupTargetAttribute('dg1', 'tg1', 'tgt1', 'rel_tgt_id', + 8), 0); + ($tgta, $errorString) = + $SCST->targetGroupTargetAttributes('dg1', 'tg1', 'tgt1'); + ok(Dumper($tgta->{'rel_tgt_id'}), + Dumper({ 'keys' => { '0' => { 'value' => '8' } }, 'static' => 0 })); + + ok($SCST->removeDeviceGroup('dg1'), 0); + ok($SCST->removeDeviceGroup('dg2'), 0); + ok($SCST->removeDeviceGroup('dg3'), 0); + ok($SCST->removeDeviceGroup('dg4'), 0); + + ok(Dumper($SCST->deviceGroups()), Dumper([], undef)); +} + +sub teardown { + my $SCST = shift; + + ok($SCST->removeVirtualTarget('scst_local', 'local1'), 0); + ok($SCST->closeDevice("vdisk_fileio", "disk01"), 0); + ok($SCST->closeDevice("vdisk_fileio", "disk02"), 0); +} + +my $_DEBUG_ = 0; + +my $SCST = eval { new SCST::SCST($_DEBUG_) }; +die("Creation of SCST object failed") if (!defined($SCST)); + +setup($SCST); +test($SCST); +teardown($SCST); diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/05-dynattr.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/05-dynattr.t new file mode 100644 index 000000000..02ff569ca --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/05-dynattr.t @@ -0,0 +1,160 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => 55; +} + +use Data::Dumper; +use SCST::SCST; + +sub setup { + my $SCST = shift; + + my ($drivers, $errorString) = $SCST->drivers(); + my %drivers = map { $_ => 1 } @{$drivers}; + ok(exists($drivers{'iscsi'})); + ok(exists($drivers{'scst_local'})); + + ok($SCST->openDevice("vdisk_fileio", "disk01", + { 'filename' => '/proc/cpuinfo' }), 0); + + ok($SCST->addVirtualTarget('iscsi', 'tgt1'), 0); + + ok($SCST->addLun('iscsi', 'tgt1', 'disk01', 0, { }), 0); +} + +sub testDriverDynAttr { + my $SCST = shift; + + ok(Dumper($SCST->driverDynamicAttributes()), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->driverDynamicAttributes('no-such-driver')), + Dumper(undef, "driverDynamicAttributes(): Driver 'no-such-driver' is " . + "not available")); + ok(Dumper($SCST->driverDynamicAttributes('scst_local')), Dumper({}, undef)); + ok(Dumper($SCST->driverDynamicAttributes('iscsi')), + Dumper({ 'IncomingUser' => '', 'OutgoingUser' => '' }, undef)); + ok($SCST->checkDriverDynamicAttributes('no-such-driver'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->checkDriverDynamicAttributes('no-such-driver', { }), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->checkDriverDynamicAttributes('scst_local', { }), 0); + ok($SCST->checkDriverDynamicAttributes('iscsi', { }), 0); + ok($SCST->checkDriverDynamicAttributes('iscsi', + { 'IncomingUser' => ''}), 0); + ok($SCST->checkDriverDynamicAttributes('iscsi', + { 'IncomingUser' => '', + 'OutgoingUser' => '' }), 0); + ok($SCST->checkDriverDynamicAttributes('iscsi', + { 'IncomingUser' => '', + 'OutgoingUser' => '', + 'NoSuchAttribute' => '' }), 1); + + ok($SCST->addDriverDynamicAttribute(), $SCST->SCST_C_DRV_ADDATTR_FAIL); + ok($SCST->addDriverDynamicAttribute('no-such-driver', '', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->addDriverDynamicAttribute('iscsi', 'no-such-attribute', ''), + $SCST->SCST_C_DRV_BAD_ATTRIBUTES); + ok($SCST->addDriverDynamicAttribute('iscsi', 'IncomingUser', + 'bar 12CharSecret'), 0); + ok($SCST->addDriverDynamicAttribute('iscsi', 'IncomingUser', + 'joe 12charsecret'), 0); + my ($da, $errorString) = $SCST->driverAttributes('iscsi'); + ok(Dumper($da->{'IncomingUser'}), + Dumper({ 'keys' => { '0' => { 'value' => 'bar 12CharSecret' }, + '1' => { 'value' => 'joe 12charsecret' } }, + 'static' => 0 })); + ok($SCST->removeDriverDynamicAttribute(), $SCST->SCST_C_DRV_REMATTR_FAIL); + ok($SCST->removeDriverDynamicAttribute('no-such-driver', '', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeDriverDynamicAttribute('iscsi', 'no-such-attribute', ''), + $SCST->SCST_C_DRV_BAD_ATTRIBUTES); + ok($SCST->removeDriverDynamicAttribute('iscsi', 'IncomingUser', + 'joe 12charsecret'), 0); + ok($SCST->removeDriverDynamicAttribute('iscsi', 'IncomingUser', + 'bar 12CharSecret'), 0); + ($da, $errorString) = $SCST->driverAttributes('iscsi'); + ok(!exists($da->{'IncomingUser'})); +} + +sub testTargetDynAttr { + my $SCST = shift; + + ok(Dumper($SCST->targetDynamicAttributes()), + Dumper(undef, "Too few arguments")); + ok(Dumper($SCST->targetDynamicAttributes('no-such-driver')), + Dumper(undef, "targetDynamicAttributes(): Driver 'no-such-driver' is" . + " not available")); + ok(Dumper($SCST->targetDynamicAttributes('scst_local')), Dumper({}, undef)); + ok(Dumper($SCST->targetDynamicAttributes('iscsi')), + Dumper({ 'IncomingUser' => '', + 'OutgoingUser' => '', + 'allowed_portal' => '' }, undef)); + ok($SCST->checkTargetDynamicAttributes('no-such-driver'), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->checkTargetDynamicAttributes('no-such-driver', { }), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->checkTargetDynamicAttributes('scst_local', { }), 0); + ok($SCST->checkTargetDynamicAttributes('iscsi', { }), 0); + ok($SCST->checkTargetDynamicAttributes('iscsi', + { 'IncomingUser' => ''}), 0); + ok($SCST->checkTargetDynamicAttributes('iscsi', + { 'IncomingUser' => '', + 'OutgoingUser' => '' }), 0); + ok($SCST->checkTargetDynamicAttributes('iscsi', + { 'IncomingUser' => '', + 'OutgoingUser' => '', + 'NoSuchAttribute' => '' }), 1); + + ok($SCST->addTargetDynamicAttribute(), $SCST->SCST_C_TGT_ADDATTR_FAIL); + ok($SCST->addTargetDynamicAttribute('no-such-driver', '', '', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->addTargetDynamicAttribute('iscsi', 'no-such-target', '', ''), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->addTargetDynamicAttribute('iscsi', 'tgt1', 'no-such-attribute', + '', ''), + $SCST->SCST_C_TGT_BAD_ATTRIBUTES); + ok($SCST->addTargetDynamicAttribute('iscsi', 'tgt1', 'IncomingUser', + 'bar 12CharSecret'), 0); + ok($SCST->addTargetDynamicAttribute('iscsi', 'tgt1', 'IncomingUser', + 'joe 12charsecret'), 0); + my ($ta, $errorString) = $SCST->targetAttributes('iscsi', 'tgt1'); + ok(Dumper($ta->{'IncomingUser'}), + Dumper({ 'keys' => { '0' => { 'value' => 'bar 12CharSecret' }, + '1' => { 'value' => 'joe 12charsecret' } }, + 'static' => 0 })); + ok($SCST->removeTargetDynamicAttribute(), $SCST->SCST_C_TGT_REMATTR_FAIL); + ok($SCST->removeTargetDynamicAttribute('no-such-driver', '', '', ''), + $SCST->SCST_C_DRV_NO_DRIVER); + ok($SCST->removeTargetDynamicAttribute('iscsi', 'no-such-target', '', ''), + $SCST->SCST_C_TGT_NO_TARGET); + ok($SCST->removeTargetDynamicAttribute('iscsi', 'tgt1', 'no-such-attribute', + ''), + $SCST->SCST_C_TGT_BAD_ATTRIBUTES); + ok($SCST->removeTargetDynamicAttribute('iscsi', 'tgt1', 'IncomingUser', + 'joe 12charsecret'), 0); + ok($SCST->removeTargetDynamicAttribute('iscsi', 'tgt1', 'IncomingUser', + 'bar 12CharSecret'), 0); + ($ta, $errorString) = $SCST->targetAttributes('iscsi', 'tgt1'); + ok(!exists($ta->{'IncomingUser'})); +} + +sub teardown { + my $SCST = shift; + + ok($SCST->removeVirtualTarget('iscsi', 'tgt1'), 0); + ok($SCST->closeDevice("vdisk_fileio", "disk01"), 0); +} + +my $_DEBUG_ = 0; + +my $SCST = eval { new SCST::SCST($_DEBUG_) }; +die("Creation of SCST object failed") if (!defined($SCST)); + +setup($SCST); +testDriverDynAttr($SCST); +testTargetDynAttr($SCST); +teardown($SCST); diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t new file mode 100644 index 000000000..2aa100c6a --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t @@ -0,0 +1,67 @@ +#!perl + +use strict; +use Cwd qw(abs_path); +use File::Basename; +use File::Spec; +use Test; + +my $testdir; +my $scstadmin_pm_dir; +my $scstadmin_dir; +my $scstadmin; + +BEGIN { + $testdir = dirname(abs_path($0)); + $scstadmin_pm_dir = dirname($testdir); + $scstadmin_dir = dirname($scstadmin_pm_dir); + $scstadmin = File::Spec->catfile($scstadmin_dir, "scstadmin"); + unless(grep /blib/, @INC) { + unshift(@INC, File::Spec->catdir($scstadmin_pm_dir, "lib")); + } + plan tests => 2; +} + +use Data::Dumper; +use SCST::SCST; +use File::Temp qw/tempfile/; + +sub setup { + my $SCST = shift; + + my ($drivers, $errorString) = $SCST->drivers(); + my %drivers = map { $_ => 1 } @{$drivers}; + ok(exists($drivers{'ib_srpt'})); +} + +sub testRestoreConfig { + my $to_be_restored = shift; + my $expected = shift; + my $tmpfilename1 = File::Spec->catfile(File::Spec->tmpdir(), + "scstadmin-test-06-$$-1"); + my $tmpfilename2 = File::Spec->catfile(File::Spec->tmpdir(), + "scstadmin-test-06-$$-2"); + + system("$scstadmin -clear_config -force -noprompt -no_lip >/dev/null"); + system("$scstadmin -cont_on_err -no_lip -config $to_be_restored" . + " >/dev/null"); + system("$scstadmin -write_config $tmpfilename1 >/dev/null"); + system("awk 'BEGIN {t = 0 } /^TARGET_DRIVER.*{\$/ { if (\$0 != \"TARGET_DRIVER scst_local {\") t = 1 } /^}\$/ { if (t == 1) t = 2 } /^\$/ { if (t == 2) { t = 3 } } /^./ { if (t == 3) { t = 0 } } { if (t == 0) print }' <$tmpfilename1 >$tmpfilename2"); + my $compare_result = system("diff -u $tmpfilename2 $expected"); + ok($compare_result, 0); + if ($compare_result == 0) { + unlink($tmpfilename2); + unlink($tmpfilename1); + } +} + +my $_DEBUG_ = 0; + +my $SCST = eval { new SCST::SCST($_DEBUG_) }; +die("Creation of SCST object failed") if (!defined($SCST)); + +setup($SCST); + +testRestoreConfig(File::Spec->catfile($testdir, "to-be-restored.conf"), + File::Spec->catfile($testdir, "after-restore.conf")); + diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/99-stop-scst.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/99-stop-scst.t new file mode 100644 index 000000000..6aeda35bd --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/99-stop-scst.t @@ -0,0 +1,21 @@ +#!perl + +use strict; +use Test; + +BEGIN { + plan tests => 2; +} + +if ($> == 0) { + ok(system("killall iscsi-scstd; " . + "modprobe -r scst_local; " . + "modprobe -r iscsi-scst; " . + "modprobe -r ib_srpt; " . + "modprobe -r qla2x00tgt; " . + "modprobe -r qla2xxx_scst; " . + "modprobe -r scst_vdisk"), 0); + ok(!(-d "/sys/module/scst")); +} else { + ok(1); +} diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf new file mode 100644 index 000000000..9bcda73e5 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf @@ -0,0 +1,56 @@ +# Automatically generated by SCST Configurator v3.0.0-pre2. + + +HANDLER vdisk_fileio { + DEVICE disk01 { + filename /proc/cpuinfo + } +} + +TARGET_DRIVER scst_local { + TARGET local1 { + session_name local1_session + + LUN 0 disk01 + LUN 1 disk01 + + GROUP initator_group { + LUN 0 disk01 + LUN 1 disk01 { + read_only 1 + } + LUN 2 disk01 + + INITIATOR ini1 + + INITIATOR ini2 + + INITIATOR ini3 + } + } +} + +DEVICE_GROUP dg01 { + DEVICE disk01 + + TARGET_GROUP tg01a { + group_id 1 + preferred 1 + state active + + TARGET tgt_a { + rel_tgt_id 2 + } + } + + TARGET_GROUP tg01b { + group_id 2 + preferred 0 + state active + + TARGET tgt_b { + rel_tgt_id 3 + } + } +} + diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf new file mode 100644 index 000000000..c5c3d6320 --- /dev/null +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf @@ -0,0 +1,62 @@ +# Automatically generated by SCST Configurator v3.0.0-pre2. + + +HANDLER vdisk_fileio { + DEVICE disk01 { + filename /proc/cpuinfo + } +} + +TARGET_DRIVER ib_srpt { + TARGET no_such_target { + enabled 1 + } +} + +TARGET_DRIVER scst_local { + TARGET local1 { + session_name local1_session + + LUN 0 disk01 + LUN 1 disk01 + + GROUP initator_group { + LUN 0 disk01 + LUN 1 disk01 { + read_only 1 + } + LUN 2 disk01 + + INITIATOR ini1 + + INITIATOR ini2 + + INITIATOR ini3 + } + } +} + +DEVICE_GROUP dg01 { + DEVICE disk01 + + TARGET_GROUP tg01a { + group_id 1 + preferred 1 + state active + + TARGET tgt_a { + rel_tgt_id 2 + } + } + + TARGET_GROUP tg01b { + group_id 2 + preferred 0 + state active + + TARGET tgt_b { + rel_tgt_id 3 + } + } +} + diff --git a/scstadmin/scstadmin.sysfs/scstadmin b/scstadmin/scstadmin.sysfs/scstadmin index 43ee1c160..07aa962a7 100755 --- a/scstadmin/scstadmin.sysfs/scstadmin +++ b/scstadmin/scstadmin.sysfs/scstadmin @@ -202,7 +202,7 @@ Target Driver Operations -issue_lip [] [-driver ] : Issue a LIP for a specific driver/target or for all drivers and targets. - -no_lip : Don't automatically issue a LIP after applying + -no_lip : Don\'t automatically issue a LIP after applying configuration changes. Options @@ -211,7 +211,8 @@ Options -force : Force all configuration changes, even deletions (DANGER!). -noprompt : Do not prompt or pause. Use with caution! - + -cont_on_err : Continue after an error occurred. + Debugging (limited support) -debug : Debug mode - don\'t do anything destructive. @@ -258,6 +259,7 @@ my $CONFIG; my $CONFIGFILE; my $_DEBUG_; my $_NOPROMPT_; +my $_CONT_ON_ERR_; my %CURRENT; @@ -458,6 +460,7 @@ sub getArgs { 'nonkey' => \$nonkey, 'noprompt' => \$_NOPROMPT_, + 'cont_on_err' => \$_CONT_ON_ERR_, 'force' => \$force, 'debug' => \$_DEBUG_)) { @@ -471,6 +474,7 @@ sub getArgs { $_DEBUG_ = TRUE if (defined($_DEBUG_)); $_NOPROMPT_ = TRUE if (defined($_NOPROMPT_)); + $_CONT_ON_ERR_ = TRUE if (defined($_CONT_ON_ERR_)); $force = TRUE if (defined($force)); $nonkey = TRUE if (defined($nonkey)); @@ -761,7 +765,7 @@ sub main { defined($applyConfig) && do { $CONFIGFILE = $applyConfig; $rc = checkConfiguration(); - immediateExit("Configuration has errors, aborting.") if ($rc); + condExit("Configuration has errors, aborting.") if ($rc); last if ($force && prompt()); my $changes = applyConfiguration($force); $rc = issueLip() if ($changes && !$noLip); @@ -1166,58 +1170,58 @@ sub readWorkingConfig { # Get current handlers/devices - my $handlers = $SCST->handlers(); - immediateExit($SCST->errorString()); + my ($handlers, $errorString) = $SCST->handlers(); + immediateExit($errorString); foreach my $handler (@{$handlers}) { - my $devices = $SCST->devicesByHandler($handler); - immediateExit($SCST->errorString()); + my ($devices, $errorString) = $SCST->devicesByHandler($handler); + immediateExit($errorString); $CURRENT{'handler'}->{$handler} = $devices; } # Get current assignments - my $drivers = $SCST->drivers(); - immediateExit($SCST->errorString()); + my ($drivers, $errorString) = $SCST->drivers(); + immediateExit($errorString); foreach my $driver (@{$drivers}) { my %empty; $CURRENT{'assign'}->{$driver} = \%empty; - my $targets = $SCST->targets($driver); - immediateExit($SCST->errorString()); + my ($targets, $errorString) = $SCST->targets($driver); + immediateExit($errorString); foreach my $target (@{$targets}) { my %empty; $CURRENT{'assign'}->{$driver}->{$target} = \%empty; - my $luns = $SCST->luns($driver, $target); + my ($luns, $errorString) = $SCST->luns($driver, $target); $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'} = $luns if (defined($luns)); - my $groups = $SCST->groups($driver, $target); - immediateExit($SCST->errorString()); + my ($groups, $errorString) = $SCST->groups($driver, $target); + immediateExit($errorString); foreach my $group (@{$groups}) { - $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'} = - $SCST->initiators($driver, $target, $group); - immediateExit($SCST->errorString()); - - $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'} = - $SCST->luns($driver, $target, $group); - immediateExit($SCST->errorString()); + my ($initiators, $errorString) = $SCST->initiators($driver, $target, $group); + immediateExit($errorString); + $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'} = $initiators; + my ($luns, $errorString) = $SCST->luns($driver, $target, $group); + $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'} = $luns; + immediateExit($errorString); } } } - my $dgroups = $SCST->deviceGroups(); - immediateExit($SCST->errorString()); + my ($dgroups, $errorString) = $SCST->deviceGroups(); + immediateExit($errorString); foreach my $dgroup (@{$dgroups}) { - $CURRENT{'dgroups'}->{$dgroup}->{'devices'} = $SCST->deviceGroupDevices($dgroup); - immediateExit($SCST->errorString()); - my $tgroups = $SCST->targetGroups($dgroup); - immediateExit($SCST->errorString()); + my ($dgd, $errorString) = $SCST->deviceGroupDevices($dgroup); + immediateExit($errorString); + $CURRENT{'dgroups'}->{$dgroup}->{'devices'} = $dgd; + my ($tgroups, $errorString) = $SCST->targetGroups($dgroup); + immediateExit($errorString); foreach my $tgroup (@{$tgroups}) { - $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'} = - $SCST->targetGroupTargets($dgroup, $tgroup); + my ($tgt, $errorString) = $SCST->targetGroupTargets($dgroup, $tgroup); + $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'} = $tgt; } } @@ -1281,12 +1285,14 @@ sub serializeKeyAttr { && defined($$attr_filter{$attribute}))); if (defined($$attributes{$attribute}->{'keys'})) { - foreach my $key (sort keys %{$$attributes{$attribute}->{'keys'}}) { + my @values; + foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) { my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'}; - if ($value ne '') { - $result .= "$prefix$attribute " . escapeMeta($value) . "\n"; - } + push (@values, $value) if ($value ne ''); + } + foreach my $value (sort @values) { + $result .= "$prefix$attribute " . escapeMeta($value) . "\n"; } } elsif ($attribute eq 'enabled' || $attribute eq 'hw_target') { my $value = $$attributes{$attribute}->{'value'}; @@ -1342,8 +1348,8 @@ sub writeConfiguration { print $io "# Automatically generated by $Version.\n\n"; { - my $attributes = $SCST->scstAttributes(); - immediateExit($SCST->errorString()); + my ($attributes, $errorString) = $SCST->scstAttributes(); + immediateExit($errorString); print $io serializeKeyAttr("", $attributes); if ($nonkey) { @@ -1360,8 +1366,8 @@ sub writeConfiguration { my $handler_buff; my $handler_buff_nk; - my $handler_attrs = $SCST->deviceCreateAttributes($handler); - my $attributes = $SCST->handlerAttributes($handler); + my ($handler_attrs, $errorString) = $SCST->deviceCreateAttributes($handler); + my ($attributes, $errorString) = $SCST->handlerAttributes($handler); $handler_buff = serializeKeyAttr("\t", $attributes); $handler_buff_nk = serializeNkAttr("\t", $attributes) if ($nonkey); @@ -1372,7 +1378,7 @@ sub writeConfiguration { foreach my $device (sort @{$devices}) { $device_buff .= "\tDEVICE $device"; - my $attributes = $SCST->deviceAttributes($device); + my ($attributes, $errorString) = $SCST->deviceAttributes($device); my $attribute_buff; my $attribute_buff_nk; @@ -1417,7 +1423,7 @@ sub writeConfiguration { foreach my $driver (sort keys %{$CURRENT{'assign'}}) { my $driver_buff; - my $drv_attrs = $SCST->driverAttributes($driver); + my ($drv_attrs, $errorString) = $SCST->driverAttributes($driver); my $drv_attr_buff; my $drv_attr_buff_nk; @@ -1428,13 +1434,13 @@ sub writeConfiguration { $drv_attr_buff_nk .= "\n" if ($drv_attr_buff_nk); my $targets = $CURRENT{'assign'}->{$driver}; - my $tgt_attrs = $SCST->targetCreateAttributes($driver); + my ($tgt_attrs, $errorString) = $SCST->targetCreateAttributes($driver); my $target_buff; foreach my $target (sort keys %{$targets}) { $target_buff .= "\tTARGET $target"; - my $attributes = $SCST->targetAttributes($driver, $target); + my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target); my $attribute_buff; my $attribute_buff_nk; @@ -1450,7 +1456,7 @@ sub writeConfiguration { $attribute_buff_nk .= "\n" if ($attribute_buff_nk); my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'}; - my $lun_attrs = $SCST->lunCreateAttributes($driver, $target); + my ($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target); my $t_lun_buff; foreach my $lun (sort numerically keys %{$luns}) { @@ -1458,7 +1464,7 @@ sub writeConfiguration { $t_lun_buff .= "\t\tLUN $lun $lun_dev"; - my $attributes = $SCST->lunAttributes($driver, $target, $lun); + my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun); my $l_attribute_buff = serializeKeyAttr("\t\t\t", $attributes, @@ -1489,8 +1495,8 @@ sub writeConfiguration { my $group_buff; foreach my $group (sort keys %{$groups}) { - my $lun_attrs = $SCST->lunCreateAttributes($driver, $target, $group); - my $ini_attrs = $SCST->initiatorCreateAttributes($driver, $target, $group); + my ($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group); + my ($ini_attrs, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group); $group_buff .= "\t\tGROUP $group"; @@ -1502,7 +1508,7 @@ sub writeConfiguration { $lun_buff .= "\t\t\tLUN $lun $lun_dev"; - my $attributes = $SCST->lunAttributes($driver, $target, $lun, $group); + my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group); my $l_attribute_buff = serializeKeyAttr("\t\t\t\t", @@ -1532,9 +1538,9 @@ sub writeConfiguration { my $init_buff; foreach my $init (sort @{$inits}) { - $init_buff .= "\n\t\t\tINITIATOR $init"; + $init_buff .= "\n\t\t\tINITIATOR " . escapeMeta($init); - my $attributes = $SCST->initiatorAttributes($driver, $target, $group, $init); + my ($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $init); my $i_attribute_buff = serializeKeyAttr("\t\t\t\t", @@ -1566,7 +1572,7 @@ sub writeConfiguration { $group_buff .= $init_buff; } - my $grp_attributes = $SCST->groupAttributes($driver, $target, $group); + my ($grp_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group); my $g_attribute_buff = serializeKeyAttr("\t\t\t", $grp_attributes); @@ -1630,10 +1636,23 @@ sub writeConfiguration { } } + my ($dga, $errorString) = $SCST->aluaAttributes(); + my $dga_buff = serializeKeyAttr("\t", $dga); + my $dga_buff_nk = serializeNkAttr("\t", $dga) if ($nonkey); + if ($dga_buff_nk) { + $dga_buff .= "\t# Non-key attributes\n"; + $dga_buff .= $dga_buff_nk; + } + if ($dga_buff) { + print $io "ALUA {\n"; + print $io $dga_buff; + print $io "}\n\n"; + } + foreach my $dgroup (sort keys %{$CURRENT{'dgroups'}}) { my $dgroup_buff; - my $dgroup_attrs = $SCST->deviceGroupAttributes($dgroup); + my ($dgroup_attrs, $errorString) = $SCST->deviceGroupAttributes($dgroup); my $dgrp_attr_buff; my $dgrp_attr_buff_nk; @@ -1660,7 +1679,7 @@ sub writeConfiguration { foreach my $tgroup (sort keys %{$tgroups}) { $tgroup_buff .= "\tTARGET_GROUP $tgroup"; - my $attributes = $SCST->targetGroupAttributes($dgroup, $tgroup); + my ($attributes, $errorString) = $SCST->targetGroupAttributes($dgroup, $tgroup); my $attribute_buff; my $attribute_buff_nk; @@ -1676,7 +1695,7 @@ sub writeConfiguration { foreach my $tgt (@{$tgts}) { $tgt_buff .= "\t\tTARGET $tgt"; - my $tgt_attrs = $SCST->targetGroupTargetAttributes($dgroup, $tgroup, $tgt); + my ($tgt_attrs, $errorString) = $SCST->targetGroupTargetAttributes($dgroup, $tgroup, $tgt); my $t_attribute_buff = serializeKeyAttr("\t\t\t", $tgt_attrs); @@ -1940,13 +1959,17 @@ sub applyConfiguration { # Apply config additions $changes += applyConfigDevices($CONFIG, $force); $changes += applyConfigAssignments($CONFIG, $force); + $changes += applyConfigAlua($CONFIG, $force); $changes += applyConfigDeviceGroups($CONFIG, $force); + $changes += applyConfigEnableTargets($CONFIG, $force); + $changes += applyConfigEnableDrivers($CONFIG, $force); # And SCST attributes.. my %_attributes; foreach my $item (keys %{$CONFIG}) { next if ($item eq 'HANDLER'); next if ($item eq 'TARGET_DRIVER'); + next if ($item eq 'ALUA'); next if ($item eq 'DEVICE_GROUP'); $_attributes{$item} = $$CONFIG{$item}; } @@ -1970,7 +1993,7 @@ sub applyConfigDevices { foreach my $handler (keys %{$handlers}) { foreach my $device (@{$$handlers{$handler}}) { if (!defined($$config{'HANDLER'}->{$handler}->{'DEVICE'}->{$device})) { - my $attributes = $SCST->deviceAttributes($device); + my ($attributes, $errorString) = $SCST->deviceAttributes($device); if ($deletions) { closeDevice($handler, $device, $deletions); @@ -1997,14 +2020,14 @@ sub applyConfigDevices { my $attributes = configToAttr(\%_attributes); my $create_attrs = configToAttr(\%_attributes); - my $possible = $SCST->deviceCreateAttributes($handler); - immediateExit($SCST->errorString()); + my ($possible, $errorString) = $SCST->deviceCreateAttributes($handler); + condExit($errorString); filterCreateAttributes($possible, $create_attrs, FALSE); filterCreateAttributes($possible, $attributes, TRUE); if (handlerHasDevice($handler, $device)) { - my $old_create_attrs = $SCST->deviceAttributes($device); - immediateExit($SCST->errorString()); + my ($old_create_attrs, $errorString) = $SCST->deviceAttributes($device); + condExit($errorString); filterCreateAttributes($possible, $old_create_attrs, FALSE); if (compareToKeyAttribute($create_attrs, $old_create_attrs)) { @@ -2083,10 +2106,10 @@ sub applyConfigAssignments { } } else { my $c_attrs = configToAttr($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'LUN'}->{$lun}->{$device}); - my $o_attrs = $SCST->lunAttributes($driver, $target, $lun); - immediateExit($SCST->errorString()); - my $possible = $SCST->lunCreateAttributes($driver, $target); - immediateExit($SCST->errorString()); + my ($o_attrs, $errorString) = $SCST->lunAttributes($driver, $target, $lun); + condExit($errorString); + my ($possible, $errorString) = $SCST->lunCreateAttributes($driver, $target); + condExit($errorString); filterCreateAttributes($possible, $c_attrs, FALSE); @@ -2126,10 +2149,10 @@ sub applyConfigAssignments { } } else { my $c_attrs = configToAttr($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'LUN'}->{$lun}->{$device}); - my $o_attrs = $SCST->lunAttributes($driver, $target, $lun, $group); - immediateExit($SCST->errorString()); - my $possible = $SCST->lunCreateAttributes($driver, $target, $group); - immediateExit($SCST->errorString()); + my ($o_attrs, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group); + condExit($errorString); + my ($possible, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group); + condExit($errorString); filterCreateAttributes($possible, $c_attrs, FALSE); @@ -2170,21 +2193,17 @@ sub applyConfigAssignments { foreach my $driver (sort keys %{$assignments}) { if (!defined($CURRENT{'assign'}->{$driver})) { - immediateExit("Target driver '$driver' is not loaded or available."); + condExit("Target driver '$driver' is not loaded or available."); } my %_attributes; - my %special; foreach my $item (keys %{$$assignments{$driver}}) { if ($item eq 'TARGET') { $changes += applyTargetAssignments($driver, $$assignments{$driver}->{$item}, $deletions); } elsif ($item ne 'enabled') { - # Enable driver last + # Enabling a driver happens in applyConfigEnableDrivers() $_attributes{$item} = $$assignments{$driver}->{$item}; - } else { - $special{$item} = $$assignments{$driver}->{$item}; - } } @@ -2193,9 +2212,28 @@ sub applyConfigAssignments { if (scalar keys %{$attributes}) { $changes += setDriverAttributes($driver, $attributes, $deletions); } + } - $attributes = configToAttr(\%special); - my $d_attributes = $SCST->driverAttributes($driver); + return $changes; +} + +sub applyConfigEnableDrivers { + my $config = shift; + my $deletions = shift; + my $changes = 0; + + my $assignments = $$config{'TARGET_DRIVER'}; + + foreach my $driver (sort keys %{$assignments}) { + my %_attributes; + foreach my $item (keys %{$$assignments{$driver}}) { + if ($item eq 'enabled') { + $_attributes{$item} = $$assignments{$driver}->{$item}; + } + } + + my $attributes = configToAttr(\%_attributes); + my ($d_attributes, $errorString) = $SCST->driverAttributes($driver); if (defined($$d_attributes{'enabled'}) && ($$d_attributes{'enabled'}->{'value'} != $$attributes{'enabled'})) { @@ -2207,6 +2245,19 @@ sub applyConfigAssignments { return $changes; } +sub applyConfigAlua { + my $config = shift; + my $deletions = shift; + + my $alua_attr = $$config{'ALUA'}; + my %_attributes; + foreach my $item (keys %{$alua_attr}) { + $_attributes{$item} = $alua_attr->{$item}; + } + my $attributes = configToAttr(\%_attributes); + return setAluaAttributes($attributes); +} + sub applyConfigDeviceGroups { my $config = shift; my $deletions = shift; @@ -2412,7 +2463,7 @@ sub applyTargetAssignments { if ($deletions && $isVirtual) { my $rc = removeVirtualTarget($driver, $target); - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); $changes++; } else { print "\t-> Virtual target '$target' for driver '$driver' is not in configuration. ". @@ -2423,16 +2474,16 @@ sub applyTargetAssignments { my $possible; - my $is_virtual = $SCST->driverIsVirtualCapable($driver); + my ($is_virtual, $errorString) = $SCST->driverIsVirtualCapable($driver); if ($is_virtual) { - $possible = $SCST->targetCreateAttributes($driver); + ($possible, $errorString) = $SCST->targetCreateAttributes($driver); } foreach my $target (sort keys %{$targets}) { if (!defined($CURRENT{'assign'}->{$driver}->{$target})) { if (!$is_virtual) { - immediateExit("Target '$target' for driver '$driver' does not exist."); + condExit("Target '$target' for driver '$driver' does not exist."); } else { my %_attributes; @@ -2445,13 +2496,13 @@ sub applyTargetAssignments { my $attributes = configToAttr(\%_attributes); if (defined($$attributes{'HW_TARGET'})) { - immediateExit("Hardware target '$target' for driver '$driver' does not exist."); + condExit("Hardware target '$target' for driver '$driver' does not exist."); } filterCreateAttributes($possible, $attributes, FALSE); my $rc = addVirtualTarget($driver, $target, $attributes); - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); $changes++ if (!$rc); } } @@ -2465,28 +2516,52 @@ sub applyTargetAssignments { } my $attributes = configToAttr(\%_attributes); - filterCreateAttributes($possible, $attributes, TRUE); + if ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL) { + filterCreateAttributes($possible, $attributes, TRUE); + } $changes += setTargetAttributes($driver, $target, $attributes, $deletions); - %_attributes = (); foreach my $item (keys %{$$targets{$target}}) { if ($item eq 'GROUP') { $changes += applyGroupAssignments($driver, $target, $$targets{$target}->{$item}); $changes += applyInitiatorAssignments($driver, $target, $$targets{$target}->{$item}, $deletions); } elsif ($item eq 'LUN') { $changes += applyLunAssignments($driver, $target, undef, $$targets{$target}->{$item}); - } elsif ($item eq 'enabled') { - $_attributes{$item} = $$targets{$target}->{$item}; } } + } - $attributes = configToAttr(\%_attributes); - my $t_attributes = $SCST->targetAttributes($driver, $target); + return $changes; +} - if (defined($$t_attributes{'enabled'}) && - ($$t_attributes{'enabled'}->{'value'} != $$attributes{'enabled'})) { - setTargetAttribute($driver, $target, 'enabled', $$attributes{'enabled'}); - $changes++; +sub applyConfigEnableTargets { + my $config = shift; + my $deletions = shift; + my $changes = 0; + + my $assignments = $$config{'TARGET_DRIVER'}; + + foreach my $driver (sort keys %{$assignments}) { + foreach my $driver_item (keys %{$$assignments{$driver}}) { + next if ($driver_item ne 'TARGET'); + my $targets = $$assignments{$driver}->{$driver_item}; + foreach my $target (sort keys %{$targets}) { + my %_attributes = (); + foreach my $target_item (keys %{$$targets{$target}}) { + if ($target_item eq 'enabled') { + $_attributes{$target_item} = $$targets{$target}->{$target_item}; + } + } + + my $attributes = configToAttr(\%_attributes); + my ($t_attributes, $errorString) = $SCST->targetAttributes($driver, $target); + + if (defined($$t_attributes{'enabled'}) && + ($$t_attributes{'enabled'}->{'value'} != $$attributes{'enabled'})) { + setTargetAttribute($driver, $target, 'enabled', $$attributes{'enabled'}); + $changes++; + } + } } } @@ -2638,17 +2713,17 @@ sub clearConfiguration { foreach my $handler (sort keys %{$handlers}) { foreach my $device (@{$$handlers{$handler}}) { - my $attributes = $SCST->deviceAttributes($device); + my ($attributes, $errorString) = $SCST->deviceAttributes($device); closeDevice($handler, $device, TRUE); } } # Todo - check return code - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); foreach my $driver (@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { disableTarget($driver, $target); @@ -2668,10 +2743,10 @@ sub addVirtualTarget { my $attributes = shift; # Enable all hardware targets before creating virtual ones - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $_target (@{$targets}) { - my $attributes = $SCST->targetAttributes($driver, $_target); + my ($attributes, $errorString) = $SCST->targetAttributes($driver, $_target); if (defined($$attributes{'hw_target'}) && !$$attributes{'enabled'}->{'value'}) { @@ -2704,7 +2779,7 @@ sub listHandlers { return listHandler($handler) if ($handler); - my $handlers = $SCST->handlers(); + my ($handlers, $errorString) = $SCST->handlers(); my $l_handler; foreach my $handler (@{$handlers}) { @@ -2730,7 +2805,7 @@ sub listHandler { my %toprint; my $got_handler = ($handler ne ''); - my $handlers = $SCST->handlers(); + my ($handlers, $errorString) = $SCST->handlers(); my $l_device; my $l_handler; @@ -2743,7 +2818,7 @@ sub listHandler { $l_handler = length($handler) if ($l_handler < length($handler)); - my $devices = $SCST->devicesByHandler($handler); + my ($devices, $errorString) = $SCST->devicesByHandler($handler); if ($#{$devices} == -1) { push @{$devices}, '-'; @@ -2764,7 +2839,7 @@ sub listHandler { print "\n"; foreach my $handler (keys %toprint) { - my $devices = $SCST->devicesByHandler($handler); + my ($devices, $errorString) = $SCST->devicesByHandler($handler); my $first = TRUE; if ($#{$devices} == -1) { @@ -2799,9 +2874,9 @@ sub listDevice { my $device = shift; my $nonkey = shift; - my $attributes = $SCST->deviceAttributes($device); + my ($attributes, $errorString) = $SCST->deviceAttributes($device); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such device '$device' exists.\n"; @@ -2817,7 +2892,7 @@ sub listDeviceGroups { return listDeviceGroup($group) if ($group ne ''); - my $groups = $SCST->deviceGroups(); + my ($groups, $errorString) = $SCST->deviceGroups(); my $l_group; foreach my $group (@{$groups}) { @@ -2844,7 +2919,7 @@ sub listDeviceGroups { sub listDeviceGroup { my $group = shift; - my $devices = $SCST->deviceGroupDevices($group); + my ($devices, $errorString) = $SCST->deviceGroupDevices($group); my $l_device; foreach my $device (@{$devices}) { @@ -2864,7 +2939,7 @@ sub listDeviceGroup { print "\t$device\n"; } - my $tgroups = $SCST->targetGroups($group); + my ($tgroups, $errorString) = $SCST->targetGroups($group); my $l_tgroup; foreach my $tgroup (@{$tgroups}) { @@ -2895,7 +2970,7 @@ sub listTargetGroups { return listDeviceGroups(undef, TRUE) if ($group eq ''); return listTargetGroup($group, $tgroup) if ($tgroup ne ''); - my $tgroups = $SCST->targetGroups($group); + my ($tgroups, $errorString) = $SCST->targetGroups($group); my $l_tgroup; foreach my $tgroup (@{$tgroups}) { @@ -2926,7 +3001,7 @@ sub listTargetGroup { my $group = shift; my $tgroup = shift; - my $targets = $SCST->targetGroupTargets($group, $tgroup); + my ($targets, $errorString) = $SCST->targetGroupTargets($group, $tgroup); my $l_tgt; foreach my $tgt (@{$targets}) { @@ -2955,7 +3030,7 @@ sub listDeviceGroupDevices { return listDevice($device) if ($device ne ''); - my $devices = $SCST->deviceGroupDevices($group); + my ($devices, $errorString) = $SCST->deviceGroupDevices($group); my $l_device; foreach my $device (@{$devices}) { @@ -2983,7 +3058,7 @@ sub listDrivers { return listTargets($driver, undef) if ($driver ne ''); - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); my $l_driver; foreach my $driver (@{$drivers}) { @@ -3013,7 +3088,7 @@ sub listTargets { my $got_driver = ($driver ne ''); - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); my $l_driver; my $l_target; @@ -3026,7 +3101,7 @@ sub listTargets { $l_driver = length($driver) if ($l_driver < length($driver)); - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { $l_target = length($target) if ($l_target < length($target)); @@ -3045,7 +3120,7 @@ sub listTargets { my %p; foreach my $driver (keys %toprint) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { if (!defined($p{$driver})) { @@ -3064,17 +3139,17 @@ sub listTargets { } sub listSessions { - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); foreach my $driver (@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { my $had_sessions = FALSE; print "Driver/Target: $driver/$target\n\n"; - my $sessions = $SCST->sessions($driver, $target); + my ($sessions, $errorString) = $SCST->sessions($driver, $target); foreach my $session (keys %{$sessions}) { print "\tSession: $session\n\n"; @@ -3112,12 +3187,13 @@ sub listGroup { my $group = shift; my $luns = shift; my $initiators = shift; + my $errorString; - $luns = $SCST->luns($driver, $target, $group) if (!$luns); - $initiators = $SCST->initiators($driver, $target, $group) - if (($initiators eq '') && ($group ne '')); - - return TRUE if issueWarning($SCST->errorString()); + ($luns, $errorString) = $SCST->luns($driver, $target, $group) if (!$luns); + if (($initiators eq '') && ($group ne '')) { + ($initiators, $errorString) = $SCST->initiators($driver, $target, $group); + return TRUE if issueWarning($errorString); + } if ((keys %{$luns}) || ($#{$initiators} > -1)) { my $l_device; @@ -3193,13 +3269,13 @@ sub listGroups { my $got_target = $target; my $got_driver = $driver; - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); foreach my $_driver (@{$drivers}) { $driver = $_driver if (!$got_driver); if ($driver eq $_driver) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $_target (@{$targets}) { $target = $_target if (!$got_target); @@ -3212,7 +3288,7 @@ sub listGroups { print "\n"; - my $groups = $SCST->groups($driver, $target); + my ($groups, $errorString) = $SCST->groups($driver, $target); foreach my $_group (@{$groups}) { $group = $_group if (!$got_group); @@ -3245,10 +3321,12 @@ sub listGroups { sub listExported { my $device = shift; my $attributes = shift; + my $errorString; - $attributes = $SCST->deviceAttributes($device) if (!$attributes); - - return TRUE if issueWarning($SCST->errorString()); + if (!$attributes) { + ($attributes, $errorString) = $SCST->deviceAttributes($device) ; + return TRUE if issueWarning($errorString); + } if (keys %{$$attributes{'exported'}}) { my $exported = $$attributes{'exported'}->{'value'}; @@ -3416,9 +3494,9 @@ sub listAttributes { sub listScstAttributes { my $nonkey = shift; - my $attributes = $SCST->scstAttributes(); + my ($attributes, $errorString) = $SCST->scstAttributes(); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "FATAL: Unable to get a list of SCST attributes! Please make sure SCST is loaded.\n"; @@ -3432,9 +3510,9 @@ sub listHandlerAttributes { my $handler = shift; my $nonkey = shift; - my $attributes = $SCST->handlerAttributes($handler); + my ($attributes, $errorString) = $SCST->handlerAttributes($handler); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such handler '$handler' found.\n"; @@ -3444,9 +3522,9 @@ sub listHandlerAttributes { my $rc = listAttributes($attributes, $nonkey); return $rc if $rc; - $attributes = $SCST->deviceCreateAttributes($handler); + ($attributes, $errorString) = $SCST->deviceCreateAttributes($handler); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return TRUE if (!scalar keys %{$attributes}); print "\n\tDevice CREATE attributes available\n"; @@ -3463,16 +3541,16 @@ sub listDriverAttributes { my $driver = shift; my $nonkey = shift; - my $attributes = $SCST->driverAttributes($driver); + my ($attributes, $errorString) = $SCST->driverAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); my $rc = listAttributes($attributes, $nonkey); return $rc if ($rc); if ($SCST->driverIsVirtualCapable($driver)) { - $attributes = $SCST->driverDynamicAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + ($attributes, $errorString) = $SCST->driverDynamicAttributes($driver); + return TRUE if issueWarning($errorString); if (scalar keys %{$attributes}) { print "\n\tDynamic attributes available\n"; @@ -3483,9 +3561,9 @@ sub listDriverAttributes { } } - my $attributes = $SCST->targetCreateAttributes($driver); + my ($attributes, $errorString) = $SCST->targetCreateAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return TRUE if (!scalar keys %{$attributes}); print "\n\tTarget CREATE attributes available:\n"; @@ -3504,9 +3582,9 @@ sub listTargetAttributes { my $target = shift; my $nonkey = shift; - my $attributes = $SCST->targetAttributes($driver, $target); + my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such driver/target '$driver/$target' found.\n"; @@ -3517,8 +3595,8 @@ sub listTargetAttributes { return $rc if $rc; if ($SCST->driverIsVirtualCapable($driver)) { - $attributes = $SCST->targetDynamicAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + ($attributes, $errorString) = $SCST->targetDynamicAttributes($driver); + return TRUE if issueWarning($errorString); if (scalar keys %{$attributes}) { print "\n\tDynamic attributes available\n"; @@ -3530,9 +3608,9 @@ sub listTargetAttributes { } } - $attributes = $SCST->lunCreateAttributes($driver, $target); + ($attributes, $errorString) = $SCST->lunCreateAttributes($driver, $target); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return TRUE if (!scalar keys %{$attributes}); print "\n\tLUN CREATE attributes available\n"; @@ -3551,9 +3629,9 @@ sub listGroupAttributes { my $group = shift; my $nonkey = shift; - my $attributes = $SCST->groupAttributes($driver, $target, $group); + my ($attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such driver/target/group '$driver/$target/$group' found.\n"; @@ -3563,9 +3641,9 @@ sub listGroupAttributes { my $rc = listAttributes($attributes, $nonkey); return $rc if $rc; - $attributes = $SCST->lunCreateAttributes($driver, $target, $group); + ($attributes, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return TRUE if (!scalar keys %{$attributes}); print "\n\tLUN CREATE attributes available\n"; @@ -3575,9 +3653,9 @@ sub listGroupAttributes { print "\t$attribute\n"; } - $attributes = $SCST->initiatorCreateAttributes($driver, $target, $group); + ($attributes, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return TRUE if (!scalar keys %{$attributes}); print "\n\tInitiator CREATE attributes available\n"; @@ -3597,9 +3675,9 @@ sub listLunAttributes { my $lun = shift; my $nonkey = shift; - my $attributes = $SCST->lunAttributes($driver, $target, $lun, $group); + my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { if ($group ne '') { @@ -3620,16 +3698,16 @@ sub listInitiatorAttributes { my $initiator = shift; my $nonkey = shift; - my $attributes = $SCST->initiatorAttributes($driver, $target, $group, $initiator); + my ($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $initiator); # As if writing, initiators didn't have attributes. This will # allow us to support it in the future. - if ($SCST->errorString() =~ /Not a directory/) { + if ($errorString =~ /Not a directory/) { print "Initiators do not (yet) have attributes.\n"; return; } - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such driver/target/group/initiator '$driver/$target/$group/$initiator' found.\n"; @@ -3643,9 +3721,9 @@ sub listDeviceGroupAttributes { my $group = shift; my $nonkey = shift; - my $attributes = $SCST->deviceGroupAttributes($group); + my ($attributes, $errorString) = $SCST->deviceGroupAttributes($group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); # Special case - as of writing, device group attributes didn't exist. if (!scalar(keys %{$attributes})) { @@ -3661,9 +3739,9 @@ sub listTargetGroupAttributes { my $tgroup = shift; my $nonkey = shift; - my $attributes = $SCST->targetGroupAttributes($group, $tgroup); + my ($attributes, $errorString) = $SCST->targetGroupAttributes($group, $tgroup); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such device group/target group '$group/$tgroup' found.\n"; @@ -3679,9 +3757,9 @@ sub listTargetGroupTargetAttributes { my $tgt = shift; my $nonkey = shift; - my $attributes = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt); + my ($attributes, $errorString) = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt, TRUE); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); if (!scalar(keys %{$attributes})) { print "No such device group/target group/target '$group/$tgroup/$tgt' found.\n"; @@ -3691,24 +3769,6 @@ sub listTargetGroupTargetAttributes { return listAttributes($attributes, $nonkey); } -sub listTargetGroupTargetAttributes { - my $group = shift; - my $tgroup = shift; - my $tgt = shift; - my $nonkey = shift; - - my $attributes = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt); - - return TRUE if issueWarning($SCST->errorString()); - - if (!scalar(keys %{$attributes})) { - print "No such target '$tgt' exists within specified target group.\n"; - return; - } - - return listAttributes($attributes, $nonkey); -} - #################################################################### sub setScstAttribute { @@ -3731,9 +3791,9 @@ sub setScstAttributes { my $showset = shift; my $error = "\t-> WARNING: SCST lacks the settable attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->scstAttributes(); + my ($_attributes, $errorString) = $SCST->scstAttributes(); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, undef, undef, undef, $attributes, $_attributes, $error, \&setScstAttribute, $showset); @@ -3761,9 +3821,9 @@ sub setDeviceAttributes { my $error = "\t-> WARNING: Device '$device' lacks the settable ". "attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->deviceAttributes($device); + my ($_attributes, $errorString) = $SCST->deviceAttributes($device); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, undef, undef, $device, $attributes, $_attributes, $error, \&setDeviceAttribute, $showset); @@ -3791,9 +3851,9 @@ sub setHandlerAttributes { my $error = "\t-> WARNING: Handler '$handler' lacks the settable ". "attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->handlerAttributes($handler); + my ($_attributes, $errorString) = $SCST->handlerAttributes($handler); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, undef, undef, $handler, $attributes, $_attributes, $error, \&setHandlerAttribute, $showset); @@ -3824,9 +3884,9 @@ sub setGroupAttributes { my $error = "\t-> WARNING: Driver/target/group '$driver/$target/$group' lacks the settable ". "attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->groupAttributes($driver, $target, $group); + my ($_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, $driver, $target, $group, $attributes, $_attributes, $error, \&setGroupAttribute, $showset); @@ -3871,9 +3931,9 @@ sub setLunAttributes { "attribute '%s', ignoring.\n\n"; } - my $_attributes = $SCST->lunAttributes($driver, $target, $lun, $group); + my ($_attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes($driver, $target, $lun, $group, $attributes, $_attributes, $error, \&setLunAttribute, $showset); @@ -3904,13 +3964,13 @@ sub setInitiatorAttributes { my $attributes = shift; my $showset = shift; - my $_attributes = $SCST->initiatorAttributes($driver, $target, $group, $initiator); + my ($_attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $initiator); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); # As if writing, initiators didn't have attributes. This will # allow us to support it in the future. - if ($SCST->errorString() =~ /Not a directory/) { + if ($errorString =~ /Not a directory/) { print "Initiators do not (yet) have attributes.\n"; return; } @@ -3922,6 +3982,35 @@ sub setInitiatorAttributes { $_attributes, $error, \&setInitiatorAttribute, $showset); } +sub setAluaAttributes { + my $attributes = shift; + my $showset = shift; + + my $error = "\t-> WARNING: no settable ALUA attribute '%s', ignoring.\n\n"; + + my ($_attributes, $errorString) = $SCST->aluaAttributes(); + + return TRUE if issueWarning($errorString); + + return setAttributes(undef, undef, undef, undef, $attributes, + $_attributes, $error, \&setAluaAttribute, $showset); +} + +sub setAluaAttribute { + shift; + shift; + shift; + shift; + my $attribute = shift; + my $value = shift; + + print "\t-> Setting ALUA attribute '$attribute' to value '$value': "; + my $rc = $SCST->setAluaAttribute($attribute, $value); + print "done.\n"; + + return $rc; +} + sub setDeviceGroupAttributes { my $group = shift; my $attributes = shift; @@ -3929,9 +4018,9 @@ sub setDeviceGroupAttributes { my $error = "\t-> WARNING: Device Group '$group' lacks the settable attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->deviceGroupAttributes($group); + my ($_attributes, $errorString) = $SCST->deviceGroupAttributes($group); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, undef, undef, $group, $attributes, $_attributes, $error, \&setDeviceGroupAttribute, $showset); @@ -3962,9 +4051,9 @@ sub setTargetGroupAttributes { my $error = "\t-> WARNING: Target Group '$group/$tgroup' lacks the settable attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->targetGroupAttributes($group, $tgroup); + my ($_attributes, $errorString) = $SCST->targetGroupAttributes($group, $tgroup); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, undef, $group, $tgroup, $attributes, $_attributes, $error, \&setTargetGroupAttribute, $showset); @@ -3996,9 +4085,9 @@ sub setTargetGroupTargetAttributes { my $error = "\t-> WARNING: Target '$group/$tgroup/$tgt' lacks the settable attribute '%s', ignoring.\n\n"; - my $_attributes = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt); + my ($_attributes, $errorString) = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt, TRUE); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); return setAttributes(undef, $group, $tgroup, $tgt, $attributes, $_attributes, $error, \&setTargetGroupTargetAttribute, $showset); @@ -4098,9 +4187,9 @@ sub setDriverAttributes { my $changes = 0; my $driverCap = $SCST->driverIsVirtualCapable($driver); - my $_attributes = $SCST->driverAttributes($driver); + my ($_attributes, $errorString) = $SCST->driverAttributes($driver); - return 0 if issueWarning($SCST->errorString()); + return 0 if issueWarning($errorString); # build caches for easier matching foreach my $attribute (keys %{$attributes}) { @@ -4171,9 +4260,9 @@ sub addDriverDynamicAttributes { my $driver = shift; my $attributes = shift; - my $_attributes = $SCST->driverAttributes($driver); + my ($_attributes, $errorString) = $SCST->driverAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); my $existing = cacheAttributes($_attributes); @@ -4199,7 +4288,7 @@ sub addDriverDynamicAttribute { my $rc = $SCST->addDriverDynamicAttribute($driver, $attribute, $value); print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4208,9 +4297,9 @@ sub removeDriverDynamicAttributes { my $driver = shift; my $attributes = shift; - my $_attributes = $SCST->driverAttributes($driver); + my ($_attributes, $errorString) = $SCST->driverAttributes($driver); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); my $existing = cacheAttributes($_attributes); @@ -4238,7 +4327,7 @@ sub removeDriverDynamicAttribute { my $rc = $SCST->removeDriverDynamicAttribute($driver, $attribute, $value); print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4260,7 +4349,7 @@ sub setTargetAttribute { my $rc = $SCST->setTargetAttribute($driver, $target, $attribute, $value); print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4274,9 +4363,9 @@ sub setTargetAttributes { my $changes = 0; my $driverCap = $SCST->driverIsVirtualCapable($driver); - my $_attributes = $SCST->targetAttributes($driver, $target); + my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target); - return 0 if issueWarning($SCST->errorString()); + return 0 if issueWarning($errorString); # build caches for easier matching foreach my $attribute (keys %{$attributes}) { @@ -4350,9 +4439,9 @@ sub addTargetDynamicAttributes { my $target = shift; my $attributes = shift; - my $_attributes = $SCST->targetAttributes($driver, $target); + my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); my $existing = cacheAttributes($_attributes); @@ -4381,7 +4470,7 @@ sub addTargetDynamicAttribute { my $rc = $SCST->addTargetDynamicAttribute($driver, $target, $attribute, $value); print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4391,9 +4480,9 @@ sub removeTargetDynamicAttributes { my $target = shift; my $attributes = shift; - my $_attributes = $SCST->targetAttributes($driver, $target); + my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target); - return TRUE if issueWarning($SCST->errorString()); + return TRUE if issueWarning($errorString); my $existing = cacheAttributes($_attributes); @@ -4423,7 +4512,7 @@ sub removeTargetDynamicAttribute { my $rc = $SCST->removeTargetDynamicAttribute($driver, $target, $attribute, $value); print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4441,7 +4530,7 @@ sub openDevice { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4451,7 +4540,7 @@ sub closeDevice { my $device = shift; my $force = shift; - my $attributes = $SCST->deviceAttributes($device); + my ($attributes, $errorString) = $SCST->deviceAttributes($device); if (!$force) { if (keys %{$$attributes{'exported'}}) { @@ -4467,7 +4556,7 @@ sub closeDevice { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4490,7 +4579,7 @@ sub addDeviceGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4505,7 +4594,7 @@ sub addTargetGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4521,7 +4610,7 @@ sub addTargetGroupTarget { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4531,8 +4620,8 @@ sub removeDeviceGroup { my $force = shift; if (!$force) { - my $devices = $SCST->deviceGroupDevices($group); - my $tgroups = $SCST->targetGroups($group); + my ($devices, $errorString) = $SCST->deviceGroupDevices($group); + my ($tgroups, $errorString) = $SCST->targetGroups($group); if (($#{$devices} > -1) || ($#{$tgroups} > -1)) { print "\n"; @@ -4547,7 +4636,7 @@ sub removeDeviceGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4558,7 +4647,7 @@ sub removeTargetGroup { my $force = shift; if (!$force) { - my $tgts = $SCST->targetGroupTargets($group, $tgroup); + my ($tgts, $errorString) = $SCST->targetGroupTargets($group, $tgroup); if ($#{$tgts} > -1) { print "\n"; @@ -4573,7 +4662,7 @@ sub removeTargetGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4590,7 +4679,7 @@ sub removeTargetGroupTarget { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4605,7 +4694,7 @@ sub addDeviceGroupDevice { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4617,10 +4706,10 @@ sub removeDeviceGroupDevice { if (!$force) { my $found = FALSE; - my $tgroups = $SCST->targetGroups($group); + my ($tgroups, $errorString) = $SCST->targetGroups($group); foreach my $tgroup (@{$tgroups}) { - my $targets = $SCST->targetGroupTargets($group, $tgroup); + my ($targets, $errorString) = $SCST->targetGroupTargets($group, $tgroup); if ($#{$targets} > -1) { print "\n"; @@ -4640,7 +4729,7 @@ sub removeDeviceGroupDevice { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4658,7 +4747,7 @@ sub addGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4670,8 +4759,8 @@ sub removeGroup { my $force = shift; if (!$force) { - my $luns = $SCST->luns($driver, $target, $group); - my $initiators = $SCST->initiators($driver, $target, $group); + my ($luns, $errorString) = $SCST->luns($driver, $target, $group); + my ($initiators, $errorString) = $SCST->initiators($driver, $target, $group); if ((keys %{$luns}) || ($#{$initiators} > -1)) { listGroup($driver, $target, $group, $luns, $initiators); @@ -4685,7 +4774,7 @@ sub removeGroup { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4719,7 +4808,7 @@ sub addInitiator { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4737,7 +4826,7 @@ sub removeInitiator { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4755,7 +4844,7 @@ sub moveInitiator { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4771,7 +4860,7 @@ sub clearInitiators { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4798,7 +4887,7 @@ sub addLun { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4821,7 +4910,7 @@ sub removeLun { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4841,7 +4930,7 @@ sub replaceLun { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4861,7 +4950,7 @@ sub clearLuns { print "done.\n"; - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); return FALSE; } @@ -4873,8 +4962,8 @@ sub clearDriverDynamicAttributes { print "\t-> Removing all dynamic attributes from driver '$driver': "; - my $attributes = $SCST->driverAttributes($driver); - my $dynamic = $SCST->driverDynamicAttributes($driver); + my ($attributes, $errorString) = $SCST->driverAttributes($driver); + my ($dynamic, $errorString) = $SCST->driverDynamicAttributes($driver); foreach my $attribute (keys %{$attributes}) { if (defined($$dynamic{$attribute})) { @@ -4883,7 +4972,7 @@ sub clearDriverDynamicAttributes { my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'}; my $rc = $SCST->removeDriverDynamicAttribute($driver, $attribute, $value); - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); } } } @@ -4902,8 +4991,8 @@ sub clearTargetDynamicAttributes { print "\t-> Removing all dynamic attributes from driver/target '$driver/$target': "; - my $attributes = $SCST->targetAttributes($driver, $target); - my $dynamic = $SCST->targetDynamicAttributes($driver); + my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target); + my ($dynamic, $errorString) = $SCST->targetDynamicAttributes($driver); foreach my $attribute (keys %{$attributes}) { if (defined($$dynamic{$attribute})) { @@ -4912,7 +5001,7 @@ sub clearTargetDynamicAttributes { my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'}; my $rc = $SCST->removeTargetDynamicAttribute($driver, $target, $attribute, $value); - immediateExit($SCST->errorString($rc)) if ($rc); + condExit($SCST->errorString($rc)); } } } @@ -4949,7 +5038,7 @@ sub enableDriver { my $driver = shift; my %attributes = ('enabled', 1); - my $attrs = $SCST->driverAttributes($driver); + my ($attrs, $errorString) = $SCST->driverAttributes($driver); return TRUE if (!defined($$attrs{'enabled'})); return setDriverAttributes($driver, \%attributes); @@ -4959,7 +5048,7 @@ sub disableDriver { my $driver = shift; my %attributes = ('enabled', 0); - my $attrs = $SCST->driverAttributes($driver); + my ($attrs, $errorString) = $SCST->driverAttributes($driver); return TRUE if (!defined($$attrs{'enabled'})); return setDriverAttributes($driver, \%attributes); @@ -4973,10 +5062,10 @@ sub issueLip { if (defined($driver) && defined($target)) { return _issueLip($driver, $target, $warn); } else { - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); foreach my $driver(@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { my $rc = _issueLip($driver, $target, $warn); @@ -4995,7 +5084,7 @@ sub _issueLip { my $warn = shift; my $rc = FALSE; - my $attributes = $SCST->targetAttributes($driver, $target); + my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target); if (!defined($$attributes{'host'}) && $warn) { print "\t-> Driver/target '$driver/$target' has no 'host' attribute, ignoring.\n"; @@ -5244,7 +5333,7 @@ sub readOldConfigFile { } } - my $drivers = $SCST->drivers(); + my ($drivers, $errorString) = $SCST->drivers(); my %added_targets; # Handle default groups @@ -5256,7 +5345,7 @@ sub readOldConfigFile { my($device, $lun) = split(/\,/, $device); foreach my $driver (@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { $new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'LUN'}->{$lun}->{$device} = {}; @@ -5269,7 +5358,7 @@ sub readOldConfigFile { my $found_t = FALSE; # Find the associated target foreach my $driver (@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { if ($target eq $group_t) { @@ -5310,7 +5399,7 @@ sub readOldConfigFile { addAllGroupsToTarget(\%config, \%new, $driver, $target); $has_enabled = TRUE; } else { - immediateExit("Unable to determine target driver information for target '$wwn'. ". + condExit("Unable to determine target driver information for target '$wwn'. ". "Please ensure this target driver is loaded."); } } @@ -5321,7 +5410,7 @@ sub readOldConfigFile { # Fill in with known targets, all disabled. foreach my $driver (@{$drivers}) { - my $targets = $SCST->targets($driver); + my ($targets, $errorString) = $SCST->targets($driver); foreach my $target (@{$targets}) { addAllGroupsToTarget(\%config, \%new, $driver, $target); @@ -5340,7 +5429,7 @@ sub readOldConfigFile { foreach my $driver (keys %{$new{'TARGET_DRIVER'}}) { next if ($driver =~ /^qla/); - my $attributes = $SCST->driverAttributes($driver); + my ($attributes, $errorString) = $SCST->driverAttributes($driver); if (defined($$attributes{'enabled'})) { $new{'TARGET_DRIVER'}->{$driver}->{'enabled'}->{'1'} = {}; @@ -5516,6 +5605,19 @@ sub immediateExit { exit 1; } +# If an error occurred, exit if -cont_on_err has not been specified. +sub condExit { + my $error = shift; + + if (!$error) { + ; + } elsif ($_CONT_ON_ERR_) { + print "$error\n"; + } else { + immediateExit($error); + } +} + sub issueWarning { my $error = shift;