Skip to content

Commit 6d8f576

Browse files
byu343Shuotian Cheng
authored andcommitted
[Arista]: Add support to convert vfat file system to ext4 (#201)
This commit will convert the existing file system of flash drive on Arista switches from VFAT to EXT4 in the booting of SONiC. It will take the whole flash and therefore remove the recovery partition. There is a check in the script making sure that the conversion operation will not happen on a non-Arista switch or if the existing file system is not VFAT.
1 parent 7bd9050 commit 6d8f576

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

build_debian.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/linux-image-3.16.0-4-amd64_*.de
113113
## Update initramfs for booting with squashfs+aufs
114114
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
115115

116+
## Hook into initramfs: change fs type from vfat to ext4 on arista switches
117+
sudo mkdir -p $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/
118+
sudo cp files/initramfs-tools/arista-convertfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs
119+
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs
120+
sudo cp files/initramfs-tools/mke2fs $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs
121+
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs
122+
116123
## Hook into initramfs: after partition mount and loop file mount
117124
## 1. Prepare layered file system
118125
## 2. Bind-mount docker working directory (docker aufs cannot work over aufs rootfs)
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#!/bin/sh
2+
3+
case $1 in
4+
prereqs)
5+
exit 0
6+
;;
7+
esac
8+
9+
set -e
10+
# set -x
11+
total_mem=$(free | awk '/^Mem:/{print $2}')
12+
tmpfs_size=$(( $total_mem / 20 * 17 ))
13+
free_mem_thres=$(( $total_mem / 20 * 18 ))
14+
tmp_mnt='/mnt/ramdisk-convfs'
15+
root_mnt='/mnt/root-convfs'
16+
root_dev=''
17+
flash_dev=''
18+
block_flash=''
19+
aboot_flag=''
20+
backup_file=''
21+
22+
# Get the fullpath of flash device, e.g., /dev/sda
23+
get_flash_dev() {
24+
for dev in $(ls /sys/block); do
25+
local is_mmc=$(echo "$dev" | grep 'mmcblk.*boot.*' | cat)
26+
if [ -n "$is_mmc" ]; then
27+
continue
28+
fi
29+
local devid=$(realpath "/sys/block/$dev/device")
30+
local is_device=$(echo "$devid" | grep '^/sys/devices/' | cat)
31+
local is_flash=$(echo "$devid" | grep "$block_flash" | cat)
32+
if [ -n "$is_device" -a -n "$is_flash" ]; then
33+
flash_dev="/dev/$dev"
34+
return 0
35+
fi
36+
done
37+
return 1
38+
}
39+
40+
# Wait for root_dev to be ready
41+
wait_for_root_dev() {
42+
local try_rounds=30
43+
while [ $try_rounds -gt 0 ]; do
44+
if [ -e "$root_dev" ]; then
45+
return 0
46+
fi
47+
sleep 1
48+
try_rounds=$(( $try_rounds - 1 ))
49+
done
50+
return 1
51+
}
52+
53+
# Alway run cleanup before exit
54+
cleanup() {
55+
if grep -q "$root_mnt" /proc/mounts; then
56+
umount "$root_mnt"
57+
fi
58+
if grep -q "$tmp_mnt" /proc/mounts; then
59+
umount "$tmp_mnt"
60+
fi
61+
[ -e "$root_mnt" ] && rmdir "$root_mnt"
62+
[ -e "$tmp_mnt" ] && rmdir "$tmp_mnt"
63+
}
64+
trap cleanup EXIT
65+
66+
notification() {
67+
cat << EOF
68+
A failure happend in modifying the root file system which stopped the upgrade. Manual interventions are needed to fix the issue. Note that:
69+
1) files in the old root file system may have been lost and the old partition table may have been corrupted;
70+
2) The files in the old root file system were copied to $tmp_mnt;
71+
3) The old partition table was dumped to the file $tmp_mnt/$backup_file by sfdisk;
72+
4) Quitting the current shell will lose all files mentioned above permanently.
73+
EOF
74+
}
75+
76+
run_cmd() {
77+
if ! eval "$1"; then
78+
echo "$2"
79+
notification
80+
sh
81+
exit 1
82+
fi
83+
}
84+
85+
# Extract kernel parameters
86+
set -- $(cat /proc/cmdline)
87+
for x in "$@"; do
88+
case "$x" in
89+
block_flash=*)
90+
block_flash="${x#block_flash=}"
91+
;;
92+
Aboot=*)
93+
aboot_flag="${x#Aboot=}"
94+
esac
95+
done
96+
root_dev="$ROOT"
97+
98+
#Check aboot and root_dev is vfat
99+
[ -z "$aboot_flag" ] && exit 0
100+
if [ -z "$root_dev" ]; then
101+
echo "Error: root device name is not provided"
102+
exit 1
103+
fi
104+
if ! wait_for_root_dev; then
105+
echo "Error: timeout in waiting for $root_dev"
106+
exit 1
107+
fi
108+
blkid | grep "$root_dev.*vfat" -q || exit 0
109+
110+
111+
# Get flash dev name
112+
if [ -z "$block_flash" ]; then
113+
echo "Error: flash device info is not provided"
114+
exit 1
115+
fi
116+
if ! get_flash_dev; then
117+
echo "Error: flash device is not found"
118+
exit 1
119+
fi
120+
121+
# Check memory size for tmpfs
122+
free_mem=$(free | awk '/^Mem:/{print $4}')
123+
if [ "$free_mem" -lt "$free_mem_thres" ]; then
124+
echo "Error: memory is not enough"
125+
exit 1
126+
fi
127+
128+
# Backup partition table
129+
mkdir -p "$root_mnt"
130+
mount "$root_dev" "$root_mnt"
131+
backup_file=backup.$(date +%Y-%m-%d.%H-%M-%S)
132+
sfdisk -d "$flash_dev" > "$root_mnt/$backup_file"
133+
134+
# Check total size of files in root
135+
total_file_size=$(du -s "$root_mnt" | awk '{print $1}')
136+
if [ "$total_file_size" -gt "$tmpfs_size" ]; then
137+
echo "Error: total file size is too large"
138+
exit 1
139+
fi
140+
141+
# Create tmpfs, and copy files to tmpfs
142+
mkdir -p "$tmp_mnt"
143+
mount -t tmpfs -o size="${tmpfs_size}k" tmpfs "$tmp_mnt"
144+
cp -a "$root_mnt/." "$tmp_mnt/"
145+
umount "$root_mnt"
146+
147+
#### Lines below will modify the root file system, so any failure will be trapped to shell for manual interventions.
148+
149+
# Create a new partition table (content in flash_dev will be deleted)
150+
err_msg="Error: repartitioning $flash_dev failed"
151+
cmd="echo ';' | sfdisk $flash_dev"
152+
run_cmd "$cmd" "$err_msg"
153+
154+
sleep 5
155+
err_msg="Error: timeout in waiting for $root_dev after repartition"
156+
cmd="wait_for_root_dev"
157+
run_cmd "$cmd" "$err_msg"
158+
159+
err_msg="Error: formatting to ext4 failed"
160+
cmd="mke2fs -t ext4 -m2 -F -O '^huge_file' $root_dev"
161+
run_cmd "$cmd" "$err_msg"
162+
163+
err_msg="Error: mounting $root_dev to $root_mnt failed"
164+
cmd="mount -t ext4 $root_dev $root_mnt"
165+
run_cmd "$cmd" "$err_msg"
166+
167+
err_msg="Error: copying files form $tmp_mnt to $root_mnt failed"
168+
cmd="cp -a $tmp_mnt/. $root_mnt/"
169+
run_cmd "$cmd" "$err_msg"
170+

