summaryrefslogtreecommitdiffstats
path: root/core/rootfs/rootfs-stage32/data
diff options
context:
space:
mode:
authorSimon Rettberg2018-03-24 15:39:31 +0100
committerSimon Rettberg2018-03-24 15:39:31 +0100
commitf7a47fd6cbf541d3627215514eaf63f0b0e393ba (patch)
tree6a5d45adb35c6d3e90cf64d9589746a84d1dafbb /core/rootfs/rootfs-stage32/data
parent[etherwake] New module (diff)
downloadmltk-f7a47fd6cbf541d3627215514eaf63f0b0e393ba.tar.gz
mltk-f7a47fd6cbf541d3627215514eaf63f0b0e393ba.tar.xz
mltk-f7a47fd6cbf541d3627215514eaf63f0b0e393ba.zip
[rfs-stage32] Smarter handling of ID45; unify part detection; sort by size
- Partitions matching a certain ID will be sorted by size by the get_all_with_id function, so in case you want only one by that type you'll get the largest one. - Partition detection is now done by querying udev for all the block devices found in /dev which works well for both DOS and GPT. - ID45 code now handles the cases where a partition was resized offline and adjusts or recreates the file system accordingly. We also enforce ext4 for ID45 now instead of acceping anything that appears to be mountable.
Diffstat (limited to 'core/rootfs/rootfs-stage32/data')
-rw-r--r--core/rootfs/rootfs-stage32/data/etc/systemd/system/setup-partitions.service2
-rwxr-xr-xcore/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions173
2 files changed, 143 insertions, 32 deletions
diff --git a/core/rootfs/rootfs-stage32/data/etc/systemd/system/setup-partitions.service b/core/rootfs/rootfs-stage32/data/etc/systemd/system/setup-partitions.service
index 6bb3a986..2cfad221 100644
--- a/core/rootfs/rootfs-stage32/data/etc/systemd/system/setup-partitions.service
+++ b/core/rootfs/rootfs-stage32/data/etc/systemd/system/setup-partitions.service
@@ -1,7 +1,7 @@
[Unit]
Description=Setup local disk partitions (tmp, swap)
DefaultDependencies=no
-Before=basic.target
+Before=basic.target tmp.target
After=systemd-udev-settle.service
Wants=tmp.target
diff --git a/core/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions b/core/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions
index d4042926..fea561d1 100755
--- a/core/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions
+++ b/core/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions
@@ -1,5 +1,6 @@
-#!/bin/ash
-# Copyright (c) 2013 - OpenSLX GmbH
+#!/bin/bash
+# Arrays etc and $(( )) with big numbers
+# Copyright (c) 2018 - OpenSLX GmbH
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
@@ -20,6 +21,31 @@ PARTITION_FILE="/run/openslx/partitions"
readonly MOUNT_POINT_45 PARTITION_FILE
mkdir -p "/run/openslx"
+declare -a TMPFILES
+gettmp () {
+ local vn file
+ for vn in "$@"; do
+ file=$(mktemp -p /run/openslx) # since we fiddle around with /tmp in this script
+ declare -g "${vn}=${file}"
+ TMPFILES+=("$file")
+ done
+}
+delalltmp () {
+ rm -f -- "${TMPFILES[@]}"
+}
+trap delalltmp EXIT
+
+mount_options () {
+ case "$1" in
+ ext2)
+ echo "-o nocheck"
+ ;;
+ ext4)
+ echo "-o errors=remount-ro,data=ordered,relatime,quota"
+ ;;
+ esac
+}
+
# General formatter for the /tmp partition on a local harddisk
format_disk () {
MOUNT_OPTIONS_SET_BY_FORMAT_DISK="" # Global var!
@@ -42,31 +68,29 @@ format_disk () {
if which "mkfs.$fs" ; then
case "$fs" in
xfs)
- fopt="-f -b size=4k -s size=4k" # fastest formatting possible :)
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK="-o noexec"
+ fopt="-f"
;;
ext2)
- fopt="-Fq"
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK="-o nocheck,noexec"
+ fopt="-F"
+ ;;
+ ext3)
+ fopt="-F"
;;
- ext3|ext4)
- fopt="-Fq"
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK="-o noexec"
+ ext4)
+ fopt="-F -b 4096 -O extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize,quota -E quotatype=usrquota:prjquota -I 256"
;;
reiserfs)
fopt="-f"
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK="-o noexec"
;;
jfs)
- fopt="-q"
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK="-o noexec"
+ fopt=""
;;
*)
- fopt=
- MOUNT_OPTIONS_SET_BY_FORMAT_DISK=
+ fopt=""
;;
esac
- mkfs.$fs ${fopt} "${target}" && return 0 # Success!
+ MOUNT_OPTIONS_SET_BY_FORMAT_DISK=$(mount_options "$fs")
+ "mkfs.$fs" ${fopt} "${target}" && return 0 # Success!
fi
done
return 1
@@ -102,6 +126,7 @@ fdisk -l | grep '^/dev/' > "$PARTITION_FILE"
if [ ! -s "$PARTITION_FILE" ]; then
udevadm trigger
sleep 3
+ udevadm trigger
udevadm settle
fdisk -l | grep '^/dev/' > "$PARTITION_FILE"
fi
@@ -110,16 +135,36 @@ echo "Partitions:"
cat "$PARTITION_FILE"
# Get all partitions with given id (list of /dev/sdXX)
+# Works for MBR/DOS by looking at the type (1 byte)
+# and for GPT by looking for the label 'OpenSLX-ID$1'
+# in case an id was given, or just at the UUID if some
+# longer string was given
+# The output will be a list of matching devices,
+# sorted from largest to smallest
get_all_with_id () {
- [ -z "$1" ] && return
- local ID=$1
- awk '{if (($2 == "*" && $6 == "'$ID'") || ($2 != "*" && $5 == "'$ID'")) print $1}' "$PARTITION_FILE" # watch out for non-spaced '$ID'
+ local ID dev exp
+ exp=
+ while [ $# -gt 0 ]; do
+ ID=$1
+ shift
+ [ -z "$ID" ] && continue
+ [ ${#ID} -eq 1 ] && ID="0?$ID" # passed '7' as argument -- look for 0x7 or 0x07
+ if [ ${#ID} -eq 2 ]; then
+ exp="$exp|ID_PART_ENTRY_(NAME=OpenSLX-ID|TYPE=0x)$ID"
+ else
+ exp="$exp|ID_PART_ENTRY_TYPE=$ID"
+ fi
+ done
+ exp=${exp:1}
+ echo "Partition find for '$*' is '$exp'" >&2
+ for dev in $(find /dev/ -type b); do
+ udevadm info --name="$dev" | grep -iqE "($exp)\$" && echo "$(blockdev --getsize64 "$dev") $dev"
+ done | sort -n -k1 -r | cut -d' ' -f2
}
# Check for standard swap partitions and make them available to the system
HAVE_SWAP=no
-for PART_DEV in $(get_all_with_id 82) '/dev/disk/by-partlabel/Linux\x20swap'; do
- [ -e "$PART_DEV" ] || continue # Since Linux\x20swap is hard-coded and might not exist
+for PART_DEV in $(get_all_with_id "82" "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f"); do
if swapon "$PART_DEV" -p 10; then
HAVE_SWAP=yes # low priority, in case we have zram swap, prefer that)
echo -e "$PART_DEV\tswap\t\tswap\t\tdefaults\t 0 0" >> "/etc/fstab"
@@ -130,11 +175,9 @@ done
# space, thus no normal filesystem will be incidentally deleted or
# corrupted
HAVE_TEMP=no
-for PART_DEV in $(get_all_with_id 44) '/dev/disk/by-partlabel/OpenSLX-ID44'; do
- [ -e "$PART_DEV" ] || continue # Since OpenSLX-ID44 is hard-coded and might not exist
+for PART_DEV in $(get_all_with_id "44"); do
# check for supported filesystem and formatter
if format_disk "$PART_DEV"; then
- # echo "$PART_DEV is mounted to /mnt/tmp at $(sysup)" >/tmp/tmpready
mount_temp "$MOUNT_OPTIONS_SET_BY_FORMAT_DISK" "$PART_DEV" || continue
echo -e "${PART_DEV}\t/tmp\t\tauto\t\tnoexec\t 0 0" >> "/etc/fstab"
HAVE_TEMP=yes
@@ -145,32 +188,100 @@ for PART_DEV in $(get_all_with_id 44) '/dev/disk/by-partlabel/OpenSLX-ID44'; do
done
# Put detected linux partitions (83) into /etc/fstab with "noauto"
-HAVE_PARTITION_45=no
for PART_DEV in $(get_all_with_id 83); do
mkdir -p "/media/${PART_DEV#/dev/*}"
echo -e "${PART_DEV}\t/media/${PART_DEV#/dev/*}\tauto\t\tnoauto,noexec\t 0 0" >> "/etc/fstab"
done
# special partition 45 (persistent scratch) to $MOUNT_POINT_45
-for PART_DEV in $(get_all_with_id 45) '/dev/disk/by-partlabel/OpenSLX-ID45'; do
+HAVE_PARTITION_45=no
+mopts=$(mount_options ext4)
+# try all the ID45 partitions until one succeeds, from large to small
+for PART_DEV in $(get_all_with_id "45"); do
mkdir -p "$MOUNT_POINT_45"
- if ! mount -t auto -o noexec "${PART_DEV}" "$MOUNT_POINT_45"; then
- format_disk "$PART_DEV" "ext4 xfs jfs ext3" || continue
- mount -t auto -o noexec "${PART_DEV}" "$MOUNT_POINT_45" || continue
+ # Let's see if this is an ext4 partition and if so, whether it has the proper size
+ # Any fixing should happen first
+ gettmp "logfile"
+ COUNT=0
+ while true; do
+ [ "$COUNT" -ge 4 ] && break
+ let COUNT++
+ fsck.ext4 -y "$PART_DEV" &> "$logfile"
+ RET=$?
+ if [ "$(( RET & 7 ))" = 4 ]; then
+ slxlog "partition-45-fsck" "Error fixing file system errors on ID45 partition" "$logfile"
+ break
+ fi
+ [ "$(( RET & 3 ))" != 1 ] && break
+ done
+ # awk script to take block count and block size from dumpe2fs output and multiply them to get byte size
+ fs_size=$(dumpe2fs -h "$PART_DEV" | awk -F: 'BEGIN{a=0;b=0}{if ($1 == "Block count") a=$2; if($1 == "Block size") b=$2;}END{ if (a>0 && b>0) print a*b}')
+ echo "$PART_DEV has ext4 fs of size $fs_size"
+ if [ -n "$fs_size" ] && [ "$fs_size" -gt 1000000 ]; then
+ # It's ext4, see if partition size was changed offline
+ dev_size=$(blockdev --getsize64 "$PART_DEV")
+ echo "$PART_DEV has actual size of $dev_size"
+ if [ -n "$dev_size" ] && [ "$dev_size" -gt 1000000 ]; then
+ # somewhat sane, see what to do
+ dev_mb=$(( dev_size / 1024 / 1024 ))
+ fs_mb=$(( fs_size / 1024 / 1024 ))
+ echo "Dev: $dev_mb, fs: $fs_mb"
+ if [ "$(( fs_mb + 100 ))" -lt "$dev_mb" ]; then
+ # dev size plus 100MB is still smaller than reported fs size -- resize fs
+ gettmp "logfile"
+ fsck.ext4 -f -y "$PART_DEV" &> "$logfile"
+ if resize2fs "$PART_DEV" &>> "$logfile"; then
+ slxlog "partition-45-resize-ok" "Resized partition $PART_DEV from $fs_mb MiB to $dev_mb MiB" "$logfile"
+ else
+ slxlog "partition-45-resize-fail" "Could not enlarge file system size of $PART_DEV from $fs_mb MiB to $dev_mb MiB" "$logfile"
+ dd if=/dev/zero of="$PART_DEV" bs=1M count=1 &>/dev/null
+ fi
+ elif [ "$dev_size" -lt "$fs_size" ]; then
+ # partition is smaller than expected by fs -- killall
+ slxlog "partition-45-shrink" "$PART_DEV has ext4 file system which is $fs_mb MiB, but partition size is only $dev_mb MiB. Will wipe partition to be safe..."
+ dd if=/dev/zero of="$PART_DEV" bs=1M count=1 &>/dev/null
+ fi
+ fi
+ fi
+ # try to mount
+ if ! mount -v -t ext4 $mopts "${PART_DEV}" "$MOUNT_POINT_45"; then
+ # failed, try to format
+ gettmp "logfile"
+ if ! format_disk "$PART_DEV" "ext4" &> "$logfile"; then
+ slxlog "partition-45-format" "Cannot format $PART_DEV with ext4" "$logfile"
+ continue
+ fi
+ gettmp "logfile"
+ if ! mount -v -t ext4 $mopts "${PART_DEV}" "$MOUNT_POINT_45" &> "$logfile"; then
+ slxlog "partition-45-newmount" "Cannot mount $PART_DEV with ext4 right after formatting" "$logfile"
+ continue
+ fi
+ fi
+ # Mount success -- clean up lost+found
+ find "${MOUNT_POINT_45}/slx_lost+found" -mindepth 1 -maxdepth 1 -mtime +90 -type d -exec rm -rf -- {} \;
+ if [ -d "${MOUNT_POINT_45}/lost+found" ]; then
+ touch "${MOUNT_POINT_45}/lost+found"
+ mkdir -p "${MOUNT_POINT_45}/slx_lost+found"
+ mv -f -- "${MOUNT_POINT_45}/lost+found" "${MOUNT_POINT_45}/slx_lost+found/$(date +%s)_$$-$RANDOM"
fi
- echo -e "${PART_DEV}\t${MOUNT_POINT_45}\tauto\t\tnoauto,noexec\t\t 0 0" >> "/etc/fstab"
+ chmod 0700 "${MOUNT_POINT_45}/slx_lost+found"
+ chown 0:0 "${MOUNT_POINT_45}/slx_lost+found"
+ # fstab entry
+ echo -e "${PART_DEV}\t${MOUNT_POINT_45}\tauto\t\tnoauto\t\t 0 0" >> "/etc/fstab"
HAVE_PARTITION_45=yes
- break
+ break # success, done
done
# and 46 to /media/devXX
-for PART_DEV in $(get_all_with_id 46); do
+for PART_DEV in $(get_all_with_id "46"); do
mkdir -p "/media/${PART_DEV#/dev/*}"
#mount -t auto ${PART_DEV} /mnt/media/${PART_DEV#/dev/*} \n\
#test -d /mnt/media/${PART_DEV#/dev/*}/home && \
# ln -sf /media/${PART_DEV#/dev/*} /var/home
echo -e "${PART_DEV}\t/media/${PART_DEV#/dev/*}\tauto\t\tnoauto\t\t 0 0" >> "/etc/fstab"
done
+
+# finally, prepare the data subdir on persistent part
if [ "$HAVE_PARTITION_45" = "yes" ]; then
mkdir -p "$MOUNT_POINT_45/data"
chown root:root "$MOUNT_POINT_45" "$MOUNT_POINT_45/data"