CasperSecurity

Current Path : /usr/lib/open-iscsi/
Upload File :
Current File : //usr/lib/open-iscsi/umountiscsi.sh

#!/bin/sh
#
# This script umounts mounted iSCSI devices on shutdown, if possible.
# It is supposed to catch most use cases but is not designed to work
# for every corner-case. It handles LVM and multipath, but only if
# one of the following stackings is used:
#   LVM -> multipath -> iSCSI
#   multipath -> iSCSI
#   LVM -> iSCSI
#   LVM -> LUKS -> multipath -> iSCSI
#   LVM -> LUKS -> iSCSI
#   LUKS -> LVM -> multipath -> iSCSI
#   LUKS -> multipath -> iSCSI
#   LUKS -> LVM -> iSCSI
#   LUKS -> iSCSI
# It does not try to umount anything belonging to any device that is
# also used as a backing store for the root filesystem. Any iSCSI
# device part of the backing store of the root filesystem will be noted
# in /run/open-iscsi/shutdown-keep-sessions, so that the session not be
# closed on shutdown.
#
# KNOWN ISSUES:
#    - It doesn't handle submounts properly in all corner cases.
#      Specifically, it doesn't handle a non-iSCSI mount below an
#      iSCSI mount if it isn't also marked _netdev in /etc/fstab.
#    - It does not handle other things device mapper can do, such as
#      RAID, crypto, manual mappings of parts of disks, etc.
#    - It doesn't try to kill programs still accessing those mounts,
#      umount will just fail then.
#    - It doesn't handle more complicated stackings such as overlayfs,
#      FUSE filesystems, loop devices, etc.
#    - It doesn't handle swap.
#
# LONG TERM GOAL:
#    - In the long term, there should be a solution where for each part
#      of the stacking (device mapper, LVM, overlayfs, etc.) explicit
#      depdendencies are declared with the init system such that it can
#      be automatically dismantled. That would make this script
#      superfluous and also not be a layering violation, as it
#      currently is.
#
# CODING CHOICES:
#    - On systems running sysvinit, this script might be called without
#      /usr being mounted, so a lot of very useful commands are not
#      available: head, tail, stat, awk, etc. This makes the script
#      quite ugly at places, but that can't be avoided.
#
# Author: Christian Seiler <christian@iwakd.de>
#

# Make sure we don't include /usr in our path, else future modifications
# to this script might accidentally use something from there and cause
# failure on separate-/usr sysvinit systems that isn't immediately
# noticed.
PATH=/sbin:/bin

EXCLUDE_MOUNTS_AT_SHUTDOWN=""
if [ -f /etc/default/open-iscsi ]; then
	. /etc/default/open-iscsi
fi

MULTIPATH=/sbin/multipath
PVS=/sbin/pvs
LVS=/sbin/lvs
VGS=/sbin/vgs
VGCHANGE=/sbin/vgchange
CRYPTSETUP=/sbin/cryptsetup
DMSETUP=/sbin/dmsetup

if [ -x $PVS ] && [ -x $LVS ] && [ -x $VGCHANGE ] ; then
	HAVE_LVM=1
else
	HAVE_LVM=0
fi
if [ -x $CRYPTSETUP ] && [ -x $DMSETUP ] ; then
	HAVE_LUKS=1
else
	HAVE_LUKS=0
fi

DRY_RUN=0

# We need to make sure that we don't try to umount the root device
# and for systemd systems, also /usr (which is pre-mounted in initrd
# there).
EXCLUDE_MOUNTS="/"
if [ -d /run/systemd/system ] ; then
        EXCLUDE_MOUNTS="$EXCLUDE_MOUNTS /usr"
fi
EXCLUDE_MOUNTS="${EXCLUDE_MOUNTS}${EXCLUDE_MOUNTS_AT_SHUTDOWN+ $EXCLUDE_MOUNTS_AT_SHUTDOWN}"
unset _EXCLUDE_MOUNTS

