-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathunion-mount.j2
255 lines (226 loc) · 8.82 KB
/
union-mount.j2
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#!/bin/sh -e
PREREQS="varlog"
prereqs() { echo "$PREREQS"; }
case $1 in
prereqs)
prereqs
exit 0
;;
esac
docker_inram=false
docker_inram_algo=tmpfs
docker_inram_size={{ DOCKER_RAMFS_SIZE }}
logs_inram=false
secureboot=false
bootloader=generic
in_kdump=false
varlog_size=0
# Extract kernel parameters
for x in $(cat /proc/cmdline); do
case "$x" in
Aboot=*)
bootloader=aboot
;;
docker_inram=on)
docker_inram=true
;;
docker_inram_algo=*)
docker_inram_algo="${x#docker_inram_algo=}"
;;
docker_inram_size=*)
docker_inram_size="${x#docker_inram_size=}"
;;
logs_inram=on)
logs_inram=true
;;
varlog_size=*)
varlog_size="${x#varlog_size=}"
;;
secure_boot_enable=[y1])
secureboot=true
docker_inram=true
;;
platform=*)
platform_flag="${x#platform=}"
;;
systemd.unit=kdump-tools.service)
in_kdump=true
;;
esac
done
set_tmpfs_log_partition_size()
{
if [ $varlog_size -gt 0 ]; then
# Use the varlog_size passed in from command line
varlogsize=$varlog_size
else
varlogsize=128
# set varlogsize to existing var-log.ext4 size
if [ -f ${rootmnt}/host/disk-img/var-log.ext4 ]; then
varlogsize=$(ls -l ${rootmnt}/host/disk-img/var-log.ext4 | awk '{print $5}')
varlogsize=$(($varlogsize/1024/1024))
fi
fi
# make sure varlogsize is between 5% to 10% of total memory size
memkb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
memmb=$(($memkb/1024))
minsize=$(($memmb*5/100))
maxsize=$(($memmb*10/100))
if [ $minsize -ge $varlogsize ]; then
varlogsize=$minsize
fi
if [ $maxsize -le $varlogsize ]; then
varlogsize=$maxsize
fi
}
remove_not_in_allowlist_files()
{
local allowlist_file="$1"
local targeted_dir="$2"
local allowlist_pattern_file=/tmp/allowlist_paths.pattern
# Return if the allowlist file does not exist
if ! test -f "${allowlist_file}"; then
echo "The file ${allowlist_file} is missing, failed to mount rw folder." 1>&2
exit 1
fi
# Set the grep pattern file, remove the blank line in config file
awk -v rw_dir="$targeted_dir" 'NF {print rw_dir"/"$0"$"}' ${allowlist_file} > $allowlist_pattern_file
# Find the files in the rw folder, and remove the files not in the allowlist
find ${targeted_dir} -type f | grep -v -f $allowlist_pattern_file | xargs /bin/rm -f
rm -f $allowlist_pattern_file
}
mount_docker_inram()
{
if [ "$docker_inram_algo" = "tmpfs" ]; then
echo "Creating tmpfs to extract {{ FILESYSTEM_DOCKERFS }}"
mount -t tmpfs -o "rw,nodev,size=$docker_inram_size" tmpfs "${rootmnt}/var/lib/docker"
else
echo "Creating zram to extract {{ FILESYSTEM_DOCKERFS }}"
modprobe zram num_devices=0
# create new zram device
local zid="$(cat /sys/class/zram-control/hot_add)"
local zname="zram$zid"
# attempt to use desired algorithm
if ! echo $docker_inram_algo > /sys/block/$zname/comp_algorithm 2>/dev/null; then
echo "zram algorithm $docker_inram_algo is not supported"
echo "using default instead: $(cat /sys/block/$zname/comp_algorithm)"
fi
echo $docker_inram_size > /sys/block/$zname/disksize
# create filesystem on the newly created zram block device
mkfs.ext4 -m 0 -L dockerfs -O '^has_journal' -q /dev/$zname
mount -o rw,nodev /dev/$zname "${rootmnt}/var/lib/docker"
fi
}
extract_dockerfs()
{
echo "Extracting {{ FILESYSTEM_DOCKERFS }}"
if [ -f "${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }}" ] && [ "$secureboot" = false ]; then
# Check if the file is zstd compressed
file_type=$(file -b --mime-type "${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }}")
if [ "$file_type" = "application/zstd" ]; then
echo "Detected zstd compression, extracting with pzstd..."
pzstd -d -q ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} -c | tar x --numeric-owner -C ${rootmnt}/var/lib/docker
else
echo "Using default extraction method (gzip assumed)..."
tar xz --numeric-owner -f "${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }}" -C "${rootmnt}/var/lib/docker"
fi
elif [ "$bootloader" = "aboot" ] && unzip -l "$swi_path" | grep -q {{ FILESYSTEM_DOCKERFS }}; then
# Aboot swi images also support extracting dockerfs.tar.gz directly from them
unzip -qp "$swi_path" {{ FILESYSTEM_DOCKERFS }} | tar xz --numeric-owner -C ${rootmnt}/var/lib/docker
else
# Warn but allow the system to boot to at least have ssh access
echo "No {{ FILESYSTEM_DOCKERFS }} to extract, SONiC will be broken"
fi
}
mount_docker()
{
if [ "$in_kdump" = true ]; then
# There is no point in mounting the docker filesystem in kdump environment
# Especially when there is some space mitigation in place
return
fi
if [ "$docker_inram" = true ]; then
# Create an in memory filesystem (tmpfs, zram) and extract dockerfs.tar.gz
mount_docker_inram
extract_dockerfs
else
# Mount the working directory of docker engine in the raw partition, bypass the overlay
mount --bind ${rootmnt}/host/$image_dir/{{ DOCKERFS_DIR }} ${rootmnt}/var/lib/docker
fi
}
## Mount the overlay file system: rw layer over squashfs
image_dir=$(cat /proc/cmdline | sed -e 's/.*loop=\(\S*\)\/.*/\1/')
rw_dir=${rootmnt}/host/$image_dir/rw
work_dir=${rootmnt}/host/$image_dir/work
mkdir -p "$rw_dir"
mkdir -p "$work_dir"
## Remove the files not in allowlist in the rw folder
if [ "$secureboot" = true ] && [ "$in_kdump" = false ]; then
if [ "$bootloader" = "aboot" ]; then
swi_path="${rootmnt}/host/$(sed -E 's/.*loop=([^ ]+).*/\1/' /proc/cmdline)"
unzip -q "$swi_path" allowlist_paths.conf -d /tmp
allowlist_file=/tmp/allowlist_paths.conf
else
allowlist_file=${rootmnt}/host/$image_dir/allowlist_paths.conf
fi
remove_not_in_allowlist_files "$allowlist_file" "$rw_dir"
## Remove the executable permission for all the files in rw folder except home folder
find ${rw_dir} -type f -not -path ${rw_dir}/home -exec chmod a-x {} +
fi
mount -n -o lowerdir=${rootmnt},upperdir=${rw_dir},workdir=${work_dir} -t overlay root-overlay ${rootmnt}
## Check if the root block device is still there
[ -b ${ROOT} ] || mdev -s
case "${ROOT}" in
ubi*)
mtd=$(cat /proc/cmdline | sed -e 's/.*ubi.mtd=\([0-9]\) .*/\1/')
if [ ! -f /dev/${ROOT}_0 ]; then
ubiattach /dev/ubi_ctrl -m $mtd 2>dev/null || true
fi
mount -t ubifs /dev/${ROOT}_0 ${rootmnt}/host
;;
*)
## Mount the raw partition again
mount -t ext4 ${ROOT} ${rootmnt}/host
tune2fs -m 0 -r 0 ${ROOT}
;;
esac
## Mount the docker storage path
mkdir -p ${rootmnt}/var/lib/docker
mount_docker
## Mount the boot directory in the raw partition, bypass the overlay
mkdir -p ${rootmnt}/boot
# make sure that the boot folder exists before attempting a mount
mkdir -p ${rootmnt}/host/$image_dir/boot
mount --bind ${rootmnt}/host/$image_dir/boot ${rootmnt}/boot
## Mount the /tmp directory as tmpfs
mount -t tmpfs -o rw,nosuid,nodev,size=25% tmpfs ${rootmnt}/tmp
## Mount loop device or tmpfs for /var/log
if $logs_inram; then
# NOTE: some platforms, when reaching initramfs stage, have a small
# limit of mounting tmpfs partition, potentially due to amount
# of RAM available in this stage. Therefore limiting the size
# set for tmpfs partitions.
#
# Another reason for using tmpfs /var/log partition is:
# Some platforms have a small flash and therefore the log partition takes valuable space.
# To improve the longevity of these devices storing the logs in memory will permit more
# SONiC image growth before being bottlenecked.
set_tmpfs_log_partition_size
mount -t tmpfs -o rw,nosuid,nodev,size=${varlogsize}M tmpfs ${rootmnt}/var/log
if [ -f ${rootmnt}/host/disk-img/var-log.ext4 ]; then
rm -rf ${rootmnt}/host/disk-img/var-log.ext4
fi
else
if [ -f ${rootmnt}/host/disk-img/var-log.ext4 ]; then
fsck.ext4 -v -p ${rootmnt}/host/disk-img/var-log.ext4 2>&1 | gzip -c >> /tmp/fsck.log.gz
mount -t ext4 -o loop,rw ${rootmnt}/host/disk-img/var-log.ext4 ${rootmnt}/var/log
fi
fi
## fscklog file: /tmp will be lost when overlayfs is mounted
if [ -f /tmp/fsck.log.gz ]; then
mv /tmp/fsck.log.gz ${rootmnt}/var/log
fi
## ssd-fw-upgrade log file: /tmp will be lost when overlayfs is mounted
if [ -f /tmp/ssd-fw-upgrade.log.gz ]; then
mv /tmp/ssd-fw-upgrade.log.gz ${rootmnt}/var/log
fi