Commit c9e6e659 authored by Kroese's avatar Kroese Committed by GitHub
Browse files

Fix for issue #381 (#383)

* feat: Refactor multi-disk code
parent 04bd8a16
Loading
Loading
Loading
Loading
+155 −167
Original line number Diff line number Diff line
@@ -14,228 +14,216 @@ SYSTEM="$STORAGE/$BASE.system.img"
[ ! -f "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81
[ ! -f "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82

DATA="${STORAGE}/data.img"

if [[ ! -f "${DATA}" ]] && [[ -f "$STORAGE/data$DISK_SIZE.img" ]]; then
  # Fallback for legacy installs
  DATA="$STORAGE/data$DISK_SIZE.img"
fi
DISK_OPTS="\
    -device virtio-scsi-pci,id=hw-synoboot,bus=pcie.0,addr=0xa \
    -drive file=${BOOT},if=none,id=drive-synoboot,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=${DISK_ROTATION},bootindex=1 \
    -device virtio-scsi-pci,id=hw-synosys,bus=pcie.0,addr=0xb \
    -drive file=${SYSTEM},if=none,id=drive-synosys,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=${DISK_ROTATION},bootindex=2"

addDisk () {

  local GB
  local DIR
  local REQ
  local SIZE
  local SPACE
  local MIN_SIZE
  local CUR_SIZE
  local DATA_SIZE
  local DISK_ID=$1
  local DISK_FILE=$2
  local DISK_DESC=$3
  local DISK_SPACE=$4
  local DISK_INDEX=$5
  local DISK_ADDRESS=$6

  DIR=$(dirname "${DISK_FILE}")
  [ ! -d "${DIR}" ] && return 0

  [ -z "$DISK_SPACE" ] && DISK_SPACE="16G"
  DISK_SPACE=$(echo "${DISK_SPACE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
  DATA_SIZE=$(numfmt --from=iec "${DISK_SPACE}")

  MIN_SIZE=6442450944
DISK_SIZE=$(echo "${DISK_SIZE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
DATA_SIZE=$(numfmt --from=iec "${DISK_SIZE}")

  if (( DATA_SIZE < MIN_SIZE )); then
  error "Please increase DISK_SIZE to at least 6 GB." && exit 83
    error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 83
  fi

if [ -f "${DATA}" ]; then
  if [ -f "${DISK_FILE}" ]; then

  OLD_SIZE=$(stat -c%s "${DATA}")
    CUR_SIZE=$(stat -c%s "${DISK_FILE}")

  if [ "$DATA_SIZE" -gt "$OLD_SIZE" ]; then
    if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then

    info "Resizing data disk from $OLD_SIZE to $DATA_SIZE bytes.."
      GB=$(( (CUR_SIZE + 1073741823)/1073741824 ))
      info "Resizing ${DISK_DESC} from ${GB}G to ${DISK_SPACE} .."

      if [[ "${ALLOCATE}" == [Nn]* ]]; then

        # Resize file by changing its length
      if ! truncate -s "${DATA_SIZE}" "${DATA}"; then
        error "Could not resize the file for the virtual disk." && exit 85
        if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
          error "Could not resize ${DISK_DESC} file (${DISK_FILE}) to ${DISK_SPACE} .." && exit 85
        fi

      else

      REQ=$((DATA_SIZE-OLD_SIZE))
        REQ=$((DATA_SIZE-CUR_SIZE))

        # Check free diskspace
      SPACE=$(df --output=avail -B 1 "${STORAGE}" | tail -n 1)
        SPACE=$(df --output=avail -B 1 "${DIR}" | tail -n 1)

        if (( REQ > SPACE )); then
        error "Not enough free space to resize virtual disk to ${DISK_SIZE}."
          error "Not enough free space to resize ${DISK_DESC} to ${DISK_SPACE} .."
          error "Specify a smaller size or disable preallocation with ALLOCATE=N." && exit 84
        fi

        # Resize file by allocating more space
      if ! fallocate -l "${DATA_SIZE}" "${DATA}"; then
        if ! truncate -s "${DATA_SIZE}" "${DATA}"; then
          error "Could not resize the file for the virtual disk." && exit 85
        if ! fallocate -l "${DISK_SPACE}" "${DISK_FILE}"; then
          if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
            error "Could not resize ${DISK_DESC} file (${DISK_FILE}) to ${DISK_SPACE} .." && exit 85
          fi
        fi

      if [[ "${ALLOCATE}" == [Zz]* ]]; then

        GB=$(( (REQ + 1073741823)/1073741824 ))

        info "Preallocating ${GB} GB of diskspace, please wait..."
        dd if=/dev/urandom of="${DATA}" seek="${OLD_SIZE}" count="${REQ}" bs=1M iflag=count_bytes oflag=seek_bytes status=none

      fi
      fi
    fi

  if [ "$DATA_SIZE" -lt "$OLD_SIZE" ]; then

    info "Shrinking existing disks is not supported yet!"
    info "Creating backup of old drive in storage folder..."

    mv -f "${DATA}" "${DATA}.bak"

  fi
  fi

if [ ! -f "${DATA}" ]; then
  if [ ! -f "${DISK_FILE}" ]; then

    if [[ "${ALLOCATE}" == [Nn]* ]]; then

      # Create an empty file
    if ! truncate -s "${DATA_SIZE}" "${DATA}"; then
      rm -f "${DATA}"
      error "Could not create a file for the virtual disk." && exit 87
      if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
        rm -f "${DISK_FILE}"
        error "Could not create a file for ${DISK_DESC} (${DISK_FILE})" && exit 87
      fi

    else

      # Check free diskspace
    SPACE=$(df --output=avail -B 1 "${STORAGE}" | tail -n 1)
      SPACE=$(df --output=avail -B 1 "${DIR}" | tail -n 1)

      if (( DATA_SIZE > SPACE )); then
      error "Not enough free space to create a virtual disk of ${DISK_SIZE}."
        error "Not enough free space to create ${DISK_DESC} of ${DISK_SPACE} .."
        error "Specify a smaller size or disable preallocation with ALLOCATE=N." && exit 86
      fi

      # Create an empty file
    if ! fallocate -l "${DATA_SIZE}" "${DATA}"; then
      if ! truncate -s "${DATA_SIZE}" "${DATA}"; then
        rm -f "${DATA}"
        error "Could not create a file for the virtual disk." && exit 87
      if ! fallocate -l "${DISK_SPACE}" "${DISK_FILE}"; then
        if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
          rm -f "${DISK_FILE}"
          error "Could not create a file for ${DISK_DESC} (${DISK_FILE}) of ${DISK_SPACE} .." && exit 87
        fi
      fi

    if [[ "${ALLOCATE}" == [Zz]* ]]; then

      info "Preallocating ${DISK_SIZE} of diskspace, please wait..."
      dd if=/dev/urandom of="${DATA}" count="${DATA_SIZE}" bs=1M iflag=count_bytes status=none

    fi
    fi

    # Check if file exists
  if [ ! -f "${DATA}" ]; then
    error "Virtual disk does not exist ($DATA)" && exit 88
    if [ ! -f "${DISK_FILE}" ]; then
      error "File for ${DISK_DESC} ($DISK_FILE) does not exist!" && exit 88
    fi

  fi

  # Check the filesize
SIZE=$(stat -c%s "${DATA}")
  SIZE=$(stat -c%s "${DISK_FILE}")

  if [[ SIZE -ne DATA_SIZE ]]; then
  error "Virtual disk has the wrong size: ${SIZE}" && exit 89
    error "File for ${DISK_DESC} (${DISK_FILE}) has the wrong size: ${SIZE} bytes" && exit 89
  fi

DISK_OPTS="\
    -device virtio-scsi-pci,id=hw-synoboot,bus=pcie.0,addr=0xa \
    -drive file=${BOOT},if=none,id=drive-synoboot,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=${DISK_ROTATION},bootindex=1 \
    -device virtio-scsi-pci,id=hw-synosys,bus=pcie.0,addr=0xb \
    -drive file=${SYSTEM},if=none,id=drive-synosys,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=${DISK_ROTATION},bootindex=2 \
    -device virtio-scsi-pci,id=hw-userdata,bus=pcie.0,addr=0xc \
    -drive file=${DATA},if=none,id=drive-userdata,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata,id=userdata0,rotation_rate=${DISK_ROTATION},bootindex=3"

: ${DISK2_SIZE:=''}
EXTRA_SIZE=DISK2_SIZE
EXTRA_DISK="/storage2/data.img"
  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-${DISK_ID},bus=pcie.0,addr=${DISK_ADDRESS} \
    -drive file=${DISK_FILE},if=none,id=drive-${DISK_ID},format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-${DISK_ID}.0,channel=0,scsi-id=0,lun=0,drive=drive-${DISK_ID},id=${DISK_ID},rotation_rate=${DISK_ROTATION},bootindex=${DISK_INDEX}"

if [ -d "$(dirname "${EXTRA_DISK}")" ]; then
  return 0
}

  if [ ! -f "${EXTRA_DISK}" ]; then
    [ -z "$EXTRA_SIZE" ] && EXTRA_SIZE="16G"
    if ! truncate -s "${EXTRA_SIZE}" "${EXTRA_DISK}"; then
      error "Could not create the file for the second disk." && exit 53
    fi
  fi
DISK1_FILE="${STORAGE}/data.img"

  if [ -n "$EXTRA_SIZE" ]; then
    CUR_SIZE=$(stat -c%s "${EXTRA_DISK}")
    DATA_SIZE=$(numfmt --from=iec "${EXTRA_SIZE}")
    if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then
      truncate -s "${EXTRA_SIZE}" "${EXTRA_DISK}"
    fi
if [[ ! -f "${DISK1_FILE}" ]] && [[ -f "${STORAGE}/data${DISK_SIZE}.img" ]]; then
  # Fallback for legacy installs
  mv "${STORAGE}/data${DISK_SIZE}.img" "${DISK1_FILE}"
fi

  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-userdata2,bus=pcie.0,addr=0xd \
    -drive file=${EXTRA_DISK},if=none,id=drive-userdata2,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata2.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata2,id=userdata2,rotation_rate=${DISK_ROTATION},bootindex=4"
DISK2_FILE="/storage2/data2.img"

if [ ! -f "${DISK2_FILE}" ]; then
  # Fallback for legacy installs
  FALLBACK="/storage2/data.img"
  if [[ -f "${DISK1_FILE}" ]] && [[ -f "${FALLBACK}" ]]; then
    SIZE1=$(stat -c%s "${FALLBACK}")
    SIZE2=$(stat -c%s "${DISK1_FILE}")
    if [[ SIZE1 -ne SIZE2 ]]; then
      mv "${FALLBACK}" "${DISK2_FILE}"
    fi

: ${DISK3_SIZE:=''}
EXTRA_SIZE=DISK3_SIZE
EXTRA_DISK="/storage3/data.img"

if [ -d "$(dirname "${EXTRA_DISK}")" ]; then

  if [ ! -f "${EXTRA_DISK}" ]; then
    [ -z "$EXTRA_SIZE" ] && EXTRA_SIZE="16G"
    if ! truncate -s "${EXTRA_SIZE}" "${EXTRA_DISK}"; then
      error "Could not create the file for the third disk." && exit 54
  fi
fi

  if [ -n "$EXTRA_SIZE" ]; then
    CUR_SIZE=$(stat -c%s "${EXTRA_DISK}")
    DATA_SIZE=$(numfmt --from=iec "${EXTRA_SIZE}")
    if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then
      truncate -s "${EXTRA_SIZE}" "${EXTRA_DISK}"
DISK3_FILE="/storage3/data3.img"

if [ ! -f "${DISK3_FILE}" ]; then
  # Fallback for legacy installs
  FALLBACK="/storage3/data.img"
  if [[ -f "${DISK1_FILE}" ]] && [[ -f "${FALLBACK}" ]]; then
    SIZE1=$(stat -c%s "${FALLBACK}")
    SIZE2=$(stat -c%s "${DISK1_FILE}")
    if [[ SIZE1 -ne SIZE2 ]]; then
      mv "${FALLBACK}" "${DISK3_FILE}"
    fi
  fi

  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-userdata3,bus=pcie.0,addr=0xe \
    -drive file=${EXTRA_DISK},if=none,id=drive-userdata3,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata3.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata3,id=userdata3,rotation_rate=${DISK_ROTATION},bootindex=5"

fi

: ${DEVICE:=''}        # Docker variable to passthrough a block device, like /dev/vdc1.
: ${DEVICE2:=''}
: ${DEVICE3:=''}

if [ -n "${DEVICE}" ]; then
DISK4_FILE="/storage4/data4.img"
DISK5_FILE="/storage5/data5.img"
DISK6_FILE="/storage6/data6.img"

  [ ! -b "${DEVICE}" ] && error "Device ${DEVICE} cannot be found! Please add it to the 'devices' section of your compose file." && exit 55
: ${DISK2_SIZE:=''}
: ${DISK3_SIZE:=''}
: ${DISK4_SIZE:=''}
: ${DISK5_SIZE:=''}
: ${DISK6_SIZE:=''}

  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-userdata4,bus=pcie.0,addr=0xf \
    -drive file=${DEVICE},if=none,id=drive-userdata4,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata4.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata4,id=userdata4,rotation_rate=${DISK_ROTATION},bootindex=6"
addDisk "userdata" "${DISK1_FILE}" "disk" "${DISK_SIZE}" "3" "0xc"
addDisk "userdata2" "${DISK2_FILE}" "disk2" "${DISK2_SIZE}" "4" "0xd"
addDisk "userdata3" "${DISK3_FILE}" "disk3" "${DISK3_SIZE}" "5" "0xe"
addDisk "userdata4" "${DISK4_FILE}" "disk4" "${DISK4_SIZE}" "9" "0x7"
addDisk "userdata5" "${DISK5_FILE}" "disk5" "${DISK5_SIZE}" "10" "0x8"
addDisk "userdata6" "${DISK6_FILE}" "disk6" "${DISK6_SIZE}" "11" "0x9"

fi
addDevice () {

if [ -n "${DEVICE2}" ]; then
  local DISK_ID=$1
  local DISK_DEV=$2
  local DISK_INDEX=$3
  local DISK_ADDRESS=$4

  [ ! -b "${DEVICE2}" ] && error "Device ${DEVICE2} cannot be found! Please add it to the 'devices' section of your compose file." && exit 56
  [ -z "${DISK_DEV}" ] && return 0
  [ ! -b "${DISK_DEV}" ] && error "Device ${DISK_DEV} cannot be found! Please add it to the 'devices' section of your compose file." && exit 55

  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-userdata5,bus=pcie.0,addr=0x5 \
    -drive file=${DEVICE2},if=none,id=drive-userdata5,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata5.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata5,id=userdata5,rotation_rate=${DISK_ROTATION},bootindex=7"

fi
    -device virtio-scsi-pci,id=hw-${DISK_ID},bus=pcie.0,addr=${DISK_ADDRESS} \
    -drive file=${DISK_DEV},if=none,id=drive-${DISK_ID},format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-${DISK_ID}.0,channel=0,scsi-id=0,lun=0,drive=drive-${DISK_ID},id=${DISK_ID},rotation_rate=${DISK_ROTATION},bootindex=${DISK_INDEX}"

if [ -n "${DEVICE3}" ]; then

  [ ! -b "${DEVICE3}" ] && error "Device ${DEVICE3} cannot be found! Please add it to the 'devices' section of your compose file." && exit 57

  DISK_OPTS="${DISK_OPTS} \
    -device virtio-scsi-pci,id=hw-userdata6,bus=pcie.0,addr=0x6 \
    -drive file=${DEVICE3},if=none,id=drive-userdata6,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
    -device scsi-hd,bus=hw-userdata6.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata6,id=userdata6,rotation_rate=${DISK_ROTATION},bootindex=8"
  return 0
}

fi
: ${DEVICE:=''}        # Docker variable to passthrough a block device, like /dev/vdc1.
: ${DEVICE2:=''}
: ${DEVICE3:=''}
: ${DEVICE4:=''}
: ${DEVICE5:=''}
: ${DEVICE6:=''}

addDevice "userdata7" "${DEVICE}" "6" "0xf"
addDevice "userdata8" "${DEVICE2}" "7" "0x5"
addDevice "userdata9" "${DEVICE3}" "8" "0x6"
addDevice "userdata4" "${DEVICE4}" "9" "0x7"
addDevice "userdata5" "${DEVICE5}" "10" "0x8"
addDevice "userdata6" "${DEVICE6}" "11" "0x9"

return 0
+1 −10
Original line number Diff line number Diff line
#!/usr/bin/env bash
set -Eeuo pipefail

STORAGE="/storage"
[ ! -d "$STORAGE" ] && error "Storage folder (${STORAGE}) not found!" && exit 13

if [ -f "$STORAGE"/dsm.ver ]; then
  BASE=$(cat "${STORAGE}/dsm.ver")
else
@@ -11,6 +8,7 @@ else
  BASE="DSM_VirtualDSM_42962"
fi

: ${URL:=''}
[ -n "$URL" ] && BASE=$(basename "$URL" .pat)

if [[ -f "$STORAGE/$BASE.boot.img" ]] && [[ -f "$STORAGE/$BASE.system.img" ]]; then
@@ -202,8 +200,6 @@ BOOT=$(find "$TMP" -name "*.bin.zip")
BOOT=$(echo "$BOOT" | head -c -5)
unzip -q -o "$BOOT".zip -d "$TMP"

[[ "${ALLOCATE}" == [Zz]* ]] && info "Install: Allocating diskspace..."

SYSTEM="$TMP/sys.img"
SYSTEM_SIZE=4954537983

@@ -217,11 +213,6 @@ if ! fallocate -l "${SYSTEM_SIZE}" "${SYSTEM}"; then
  fi
fi

if [[ "${ALLOCATE}" == [Zz]* ]]; then
  info "Install: Preallocating 4 GB of diskspace..."
  dd if=/dev/urandom of="${SYSTEM}" count="${SYSTEM_SIZE}" bs=1M iflag=count_bytes status=none
fi

# Check if file exists
[ ! -f "${SYSTEM}" ] && error "System disk does not exist ($SYSTEM)" && exit 89

+5 −1
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ trap 'error "Status $? while: ${BASH_COMMAND} (line $LINENO/$BASH_LINENO)"' ERR

# Docker environment variables

: ${URL:=''}            # URL of the PAT file
: ${GPU:='N'}           # Enable GPU passthrough
: ${DEBUG:='N'}         # Enable debugging mode
: ${ALLOCATE:='Y'}      # Preallocate diskspace
@@ -32,4 +31,9 @@ rm -f /run/dsm.url
rm -f /run/qemu.pid
rm -f /run/qemu.count

# Check folder

STORAGE="/storage"
[ ! -d "$STORAGE" ] && error "Storage folder (${STORAGE}) not found!" && exit 13

return 0