error_usage() {
	echo "Usage: $0 [--dry-run | --timeout secs]" >&2
	exit 1
}

timeout=0

if [ $# -gt 2 ] ; then
	error_usage
fi

if [ $# -eq 2 ] ; then
	if [ x"$1"x != x"--timeout"x ] ; then
		error_usage
	fi
	case "$2" in
		(-1)            timeout="$2" ;;
		(*[!0-9]*|"")   error_usage ;;
		(*)             timeout="$2" ;;
	esac
elif [ $# -eq 1 ] ; then
	if [ x"$1"x != x"--dry-run"x ] ; then
		error_usage
	fi
	DRY_RUN=1
fi

# poor man's hash implementation using shell variables
hash_keys() {
	_hash_keys_hash_key_prefix="${1}_"
	(
		IFS='='
		set | while read var value ; do
			if [ x"${var#$_hash_keys_hash_key_prefix}"x != x"${var}"x ] ; then
				printf '%s\n' "${var#$_hash_keys_hash_key_prefix}"
			fi
		done
	)
}


hash_clear() {
	for k in $(hash_keys "$1") ; do
		unset "${1}_${k}"
	done
}

hash_get() {
	_hash_get_var="$2_$(printf '%s' "$3" | sed 's%[^A-Za-z0-9_]%_%g')"
	eval _hash_get_value=\$${_hash_get_var}
	eval $1=\${_hash_get_value}
}

hash_set() {
	_hash_set_var="$1_$(printf '%s' "$2" | sed 's%[^A-Za-z0-9_]%_%g')"
	eval ${_hash_set_var}=\${3}
}

hash_unset() {
	_hash_set_var="$1_$(printf '%s' "$2" | sed 's%[^A-Za-z0-9_]%_%g')"
	unset ${_hash_set_var}
}

in_set() {
	eval _set=\$$1
	case "${_set}" in
		("$2"|*" $2"|"$2 "*|*" $2 "*) return 0 ;;
		(*)                           return 1 ;;
	esac
}

_add_to_set() {
	eval _set=\$$1
	case "${_set}" in
		("$2"|*" $2"|"$2 "*|*" $2 "*) ;;
		("")    _set="$2" ;;
		(*)     _set="${_set} $2" ;;
	esac
	eval $1=\${_set}
}

add_to_set() {
	_add_to_set_set="$1"
	shift
	for _add_to_set_val in "$@" ; do
		_add_to_set "${_add_to_set_set}" "${_add_to_set_val}"
	done
}

hash_add_to_set() {
	_hash_add_to_set_var="$1_$(printf '%s' "$2" | sed 's%[^A-Za-z0-9_]%_%g')"
	shift
	shift
	add_to_set "${_hash_add_to_set_var}" "$@"
}

device_majmin() {
	eval $1=\"\"
	_majmin_dec=$(LC_ALL=C ls -lnd /dev/"$2" | while read _perms _links _uid _gid _majcomma _min _rest ; do
		if [ x"${_majcomma%,}"x != x"${_majcomma}"x ] ; then
			printf '%s' ${_majcomma%,}:${_min}
		fi
		break
	done)
	[ -n "${_majmin_dec}" ] || return
	eval $1=\${_majmin_dec}
}

get_lvm_vgs() {
	# handle the case where we didn't get passed any PVs
	# at all
	[ $# -gt 0 ] || return 0
	# subshell for pwd change
	(
		cd /dev
		$PVS --noheadings -o vg_name "$@" 2>/dev/null
	)
}

enumerate_luks() {
	hash_clear LUKS_DEVICES_REVERSE_MAP

	_all_crypt_devices=$($DMSETUP info --noheadings -o name -c -S subsystem=CRYPT 2>/dev/null || :)
	for _crypt_device in ${_all_crypt_devices} ; do
		[ -b "/dev/mapper/${_crypt_device}" ] || continue
		_crypt_device="$(readlink -fe "/dev/mapper/${_crypt_device}" 2>/dev/null || :)"
		_crypt_device="${_crypt_device#/dev/}"
		[ -b "/dev/${_crypt_device}" ] || continue
		# dmsetup deps is weird, it outputs the following:
		# 1 dependencies : (XYZ)
		_dep=$($DMSETUP deps -o blkdevname "/dev/${_crypt_device}" | sed -n '1s%.*: (\(.*\)).*%\1%p')
		if [ -n "$_dep" ] && [ -b "/dev/${_dep}" ] ; then
			_dep="$(readlink -fe "/dev/$_dep" 2>/dev/null || :)"
			_dep="${_dep#/dev/}"
		fi
		if [ -n "$_dep" ] && [ -b "/dev/${_dep}" ] ; then
			hash_set LUKS_DEVICES_REVERSE_MAP "${_dep}" "${_crypt_device}"
		fi
	done
}

enumerate_iscsi_devices() {
	# Empty arrays
	iscsi_disks=""
	iscsi_partitions=""
	iscsi_multipath_disks=""
	iscsi_multipath_disk_aliases=""
	iscsi_multipath_partitions=""
	iscsi_lvm_vgs=""
	iscsi_lvm_lvs=""
	iscsi_potential_mount_sources=""
	iscsi_luks_pass1=""
	iscsi_luks_pass2=""

	hash_clear ISCSI_DEVICE_SESSIONS
	hash_clear ISCSI_MPALIAS_SESSIONS
	hash_clear ISCSI_LVMVG_SESSIONS
	hash_clear ISCSI_NUMDEVICE_SESSIONS
	ISCSI_EXCLUDED_SESSIONS=""

	# We first need to generate a global reverse mapping of all
	# cryptsetup (e.g. LUKS) devices, because there's no easy way
	# to query "is this the encrypted backing of an active crypto
	# mapping?
	enumerate_luks

	# Look for all iscsi disks
	for _host_dir in /sys/devices/platform/host* /sys/devices/pci*/*/*/host* ; do
		if ! [ -d "$_host_dir"/iscsi_host* ] || ! [ -d "$_host_dir"/iscsi_host/host* ] ; then
			continue
		fi
		for _session_dir in "$_host_dir"/session* ; do
			[ -d "$_session_dir"/target* ] || continue
			for _block_dev_dir in "$_session_dir"/target*/*\:*/block/* ; do
				_block_dev=${_block_dev_dir##*/}
				[ x"${_block_dev}"x != x"*"x ] || continue
				add_to_set iscsi_disks "${_block_dev}"
				hash_add_to_set ISCSI_DEVICE_SESSIONS "${_block_dev}" ${_session_dir}
			done
		done
	done

	# Look for all partitions on those disks
	for _disk in $iscsi_disks ; do
		hash_get _disk_sessions ISCSI_DEVICE_SESSIONS "${_disk}"
		for _part_dir in /sys/class/block/"${_disk}"/"${_disk}"?* ; do
			_part="${_part_dir##*/}"
			[ x"${_part}"x != x"${_disk}?*"x ] || continue
			add_to_set iscsi_partitions "${_part}"
			hash_set ISCSI_DEVICE_SESSIONS "${_part}" "${_disk_sessions}"
		done
	done

	if [ -x $MULTIPATH ] ; then
		# Look for all multipath disks
		for _disk in $iscsi_disks ; do
			hash_get _disk_sessions ISCSI_DEVICE_SESSIONS "${_disk}"
			for _alias in $($MULTIPATH -v1 -l /dev/"$_disk") ; do
				_mp_dev="$(readlink -fe "/dev/mapper/${_alias}" || :)"
				[ -n "${_mp_dev}" ] || continue
				add_to_set iscsi_multipath_disks "${_mp_dev#/dev/}"
				add_to_set iscsi_multipath_disk_aliases "${_alias}"
				hash_add_to_set ISCSI_DEVICE_SESSIONS "${_mp_dev#/dev/}" ${_disk_sessions}
				hash_add_to_set ISCSI_MPALIAS_SESSIONS "${_alias}" ${_disk_sessions}
			done
		done

		# Look for partitions on these multipath disks
		for _alias in $iscsi_multipath_disk_aliases ; do
			hash_get _mp_sessions ISCSI_MPALIAS_SESSIONS "${_alias}"
			for _part_name in /dev/mapper/"${_alias}"-part* ; do
				_part="$(readlink -fe "$_part_name" 2>/dev/null || :)"
				[ -n "${_part}" ] || continue
				add_to_set iscsi_multipath_partitions "${_part#/dev/}"
				hash_set ISCSI_DEVICE_SESSIONS "${_part#/dev/}" "${_mp_sessions}"
			done
		done
	fi

	if [ $HAVE_LUKS -eq 1 ] ; then
		# Look for all LUKS devices.
		for _dev in $iscsi_disks $iscsi_partitions $iscsi_multipath_disks $iscsi_multipath_partitions ; do
			hash_get _luksDev LUKS_DEVICES_REVERSE_MAP "${_dev}"
			[ -n "${_luksDev}" ] || continue
			add_to_set iscsi_luks_pass1 "${_luksDev}"
			hash_get _currentSession ISCSI_DEVICE_SESSIONS "${_dev}"
			if [ -n "${_currentSession}" ] ; then
				hash_set ISCSI_DEVICE_SESSIONS "${_luksDev}" "${_currentSession}"
			fi
		done
	fi

	if [ $HAVE_LVM -eq 1 ] ; then
		# Look for all LVM volume groups that have a backing store
		# on any iSCSI device we found. Also, add $LVMGROUPS set in
		# /etc/default/open-iscsi (for more complicated stacking
		# configurations we don't automatically detect).
		for _vg in $(get_lvm_vgs $iscsi_disks $iscsi_partitions $iscsi_multipath_disks $iscsi_multipath_partitions $iscsi_luks_pass1) $LVMGROUPS ; do
			add_to_set iscsi_lvm_vgs "$_vg"
		done

		# $iscsi_lvm_vgs is now unique list
		for _vg in $iscsi_lvm_vgs ; do
			# get PVs to track iSCSI sessions
			for _pv in $($VGS --noheadings -o pv_name "$_vg" 2>/dev/null) ; do
				_pv_dev="$(readlink -fe "$_pv" 2>/dev/null || :)"
				[ -n "${_pv_dev}" ] || continue
				hash_get _pv_sessions ISCSI_DEVICE_SESSIONS "${_pv_dev#/dev/}"
				hash_add_to_set ISCSI_LVMVG_SESSIONS "${_vg}" ${_pv_sessions}
			done

			# now we collected all sessions belonging to this VG
			hash_get _vg_sessions ISCSI_LVMVG_SESSIONS "${_vg}"

			# find all LVs
			for _lv in $($VGS --noheadings -o lv_name "$_vg" 2>/dev/null) ; do
				_dev="$(readlink -fe "/dev/${_vg}/${_lv}" 2>/dev/null || :)"
				[ -n "${_dev}" ] || continue
				iscsi_lvm_lvs="$iscsi_lvm_lvs ${_dev#/dev/}"
				hash_set ISCSI_DEVICE_SESSIONS "${_dev#/dev/}" "${_vg_sessions}"
			done
		done
	fi

	if [ $HAVE_LUKS -eq 1 ] ; then
		# Look for all LUKS devices.
		for _dev in $iscsi_lvm_lvs ; do
			hash_get _luksDev LUKS_DEVICES_REVERSE_MAP "${_dev}"
			[ -n "${_luksDev}" ] || continue
			add_to_set iscsi_luks_pass2 "${_luksDev}"
			hash_get _currentSession ISCSI_DEVICE_SESSIONS "${_dev}"
			if [ -n "${_currentSession}" ] ; then
				hash_set ISCSI_DEVICE_SESSIONS "${_luksDev}" "${_currentSession}"
			fi
		done
	fi

	# Gather together all mount sources
	iscsi_potential_mount_sources="$iscsi_potential_mount_sources $iscsi_disks $iscsi_partitions"
	iscsi_potential_mount_sources="$iscsi_potential_mount_sources $iscsi_multipath_disks $iscsi_multipath_partitions"
	iscsi_potential_mount_sources="$iscsi_potential_mount_sources $iscsi_lvm_lvs"
	iscsi_potential_mount_sources="$iscsi_potential_mount_sources $iscsi_luks_pass1 $iscsi_luks_pass2"

	# Convert them to numerical representation
	iscsi_potential_mount_sources_majmin=""
	for _src in $iscsi_potential_mount_sources ; do
		device_majmin _src_majmin "$_src"
		[ -n "$_src_majmin" ] || continue
		iscsi_potential_mount_sources_majmin="${iscsi_potential_mount_sources_majmin} ${_src_majmin}"
		hash_get _dev_sessions ISCSI_DEVICE_SESSIONS "${_src}"
		hash_set ISCSI_NUMDEVICE_SESSIONS "${_src_majmin}" "${_dev_sessions}"
	done

	# Enumerate mount points
	iscsi_mount_points=""
	iscsi_mount_point_ids=""
	while read _mpid _mppid _mpdev _mpdevpath _mppath _mpopts _other ; do
		if in_set iscsi_potential_mount_sources_majmin "$_mpdev" ; then
			if in_set EXCLUDE_MOUNTS "${_mppath}" ; then
				hash_get _dev_sessions ISCSI_NUMDEVICE_SESSIONS "${_mpdev}"
				add_to_set ISCSI_EXCLUDED_SESSIONS $_dev_sessions
				continue
			fi
			# list mountpoints in reverse order (in case
			# some are stacked) mount --move may cause the
			# order of /proc/self/mountinfo to not always
			# reflect the stacking order, so this is not
			# fool-proof, but it's better than nothing
			iscsi_mount_points="$_mppath $iscsi_mount_points"
			iscsi_mount_point_ids="$_mpid $iscsi_mount_points"
		fi
	done < /proc/self/mountinfo
}

try_umount() {
	# in order to handle stacking try twice; together with the fact
	# that the list of mount points is in reverse order of the
	# contents /proc/self/mountinfo this should catch most cases
	for retry in 1 2 ; do
		for path in $iscsi_mount_points ; do
			# first try to see if it really is a mountpoint
			# still (might be the second round this is done
			# and the mount is already gone, or something
			# else umounted it first)
			if ! fstab-decode mountpoint -q "$path" ; then
				continue
			fi

			# try to umount it
			if ! fstab-decode umount "$path" ; then
				# unfortunately, umount's exit code
				# may be a false negative, i.e. it
				# might give a failure exit code, even
				# though it succeeded, so check again
				if fstab-decode mountpoint -q "$path" ; then
					echo "Could not unmount $path" >&2
					any_umount_failed=1
				fi
			fi
		done
	done
}

try_deactivate_lvm() {
	[ $HAVE_LVM -eq 1 ] || return

	for vg in $iscsi_lvm_vgs ; do
		vg_excluded=0
		hash_get vg_sessions ISCSI_LVMVG_SESSIONS "$vg"
		for vg_session in $vg_sessions ; do
			if in_set ISCSI_EXCLUDED_SESSIONS "$vg_session" ; then
				vg_excluded=1
			fi
		done
		if [ $vg_excluded -eq 1 ] ; then
			# volume group on same iSCSI session as excluded
			# mount, don't disable it
			# (FIXME: we should only exclude VGs that contain
			# those mounts, not also those that happen to be
			# in the same iSCSI session)
			continue
		fi
		if ! $VGCHANGE --available=n $vg ; then
			# Make sure the volume group (still) exists. If
			# it doesn't we count that as deactivated, so
			# don't fail then.
			_vg_test=$(vgs -o vg_name --noheadings $vg 2>/dev/null || :)
			if [ -n "${_vg_test}" ] ; then
				echo "Cannot deactivate Volume Group $vg" >&2
				any_umount_failed=1
			fi
		fi
	done
}

try_dismantle_multipath() {
	[ -x $MULTIPATH ] || return

	for mpalias in $iscsi_multipath_disk_aliases ; do
		mp_excluded=0
		hash_get mp_sessions ISCSI_MPALIAS_SESSIONS "$mpalias"
		for mp_session in $mp_sessions ; do
			if in_set ISCSI_EXCLUDED_SESSIONS "$mp_session" ; then
				mp_excluded=1
			fi
		done
		if [ $mp_excluded -eq 1 ] ; then
			# multipath device on same iSCSI session as
			# excluded mount, don't disable it
			# (FIXME: we should only exclude multipath mounts
			# that contain those mounts, not also those that
			# happen to be in the same iSCSI session)
			continue
		fi
		if ! $MULTIPATH -f $mpalias ; then
			echo "Cannot dismantle Multipath Device $mpalias" >&2
			any_umount_failed=1
		fi
	done
}

try_dismantle_luks() {
	[ $HAVE_LUKS -eq 1 ] || return
	case "$1" in
	1)	iscsi_luks_current_pass="$iscsi_luks_pass1" ;;
	2|*)	iscsi_luks_current_pass="$iscsi_luks_pass2" ;;
	esac

	for luksDev in $iscsi_luks_current_pass ; do
		luks_excluded=0
		hash_get device_sessions ISCSI_DEVICE_SESSIONS "$luksDev"
		for device_session in $device_sessions ; do
			if in_set ISCSI_EXCLUDED_SESSIONS "$device_session" ; then
				luks_excluded=1
			fi
		done
		if [ $luks_excluded -eq 1 ] ; then
			continue
		fi
		_luksName="$($DMSETUP info -c --noheadings -o name /dev/"$luksDev" 2>/dev/null || :)"
		[ -n "${_luksName}" ] || continue
		if ! $CRYPTSETUP close "${_luksName}" ; then
			echo "Cannot dismantle cryptsetup device ${_luksName}" >&2
			any_umount_failed=1
		fi
	done
}

# Don't do this if we are using systemd as init system, since systemd
# takes care of network filesystems (including those marked _netdev) by
# itself.
if ! [ -d /run/systemd/system ] && [ $HANDLE_NETDEV -eq 1 ] && [ $DRY_RUN -eq 0 ]; then
	echo "Unmounting all devices marked _netdev";
	umount -a -O _netdev >/dev/null 2>&1
fi

enumerate_iscsi_devices

# Dry run? Just print what we want to do (useful for administrator to check).
if [ $DRY_RUN -eq 1 ] ; then
	echo "$0: would umount the following mount points:"
	had_mount=0
	if [ -n "$iscsi_mount_points" ] ; then
		for v in $iscsi_mount_points ; do
			echo "  $v"
			had_mount=1
		done
	fi
	[ $had_mount -eq 1 ] || echo "  (none)"

	echo "$0: would disable the following LUKS devices (second pass):"
	had_luks=0
	if [ -n "$iscsi_luks_pass2" ] ; then
		for v in ${iscsi_luks_pass2} ; do
			luks_excluded=0
			hash_get device_sessions ISCSI_DEVICE_SESSIONS "$v"
			for device_session in $device_sessions ; do
				if in_set ISCSI_EXCLUDED_SESSIONS "$device_session" ; then
					luks_excluded=1
				fi
			done
			if [ $luks_excluded -eq 1 ] ; then
				continue
			fi
			_luksName="$($DMSETUP info -c --noheadings -o name /dev/"$v" 2>/dev/null || :)"
			[ -n "${_luksName}" ] || continue
			echo "  ${_luksName}"
			had_luks=1
		done
	fi
	[ $had_luks -eq 1 ] || echo "  (none)"

	echo "$0: would deactivate the following LVM Volume Groups:"
	had_vg=0
	if [ -n "$iscsi_lvm_vgs" ] ; then
		for v in $iscsi_lvm_vgs ; do
			# sync this exclusion logic with try_deactivate_lvm
			vg_excluded=0
			hash_get vg_sessions ISCSI_LVMVG_SESSIONS "$v"
			for vg_session in $vg_sessions ; do
				if in_set ISCSI_EXCLUDED_SESSIONS "$vg_session" ; then
					vg_excluded=1
				fi
			done
			if [ $vg_excluded -eq 1 ] ; then
				continue
			fi
			echo "  $v"
			had_vg=1
		done
	fi
	[ $had_vg -eq 1 ] || echo "  (none)"

	echo "$0: would disable the following LUKS devices (first pass):"
	had_luks=0
	if [ -n "$iscsi_luks_pass1" ] ; then
		for v in ${iscsi_luks_pass1} ; do
			luks_excluded=0
			hash_get device_sessions ISCSI_DEVICE_SESSIONS "$v"
			for device_session in $device_sessions ; do
				if in_set ISCSI_EXCLUDED_SESSIONS "$device_session" ; then
					luks_excluded=1
				fi
			done
			if [ $luks_excluded -eq 1 ] ; then
				continue
			fi
			_luksName="$($DMSETUP info -c --noheadings -o name /dev/"$v" 2>/dev/null || :)"
			[ -n "${_luksName}" ] || continue
			echo "  ${_luksName}"
			had_luks=1
		done
	fi
	[ $had_luks -eq 1 ] || echo "  (none)"

	echo "$0: would deactivate the following multipath volumes:"
	had_mp=0
	if [ -n "$iscsi_multipath_disk_aliases" ] ; then
		for v in $iscsi_multipath_disk_aliases ; do
			# sync this exclusion logic with try_dismantle_multipath
			mp_excluded=0
			hash_get mp_sessions ISCSI_MPALIAS_SESSIONS "$v"
			for mp_session in $mp_sessions ; do
				if in_set ISCSI_EXCLUDED_SESSIONS "$mp_session" ; then
					mp_excluded=1
				fi
			done
			if [ $mp_excluded -eq 1 ] ; then
				continue
			fi
			echo "  $v"
			had_mp=1
		done
	fi
	[ $had_mp -eq 1 ] || echo "  (none)"

	if [ -n "$ISCSI_EXCLUDED_SESSIONS" ] ; then
		echo "$0: the following sessions are excluded from disconnection (because / or another excluded mount is on them):"
		for v in $ISCSI_EXCLUDED_SESSIONS ; do
			echo "  $v"
		done
	fi

	exit 0
fi

# after our first enumeration, write out a list of sessions that
# shouldn't be terminated because excluded mounts are on those
# sessions
if [ -n "$ISCSI_EXCLUDED_SESSIONS" ] ; then
	mkdir -p -m 0700 /run/open-iscsi
	for session in $ISCSI_EXCLUDED_SESSIONS ; do
		printf '%s\n' $session
	done > /run/open-iscsi/shutdown-keep-sessions
else
	# make sure there's no leftover from a previous call
	rm -f /run/open-iscsi/shutdown-keep-sessions
fi

any_umount_failed=0
try_umount
try_dismantle_luks 2
try_deactivate_lvm
try_dismantle_luks 1
try_dismantle_multipath

while [ $any_umount_failed -ne 0 ] && ( [ $timeout -gt 0 ] || [ $timeout -eq -1 ] ) ; do
	# wait a bit, perhaps there was still a program that
	# was terminating
	sleep 1

	# try again and decrease timeout
	enumerate_iscsi_devices
	any_umount_failed=0
	try_umount
	try_dismantle_luks 2
	try_deactivate_lvm
	try_dismantle_luks 1
	try_dismantle_multipath
	if [ $timeout -gt 0 ] ; then
		timeout=$((timeout - 1))
	fi
done

# Create signaling file (might be useful)
if [ $any_umount_failed -eq 1 ] ; then
	touch /run/open-iscsi/some_umount_failed
else
	rm -f /run/open-iscsi/some_umount_failed
fi
exit $any_umount_failed
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY