HEX
Server: Apache/2.4.63 (Unix)
System: Linux TOMS-220NAS 4.4.302+ #86009 SMP Wed Nov 26 18:19:17 CST 2025 x86_64
User: flavio87 (1026)
PHP: 8.3.27
Disabled: NONE
Upload Files
File: //usr/syno/lib/systemd/scripts/volume.sh
#!/bin/sh
# Copyright (c) 2000-2018 Synology Inc. All rights reserved.

# FIXME we only use RCMsg & MsgWarn
. /etc.defaults/rc.subr
source /usr/syno/lib/systemd/scripts/syno-bootup-type-status-check.sh

BIN_MOUNT="/bin/mount"
BIN_SPACETOOL="/usr/syno/bin/spacetool"
BIN_UMOUNT="/bin/umount"
BIN_MKDIR="/bin/mkdir"
BIN_RMDIR="/bin/rmdir"
BIN_MV="/bin/mv"
BIN_RM="/bin/rm"
BIN_CHMOD="/bin/chmod"
BIN_LOGGER="/bin/logger"
BIN_ECHO="/bin/echo"
BIN_GZIP="/bin/gzip"
BIN_GREP="/bin/grep"
BIN_DATE="/bin/date"
BIN_AWK="/bin/awk"
BIN_TOUCH="/bin/touch"
BIN_CUT="/bin/cut"
BIN_CAT="/bin/cat"
BIN_MODPROBE="/sbin/modprobe"
BIN_LOGGER="/bin/logger"
BIN_GETKEYVALUE="/bin/get_key_value"
BIN_SYNOFSTOOL="/usr/syno/bin/synofstool"
BIN_SYNOGETKEYVALUE="/usr/syno/bin/synogetkeyvalue"
BIN_SYNOSETKEYVALUE="/usr/syno/bin/synosetkeyvalue"
BIN_TUNE2FS="/sbin/tune2fs"
BIN_BLKID="/sbin/blkid"
BIN_SYNO_SWAP_CTL="/usr/syno/bin/syno_swap_ctl"
BIN_SYSLOG_NG_SCRIPT="/usr/syno/lib/systemd/scripts/syslog-ng.sh"
BIN_SYNOSTGVOLUME="/usr/syno/sbin/synostgvolume"
BIN_SYNOSPACETOOL="/usr/syno/sbin/synospace"

SYNOINFO="/etc/synoinfo.conf"
SYNOINFO_DEF="/etc.defaults/synoinfo.conf"
PLATFORM=`$BIN_GETKEYVALUE $SYNOINFO_DEF unique | $BIN_CUT -d"_" -f2`
SZF_MANUTIL_VOLUME_SIZE="/.manutil_volume_size"
# Make sure that SZF_TUNEFS_CONF is consistent with volume.h
SZF_TUNEFS_CONF="/usr/syno/etc/.tunefs.conf"
SZF_SYNORBD_RESET_FLAG="/.reset_synorbd"

# $1: path of volume
# $2: filesystem
VolumeQuotaCheck()
{
	local volume= fs= quotacheck=

	[ $# -eq 2 ] || return 1

	volume="$1"
	fs="$2"

	if [ "$fs" = "btrfs" ]; then
		return;
	fi
	if [ ! -f "$volume/aquota.user" ] || [ ! -f "$volume/aquota.group" ]; then
		quotacheck="yes"
	elif [ -f "$volume/.needquotacheck" ]; then
		MsgWarn "Got $volume/.needquotacheck"
		$BIN_RM -f "$volume/.needquotacheck" &> /dev/null
		[ "$fs" = "ext4" ] || quotacheck="yes"
	elif [ -f "$volume/.needquotacheck_upgrade" ]; then
		# .needquotacheck_upgrade created by /etc/upgrade.sh
		MsgWarn "Got $volume/.needquotacheck_upgrade"
		$BIN_RM -f "$volume/.needquotacheck_upgrade" &> /dev/null
		[ "$fs" = "ext4" ] || quotacheck="yes"
	fi

	if [ "$quotacheck" = "yes" ]; then
		RCMsg "Checking quota on $volume" \
		/sbin/quotacheck -g -u -F vfsv0 "$volume"
	fi

	RCMsg "Enabling quota on $volume" \
	/sbin/quotaon -F vfsv0 "$volume"
}

# $1: path of device node
# $2: path of volume
# $3: filesystem (optional)
VolumeRemount()
{
	local devpath= volume= fs= devname= sb=

	[ $# -ge 2 ] || return 1

	devpath="$1"
	volume="$2"
	fs="$3"
	mntopts="$4"
	devname="$($BIN_ECHO $devpath | $BIN_CUT -c6-)"

	# So we can append new mount option by "spacetool --mount $mntoptsOption1,Option2..."
	if [ "$mntopts" == "" ]; then
		mntopts="-o "
	else
		mntopts="$mntopts,"
	fi

	# Handle all btrfs cases here
	if [ "$fs" = "btrfs" ]; then
		# try fix first super block and mount it again
		/sbin/btrfs rescue super-recover -y "$devpath"
		RCMsg "Mounting $devpath:$volume with btrfs super-recover." \
		/usr/syno/bin/spacetool --bootup-mount "$mntopts" "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			return
		fi

		# mount btrfs with drop log tree
		RCMsg "Mounting $devpath:$volume with drop log tree" \
		/usr/syno/bin/spacetool --bootup-mount "$mntopts"drop_log_tree "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			$BIN_ECHO "$volume" >> /run/synostorage/.notify_drop_log_tree
			return
		fi

		# mount btrfs with ro
		RCMsg "Mounting $devpath:$volume with ro." \
		/usr/syno/bin/spacetool --bootup-mount "$mntopts"ro "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			return
		fi

		# mount btrfs with ro,no_block_group
		RCMsg "Mounting $devpath:$volume with ro,no_block_group,nologreplay." \
		/usr/syno/bin/spacetool --bootup-mount "$mntopts"ro,no_block_group,nologreplay "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			return
		fi

		#mount btrfs with ro,recovery
		RCMsg "Mounting $devpath:$volume with ro,recovery." \
		/usr/syno/bin/spacetool --bootup-mount "$mntopts"ro,recovery "$devpath" "$volume"

		return
	fi

	if [ "$fs" = "ext4" ]; then
		# mount ext4 without loading journal
		RCMsg "Mounting $devpath:$volume without loading journal." \
		mount -o ro,noload "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			echo "${devname}mount=\"ro,noload\"" >> /tmp/hdhealth.tmp
			mv -f /tmp/hdhealth.tmp /tmp/hdhealth
			return
		fi
	fi

	if [ "$fs" = "ext4" ] || [ "$fs" = "ext3" ]; then
		mntoptsarray=($mntopts)
		newmntopts=${mntoptsarray[1]}
		# mount ext3/4 backup superblocks
		for sb in 1 131072 393216 655360 917504 1179648 3276800 3538944; do
			$BIN_GREP -v "${devname}mount" /tmp/hdhealth > /tmp/hdhealth.tmp 2>/dev/null

			RCMsg "Mounting read-only on $devpath:$volume. (superblock=$sb)" \
			$BIN_SPACETOOL --bootup-mount -o ro,sb=$sb,"$newmntopts" "$devpath" "$volume"
			if [ $? -eq 0 ]; then
				$BIN_ECHO "${devname}mount=\"ro\"" >> /tmp/hdhealth.tmp
				$BIN_MV -f /tmp/hdhealth.tmp /tmp/hdhealth
				break
			else
				$BIN_ECHO "${devname}mount=\"fail\"" >> /tmp/hdhealth.tmp
				$BIN_MV -f /tmp/hdhealth.tmp /tmp/hdhealth
			fi
		done
	else
		RCMsg "Mounting read-only on $devpath:$volume." \
		$BIN_SPACETOOL --bootup-mount -o ro "$devpath" "$volume"
		if [ $? -eq 0 ]; then
			$BIN_ECHO "${devname}mount=\"ro\"" >> /tmp/hdhealth
		else
			$BIN_ECHO "${devname}mount=\"fail\"" >> /tmp/hdhealth
		fi
	fi
}

EnableCachePinFileFeature()
{
	local vol=$1
	local pin_tool="/usr/syno/sbin/synocachepinfiletool $pin_tool_opt"
	local vol_support_pin="No"
	local is_bitmap_set="No"
	local cache_support_pin=`$BIN_GETKEYVALUE /etc.defaults/synoinfo.conf cache_support_pin`

	if test "$cache_support_pin" != "yes" ; then
		RCMsg "Doesn't support cache pin feature"
		return;
	fi

	# SSD Cache pin file feature
	vol_support_pin=`$pin_tool --mount-path $vol --support-pin`
	is_bitmap_set=`$pin_tool --mount-path $vol --check-bitmap`
	RCMsg "Volume: $vol support_pin: $vol_support_pin Bitmet Set: $is_bitmap_set"
	if test "$vol_support_pin" = "Yes" -a "$is_bitmap_set" = "No" ; then
		$pin_tool --send-bitmap --mount-path $vol
		RCMsg "SSD Cache send bitmap to $vol"
		is_bitmap_set=`$pin_tool --mount-path $vol --check-bitmap`
		RCMsg "Volume: $vol Bitmap Set: $is_bitmap_set"
	fi
}

# Mount device on volume
# $1: path of device node
# $2: path of volume
VolumeMount()
{
	local devpath= volume= mntopts=
	local fs= quotacheck= synoacl= clean=
	local debug_cp=""
	local bl_need_cache_protection_replay_end=false
	local cache_protection_replay_path=

	[ $# -eq 3 ] || return 1

	devpath="$1"
	volume="$2"
	mntopts="$3"

	# determine filesystem
	fs=$($BIN_SYNOFSTOOL --get-fs-type $devpath)
	if [ $? -ne 0 ]; then
		MsgFail "Failed to read filesystem magic on $devpath:$volume. Trying ext4fs."
		fs=ext4
	fi

	# check if cleanly umounted before mounting it
	if [ "$fs" = "ext3" ]; then
		if /sbin/e2fsck -nq $devpath 2> /dev/null | $BIN_GREP -q "is cleanly umounted"; then
			clean="yes"
		else
			MsgWarn "$volume is not cleanly unmounted"
		fi

		# ext3 has no journal quota and need quota check if not cleanly umounted
		if [ "$clean" != "yes" ]; then
			$BIN_TOUCH "$volume/.needquotacheck"
		fi
	fi

	if [ "$mntopts" != "" ]; then
		mntopts="-o $mntopts"
	fi

	# replay cache protection, must be before --bootup-mount
	if [ "$($BIN_CAT /sys/fs/syno-cache-protection/pool_enable)" == "1" ]; then
		sysctl -w vm.dirty_ratio=40
		sysctl -w vm.dirty_background_ratio=30
		sysctl -w vm.dirty_expire_centisecs=4000
		sysctl -w vm.dirty_writeback_centisecs=500
		if [[ ${volume:0:1} == "/" ]]; then
			cache_protection_replay_path="/run/cache_protection$volume"
		else
			cache_protection_replay_path="/run/cache_protection/$volume"
		fi
		$BIN_MKDIR -p "$cache_protection_replay_path"
		if [ "$($BIN_SYNOGETKEYVALUE "/usr/syno/etc/cache_protection.conf" "debug_mode")" == "yes" ]; then
			debug_cp="--debug"
		fi
		RCMsg "Replay cache protection start on volume $devpath:$cache_protection_replay_path" \
		$BIN_SPACETOOL --bootup-replay-start "$debug_cp" "$devpath" "$cache_protection_replay_path"
		bl_need_cache_protection_replay_end=true
	fi

	# mount general volume
	RCMsg "Mounting volume $devpath:$volume with $mntopts" \
	$BIN_SPACETOOL --bootup-mount "$mntopts" "$devpath" "$volume"
	if [ $? -eq 0 ]; then
		$BIN_MKDIR -p "$volume/@tmp.del/"
		delfolder=`$BIN_DATE +%s`
		RCMsg "move $volume/@tmp" \
		$BIN_MV "$volume/@tmp" "$volume/@tmp.del/$delfolder"
		$BIN_RM -rf "$volume/@tmp.del" &
		$BIN_MKDIR "$volume/@tmp"
		$BIN_CHMOD 777 "$volume/@tmp"
	else
		VolumeRemount "$devpath" "$volume" "$fs" "$mntopts"
	fi

	# replay cache protection end, must be after --bootup-mount
	if $bl_need_cache_protection_replay_end; then
		RCMsg "Replay cache protection end on volume $cache_protection_replay_path" \
		$BIN_SPACETOOL --bootup-replay-end "$cache_protection_replay_path"
	fi

	$BIN_CHMOD 755 "$volume"

	VolumeQuotaCheck "$volume" "$fs"

	EnableCachePinFileFeature $volume
}

CreateRaid() {
    local raidLevel="$1"

	swapParts=`$BIN_SYNO_SWAP_CTL --disk-list`
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to get swap disk partition list"
		return 1
	fi

	diskCnt=`echo ${swapParts} | wc -w`
	if [ ${diskCnt} -eq 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: no swap disk partition"
		return 1
	fi

	/sbin/mdadm -C /dev/md1 -e 1.2 -amd -f -R "-l${raidLevel}" -n ${diskCnt} ${swapParts}
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to create raid on /dev/md1"
		return 1
	fi
    return 0
}

CreateScratch() {
	local swapParts=""
	local diskCnt=""

	$BIN_SYNO_SWAP_CTL --stop
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to stop swap"
		return 1
	fi

	CreateRaid 0
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to create raid0 on /dev/md1"
		return 1
	fi

	/sbin/mkfs.ext4 -F /dev/md1
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to mkfs.ext4 on /dev/md1"
		return 1
	fi

	$BIN_MKDIR /scratch
	$BIN_MOUNT /dev/md1 /scratch
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to mount /dev/md1 on /scratch"
		return 1
	fi

	$BIN_MKDIR -p /sbin/etc
	$BIN_ECHO "[scratch_files]" > /sbin/etc/e2fsck.conf
	$BIN_ECHO "directory = /scratch" >> /sbin/etc/e2fsck.conf
	return 0
}

RemoveScratch()
{
	$BIN_RM -f /sbin/etc/e2fsck.conf
	$BIN_RMDIR /sbin/etc
	$BIN_UMOUNT /scratch
	$BIN_RM -r /scratch

	/sbin/mdadm -S /dev/md1
	CreateRaid 1
	if [ $? != 0 ]; then
		$BIN_LOGGER -s -t rc -p err "Error: failed to create raid1 on /dev/md1"
		return 1
	fi
	/sbin/mdadm -S /dev/md1
	$BIN_SYNO_SWAP_CTL --start
}

NeedVolumeScan()
{
	if [ ! -r /.vscan_confirmed ]; then
		return 1
	fi

	if [ ! -r /var/.do_volume_scan_on_bootup ]; then
		echo "DSM is not perform bootup, skip volume scan this time"
		/usr/syno/sbin/synostorage --notify-fsck-skipped
		return 1
	fi

	if [ -f /var/.UpgradeBootup ]; then
		echo "DSM is upgrading, skip volume scan once"
		/usr/syno/sbin/synostorage --notify-fsck-skipped
		return 1
	fi

	if /usr/syno/sbin/synohacore --is_ha_running; then
		if /var/packages/HighAvailability/target/sbin/synoha --check-ha-is-binding; then
			/usr/syno/sbin/synostorage --notify-fsck-skipped
			echo "HA is binding, skip volume scan once"
			return 1
		fi
		if /var/packages/HighAvailability/target/sbin/synoha --is-safemode; then
			/usr/syno/sbin/synostorage --notify-fsck-skipped
			echo "HA is in safemode, skip volume scan once"
			return 1
		fi
	fi

	return 0
}

VolumeSetScan()
{
	if [ -f "/.vscan_confirmed" ]; then
		$BIN_TOUCH "/var/.do_volume_scan_on_bootup"
	fi
}

CheckRemapFile()
{
	local RemapFile=$1
	local IsGenBadVolumeList=$2
	local DevName="/dev/"`$BIN_ECHO "$RemapFile" | $BIN_CUT -d '.' -f 3-4 | sed 's/\./\//g'`
	local ThisDevUUID=`$BIN_SYNOFSTOOL --get-fs-uuid ${DevName}`
	local RemapDevUUID=`$BIN_SYNOGETKEYVALUE ${RemapFile} UUID`
	if [ "$ThisDevUUID" != "$RemapDevUUID" ]; then
		# <DSM> #137682
		if [ ${BLKID_CACHE} == "n" ]; then
			# Existing blkid cache might have both /dev/vgX/volumeY and /dev/mapper/cachedev_Z
			# for the same filesystem UUID but without priority, because we generate space info
			# based on vgX/volumeY not mapper/cachedev_Z.
			# In this way blkid would get vgX/volumeY instead of mapper/cachedev_Z,
			# this is not what we want. so re-generate blkid cache to have device priority.
			${BIN_BLKID} >/dev/null 2>&1
			BLKID_CACHE="y"
		fi
		DevPath=`${BIN_BLKID} -U ${RemapDevUUID}`
		if [ "${DevPath}" == "" ]; then
			$BIN_RM $RemapFile
			return
		fi
		local NewRemapFile="/.remap."`${BIN_ECHO} ${DevPath} | $BIN_CUT -d '/' -f 3- | sed 's/\//\./g'`
		if test -f ${NewRemapFile}; then
			local TmpRemapFile=${RemapFile}.`${BIN_DATE} +%s.%N`
			$BIN_MV ${RemapFile} ${TmpRemapFile}
			CheckRemapFile "${NewRemapFile}" "${IsGenBadVolumeList}"
			RemapFile=${TmpRemapFile}
		fi
		$BIN_MV ${RemapFile} ${NewRemapFile}
		RemapFile=${NewRemapFile}
	fi
	if [ "y" = "${IsGenBadVolumeList}" ]; then
		Remap=$($BIN_ECHO "$RemapFile" | $BIN_CUT -d '.' -f 3-4);
		if [ ! -e /.e2fs_volume ] || [ "$($BIN_CAT /.e2fs_volume | $BIN_GREP -c "\<${Remap}\>")" -eq 0 ]; then
			$BIN_ECHO "${Remap}" >> /.e2fs_volume
		fi
	fi
}

CheckRemapFiles()
{
	local IsGenBadVolumeList=$1
	for RemapFile in /.remap.*
	do
		CheckRemapFile "${RemapFile}" "${IsGenBadVolumeList}"
	done
}

VolumeScan()
{
	local UseScratch="n"
	BLKID_CACHE="n"
	if [ "alpine" == `$BIN_GETKEYVALUE /etc.defaults/synoinfo.conf unique | $BIN_CUT -d"_" -f2` ]; then
		UseScratch="y"
	fi

	if NeedVolumeScan; then
		$BIN_ECHO "volume scan begin"
		$BIN_MKDIR -p /var/log/fsck
		if [ "y" == $UseScratch ]; then
			$BIN_LOGGER -s -t rc -p notice "Create scratch..."
			CreateScratch
		else
			$BIN_LOGGER -s -t rc -p notice "Expand swap..."
			$BIN_SYNO_SWAP_CTL --expand
		fi
		# Update remap file name by UUID and gen bad volume list /.e2fs_volume
		$BIN_RM -rf /.e2fs_volume > /dev/null
		CheckRemapFiles "y"
		RemapList=`/bin/cat /.e2fs_volume`
		for ThisRemap in $RemapList;
		do
			ThisDev="/dev/"`$BIN_ECHO $ThisRemap|sed 's/\./\//g'`
			RemapFile="/.remap."$ThisRemap
			$BIN_ECHO "scan $ThisDev ..."
			$BIN_LOGGER -p warn "Start to fsck on $ThisDev."
			$BIN_ECHO "`$BIN_DATE +'%Y-%m-%dT%H:%M:%S%:z'` Start to fsck on $ThisDev." >> /var/log/fsck/${ThisRemap}.log
			/sbin/e2fsck -C-1 -pvf $ThisDev >> /var/log/fsck/${ThisRemap}.log 2>&1
			local fsckExitCode=$?
			local fsckEndMessage="End of fsck on $ThisDev. exit code:[$fsckExitCode]"
			$BIN_LOGGER -p warn "$fsckEndMessage"
			$BIN_ECHO "$($BIN_DATE +'%Y-%m-%dT%H:%M:%S%:z')" "$fsckEndMessage" >> "/var/log/fsck/${ThisRemap}.log"
			/sbin/debugfs -q $RemapFile $ThisDev
			$BIN_RM $RemapFile
			$BIN_SYNOSTGVOLUME --report-ext4-fsck-done --path="$ThisDev" --fsck-exit-code="$fsckExitCode"
			$BIN_MV $RemapFile".files" "/.badfiles."$ThisRemap
		done
		$BIN_RM /.vscan_confirmed
		# Trigger scemd check bad files with bad volume list /.scemd.show.badfiles
		$BIN_MV /.e2fs_volume /.scemd.show.badfiles
		$BIN_RM /var/.do_volume_scan_on_bootup
		if [ "y" == $UseScratch ]; then
			RemoveScratch
		else
			$BIN_SYNO_SWAP_CTL --shrink
		fi
		$BIN_ECHO "volume scan finished"
	else
		# Update remap file name by UUID
		#   to keep volume bad sectors records repported by pool repair
		CheckRemapFiles "n"
	fi
}

VolumeTuneFS()
{
	[ -b "$1" ] || return 1
	[ -f "$SZF_TUNEFS_CONF" ] || return 0

	local devpath="$1"
	local opts=

	fs=$($BIN_SYNOFSTOOL --get-fs-type $devpath)
	if [ $? -ne 0 ]; then
		MsgFail "Failed to read filesystem magic on $devpath"
		return 1
	fi

	if [ "$fs" = "ext4" ]; then
		opts=$($BIN_SYNOGETKEYVALUE $SZF_TUNEFS_CONF ext4)
		if [ -z "$opts" ]; then
			return 0
		fi
		MsgWarn "Tune $devpath with $opts"
		$BIN_TUNE2FS -o "$opts" "$devpath"
		if [ $? -ne 0 ]; then
			MsgFail "Failed to tune $devpath : $?"
			return 1
		fi
	fi
	return 0
}

# check disable volumes expected not to be mounted for support
VolumeCheckDisable()
{
	if [ -z $1 ]; then
		return 1
	fi
	local input_vol=$(/bin/basename $1)
	local disable_vols=$($BIN_SYNOGETKEYVALUE /etc/synoinfo.conf disable_volumes)
	disable_vols=$($BIN_ECHO $disable_vols | tr "," "\n")

	for disable_vol in $disable_vols; do
		if [ $input_vol = $disable_vol ]; then
			return 0
		fi
	done
	return 1
}

# mount all data volumes according to /etc/fstab
VolumeStart()
{
	local v= dev= vol= opts= mount_pids=
	local volumes=$($BIN_GREP /volume /etc/fstab | $BIN_AWK '{ printf("%s:%s:%s \n", $1, $2, $4) }')

	$BIN_RM -f /tmp/hdhealth

	for v in $volumes; do
		dev=$($BIN_ECHO $v | $BIN_CUT -d':' -f1)
		vol=$($BIN_ECHO $v | $BIN_CUT -d':' -f2)
		opts=$($BIN_ECHO $v | $BIN_CUT -d':' -f3)

		VolumeTuneFS "$dev"
		VolumeCheckDisable "$vol" && continue

		$BIN_MKDIR -p "$vol"
		VolumeMount "$dev" "$vol" "$opts" &
		mount_pids="$mount_pids $!"
	done

	$BIN_SYNOSETKEYVALUE /etc/synoinfo.conf disable_volumes ""
	$BIN_RM -f $SZF_TUNEFS_CONF

	wait $mount_pids

	# update /run/synostorage/volumetab to let sdk get correct volume info
	/usr/syno/sbin/synostorage --update-volumetab
	# dump /run/space/cache_filesystem_info
	/usr/syno/sbin/synofstool --dump-fscache

	if [ -d "/sys/fs/syno-cache-protection" ] && \
		[ "$($BIN_SYNOGETKEYVALUE "/usr/syno/etc/cache_protection.conf" "debug_mode")" != "yes" ]; then
		echo 1 > /sys/fs/syno-cache-protection/release_all
		echo 0 > /sys/fs/syno-cache-protection/pool_enable
	fi

	return $LSB_SUCCESS
}

VolumeStartPostHook()
{
	local volumes=$($BIN_GREP /volume /etc/fstab | $BIN_AWK '{ printf("%s:%s:%s \n", $1, $2, $4) }')

	for v in $volumes; do
		dev=$($BIN_ECHO $v | $BIN_CUT -d':' -f1)
		vol=$($BIN_ECHO $v | $BIN_CUT -d':' -f2)
		$BIN_SPACETOOL --bootup-mount-post-hook "$dev" "$vol"
		$BIN_SPACETOOL --notify-ro-volume-mount-rw "$vol"
	done
	if [ -f "$SZF_SYNORBD_RESET_FLAG" ]; then
		for v in $volumes; do
			vol=$($BIN_ECHO $v | $BIN_CUT -d':' -f2)
			$BIN_SYNOSPACETOOL --rbd-space --disable-volume "$vol"
			$BIN_SYNOSPACETOOL --rbd-space --enable-volume "$vol"
		done
		unlink "$SZF_SYNORBD_RESET_FLAG"
	fi
}

VolumeStopAll()
{
	${BIN_SYSLOG_NG_SCRIPT} reload-block
	/etc.defaults/rc.check_data_volume_holder
	/usr/syno/sbin/synostgvolume --stop-all-running-volume-offline-op
	/usr/syno/bin/spacetool --stop-all-volume
	return $?
}

VolumeStopExternal()
{
	/usr/syno/bin/spacetool --stop-all-ext-volume
	return $?
}

# needless
VolumeStop()
{
	local v= dev=
	local volumes=$($BIN_GREP /volume /etc/fstab | $BIN_AWK '{ printf("%s:%s \n", $1, $2) }')

	for v in $volumes; do
		vol=$($BIN_ECHO $v | $BIN_CUT -d':' -f2)
		/bin/killps "$vol"
		/sbin/quotaoff "$vol"
		$BIN_UMOUNT -R -k "$vol"
	done

	return $LSB_SUCCESS
}

VolumeStatus()
{
	local v= dev=
	local ret=$LSB_STAT_RUNNING
	local volumes=$($BIN_GREP /volume /etc/fstab | $BIN_AWK '{ printf("%s:%s \n", $1, $2) }')

	for v in $volumes; do
		dev=$($BIN_ECHO $v | $BIN_CUT -d':' -f1)
		if $BIN_GREP -q "^$dev" /proc/mounts; then
			MsgDone "$v is enabled"
		else
			MsgWarn "$v is disabled"
			ret=$LSB_STAT_NOT_RUNNING
		fi
	done

	return $ret
}

VolumeBootupPreStart()
{
	local _feature_worm="/sys/fs/btrfs/features/locker"
	local _support_worm="$($BIN_GETKEYVALUE $SYNOINFO_DEF support_worm)"
	local _support_btrfs="$($BIN_GETKEYVALUE $SYNOINFO_DEF support_btrfs)"

	if [ "$_support_btrfs" = "yes" ]; then
		$BIN_MODPROBE -q btrfs
	fi
	if [ -f "$_feature_worm" ] && [ "$_support_worm" != "yes" ]; then
		echo 0 > "$_feature_worm"
	fi

	if [ "yes" = "$(/usr/syno/bin/synogetkeyvalue /etc.defaults/synoinfo.conf support_xa)" ]
	then
		/usr/syno/sbin/synostgpool --xa --volume-rw-keeper
	fi
	if [ "yes" = "$(/usr/syno/bin/synogetkeyvalue /etc.defaults/synoinfo.conf support_dual_head)" ]
	then
		/usr/syno/synoaha/bin/synoaha --volume-rw-keeper
	fi
}

VolumeBootupStart()
{
	$BIN_ECHO `$BIN_DATE`": start volume"

	$BIN_MKDIR /run/space

	/usr/syno/cfgen/s00_synocheckfstab

	# checking and Mounting filesystem(s) ...
	/usr/syno/bin/synobootseq --set-check-fs  >/dev/null 2>&1
	VolumeStart

	# IsBootupTypeFreshInstall return 0 means fresh install, so please be careful if you use return value to judge
	if IsBootupTypeFreshInstall; then
		if [ -f $SZF_MANUTIL_VOLUME_SIZE ]; then
			$BIN_RM -f $SZF_MANUTIL_VOLUME_SIZE
		fi

		local maxdisks=`$BIN_GETKEYVALUE $SYNOINFO_DEF maxdisks`
		local supportraid=`$BIN_GETKEYVALUE $SYNOINFO_DEF supportraid`

		if [ "$maxdisks" == "1" ] && [ "$supportraid" != "yes" ]; then
			# auto create volume for 1-bay if disk condition is good
			/usr/syno/bin/synodisk --is-all-interal-drives-free-to-use
			if [ 0 -eq $? ]; then
				/usr/syno/bin/volumetool --create-single-disk-volume
			fi
		fi
	fi

	#Create volume for VDSM
	if [ "$PLATFORM" = "kvmx64" -o \
			"$PLATFORM" = "nextkvmx64" -o \
			"$PLATFORM" = "kvmcloud" -o \
			"$PLATFORM" = "kvmx64v2" ]; then
		/usr/syno/bin/volumetool --create-vdsm-volumes
	fi

	# reset bootseq to start-services
	/usr/syno/bin/synobootseq --set-start-services >/dev/null 2>&1
}

case "$1" in
	--bootup-start)
		VolumeBootupStart
		;;
	--bootup-pre-start)
		VolumeBootupPreStart
		;;
	--start)
		VolumeStart
		;;
	--scan)
		VolumeScan
		;;
	--set-scan)
		VolumeSetScan
		;;
	--stop-all)
		VolumeStopAll
		VolumeStopExternal
		;;
	--stop-external)
		VolumeStopExternal
		;;
	--status)
		VolumeStatus
		;;
	--post-hook)
		VolumeStartPostHook
		;;
	*)
		;;
esac

exit 0

# vim:ft=sh