1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 | ogra@localhost:~$ cat /usr/share/initramfs-tools/scripts/local-premount/resize
#! /bin/sh -e
# initramfs local-premount script for resizing writable
PREREQ=""
# Output pre-requisites
prereqs()
{
echo "$PREREQ"
}
case "$1" in
prereqs)
prereqs
exit 0
;;
esac
TMPFILE="/run/initramfs/old-table.txt"
LOGFILE="/run/initramfs/resize-writable.log"
wait-for-root "LABEL=writable" "${ROOTDELAY:-180}" >/dev/null || true
for opt in $(cat /proc/cmdline); do
case $opt in
debug)
LOGFILE="/dev/kmsg"
;;
esac
done
writable_part="$(findfs LABEL=writable)"
syspath="$(dirname $(realpath /sys/class/block/$(basename $writable_part)))"
device="$(realpath /dev/block/$(cat $syspath/dev))"
partition=$(cat $syspath/$(basename $writable_part)/partition)
device_size="$(($(cat $syspath/size)/2))"
sum_size="$(($(grep $(basename $device)[a-z0-9] /proc/partitions|\
tr -s ' '|cut -d' ' -f4|tr '\n' '+'|sed 's/+$//')))"
get_end()
{
NUM=$1
lastpart="$(grep -cE ^'[0-9]{1,}': $TMPFILE)"
if [ "$lastpart" = "$NUM" ]; then
endsize="$(parted -ms $DEV print| grep ^/ | cut -d: -f2)"
else
# we are not at the end ! get the start of the next partition
# (minus 1 byte) instead of using the absolute end of the disk
endsize=$(($(parted -ms $DEV unit B print|grep ^$(($num+1)):|\
cut -d: -f2|sed 's/B$//')-1))
fi
echo "$endsize"
}
do_gpt()
{
DISK=$1
PARTNUM="$(sgdisk -p $DISK|grep writable|sed -r 's/^([^ ]*[ ]*){1}([^ ]*).*/\2/')"
GUID="$(sgdisk -i $PARTNUM $DISK|grep unique| sed 's/^.*: //g')"
FIRST="$(sgdisk -i $PARTNUM $DISK|grep ^First| sed 's/^.*: //g;s/ .*$//')"
echo "fixing backup GPT" >>$LOGFILE 2>&1
sgdisk --move-second-header $DISK >>$LOGFILE 2>&1
echo "Deleting partition $PARTNUM" >>$LOGFILE 2>&1
sgdisk -d $PARTNUM $DISK >>$LOGFILE 2>&1
echo "Creating partition $PARTNUM at $FIRST" >>$LOGFILE 2>&1
sgdisk -n $PARTNUM:$FIRST:0 $DISK >>$LOGFILE 2>&1
echo "Setting GUID of partition $PARTNUM to $GUID" >>$LOGFILE 2>&1
sgdisk -u $PARTNUM:$GUID $DISK >>$LOGFILE 2>&1
echo "Setting name of $PARTNUM to writable" >>$LOGFILE 2>&1
sgdisk -c $PARTNUM:writable $DISK >>$LOGFILE 2>&1
sgdisk -p $DISK >/run/initramfs/new-gpt-table.txt 2>/dev/null
}
do_mbr()
{
DEV=$1
PART=$2
endsize=$(get_end $PART)
parted -s $DEV resizepart $PART $endsize
}
free_space=$(($device_size-$sum_size))
min_free_space=$(($device_size/10))
if [ "$min_free_space" -lt "$free_space" ]; then
echo "initrd: found more than 10% free space on disk, resizing ${writable_part}" >/dev/kmsg || true
echo "initrd: partition to full disk size, see ${LOGFILE} for details" >/dev/kmsg || true
# back up the original partition table for later use or debugging
parted -ms $device unit B print >$TMPFILE 2>/dev/null
# grow our selected partition to max space available
table="$(parted -ms $device print| grep ^/| cut -d: -f6)"
case $table in
gpt)
# do_gpt needs the device name
do_gpt $device >>$LOGFILE 2>&1
;;
mbr|msdos)
# do_mbr needs the device node and partition number
do_mbr $device $partition >>$LOGFILE 2>&1
resizeopts="-f"
;;
*)
echo "unknown partition table type, not resizing" >>$LOGFILE
exit 0
;;
esac
# make sure the partitions are ready for further use
udevadm settle >>$LOGFILE 2>&1
# check the filesystem before attempting re-size
e2fsck -fy $writable_part >>$LOGFILE 2>&1
# resize the filesystem to full size of the partition
resize2fs $resizeopts $writable_part >>$LOGFILE 2>&1
fi
ogra@localhost:~$
|