files/initramfs-tools/mke2fs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/sh
2+
#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2.
3+
4+
PREREQ=""
5+
6+
prereqs()
7+
{
8+
echo "$PREREQ"
9+
}
10+
11+
case $1 in
12+
prereqs)
13+
prereqs
14+
exit 0
15+
;;
16+
esac
17+
18+
. /usr/share/initramfs-tools/hook-functions
19+
20+
copy_exec /sbin/mke2fs
21+
copy_exec /sbin/sfdisk
22+
copy_exec /sbin/fdisk
23+
24+
fstypes="ext4"
25+
26+
for type in $fstypes; do
27+
prog="/sbin/mkfs.${type}"
28+
if [ -h "$prog" ]; then
29+
link=$(readlink -f "$prog")
30+
copy_exec "$link"
31+
ln -s "$link" "${DESTDIR}/$prog"
32+
elif [ -x "$prog" ] ; then
33+
copy_exec "$prog"
34+
else
35+
echo "Warning: /sbin/mkfs.${type} doesn't exist, can't install to initramfs, ignoring."
36+
fi
37+
done
38+
39+
for type in $fstypes; do
40+
prog="/sbin/fsck.${type}"
41+
if [ -h "$prog" ]; then
42+
link=$(readlink -f "$prog")
43+
copy_exec "$link"
44+
ln -s "$link" "${DESTDIR}/$prog"
45+
elif [ -x "$prog" ] ; then
46+
copy_exec "$prog"
47+
else
48+
echo "Warning: /sbin/fsck.${type} doesn't exist, can't install to initramfs, ignoring."
49+
fi
50+
done

0 commit comments

Comments
 (0)