/usr/lib/criu/scripts/systemd-autofs-restart.sh is in criu 3.6-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #!/bin/bash
#
# This script can be used as a workaround for systemd autofs mount migration.
# The problem is that systemd is a clever guy: before mounting of actual file
# system on top of autofs mount, it first checks that device number of autofs
# mount is equal to the one, stored in sytemd internals. If they do not match,
# systemd ignores kernel request.
# The problem happens each time autofs is restored (new device number for
# autofs superblock) and can't be properly solved without some kind of "device
# namespaces", where device number can be preseved.
# But some of systemd services can be painlessly restarted. Like
# proc-sys-fs-binfmt_misc.
#
# Usage:
# criu restore <options> --action-script $(pwd)/scripts/systemd-autofs-restart.sh
#
[ "$CRTOOLS_SCRIPT_ACTION" == "post-resume" ] || exit 0
if [ ! -n "$CRTOOLS_INIT_PID" ]; then
echo "CRTOOLS_INIT_PID environment variable is not set"
exit 1
fi
if [ ! -d "/proc/$CRTOOLS_INIT_PID" ]; then
echo "Process with CRTOOLS_INIT_PID=$CRTOOLS_INIT_PID doesn't exist"
exit 1
fi
NS_ENTER=/bin/nsenter
[ ! -x $NSENTER ] || NS_ENTER=/usr/bin/nsenter
if [ ! -x $NS_ENTER ]; then
echo "$NS_ENTER binary not found"
exit 2
fi
JOIN_CT="$NS_ENTER -t $CRTOOLS_INIT_PID -m -u -p"
# Skip container, if it's not systemd based
[ "$($JOIN_CT basename -- $($JOIN_CT readlink /proc/1/exe))" == "systemd" ] || exit 0
AUTOFS_SERVICES="proc-sys-fs-binfmt_misc.automount"
bindmount=""
function remove_bindmount {
if [ -n "$bindmount" ]; then
$JOIN_CT umount $bindmount
$JOIN_CT rm -rf $bindmount
bindmount=""
fi
}
trap remove_bindmount EXIT
function get_fs_type {
local mountpoint=$1
local top_mount_id=""
local top_mount_fs_type=""
while IFS='' read -r line; do
# Skip those entries which do not match the mountpoint
[ "$(echo $line | awk '{print $5;}')" = "$mountpoint" ] || continue
local mnt_id=$(echo $line | awk '{print $1;}')
local mnt_parent_id=$(echo $line | awk '{print $2;}')
local mnt_fs_type=$(echo $line | sed 's/.* - //g' | awk '{print $1;}')
# Skip mount entry, if not the first one and not a child
[ -n "$top_mount_id" ] && [ "$mnt_parent_id" != "$top_mount_id" ] && continue
top_mount_id=$mnt_id
top_mount_fs_type=$mnt_fs_type
done < "/proc/$CRTOOLS_INIT_PID/mountinfo"
if [ -z "$top_mount_fs_type" ]; then
echo "Failed to find $mountpoint mountpoint"
return 1
fi
echo $top_mount_fs_type
return 0
}
function bind_mount {
local from=$1
local to=$2
$JOIN_CT mount --bind $from $to && return 0
echo "Failed to bind mount $from to $to"
return 1
}
function save_mountpoint {
local mountpoint=$1
local top_mount_fs_type=""
top_mount_fs_type=$(get_fs_type $mountpoint)
if [ $? -ne 0 ]; then
echo "$top_mount_fs_type"
return
fi
# Nothing to do, if no file system is on top of autofs
[ "$top_mount_fs_type" = "autofs" ] && return
bindmount=$($JOIN_CT mktemp -d)
if [ -z "$bindmount" ]; then
echo "Failed to create temporary directory"
return 1
fi
# No need to unmount fs on top of autofs:
# systemd will does it for us on service restart
bind_mount $mountpoint $bindmount || $JOIN_CT rm -rf $bindmount
}
function restore_mountpoint {
local mountpoint=$1
[ -n "$bindmount" ] || return
# Umount file system, remounted by systemd, if any
top_mount_fs_type=$(get_fs_type $mountpoint)
if [ $? -ne 0 ]; then
echo "$top_mount_fs_type"
return
fi
# Nothing to do, if no file system is on top of autofs
if [ "$top_mount_fs_type" != "autofs" ]; then
$JOIN_CT umount $mountpoint || echo "Failed to umount $mountpoint"
fi
# Restore origin file system even if we failed to unmount the new one
bind_mount $bindmount $mountpoint
remove_bindmount
}
function restart_service {
local service=$1
local mountpoint=$($JOIN_CT systemctl show $service -p Where | sed 's/.*=//g')
if [ -z "$mountpoint" ]; then
echo "Failed to discover $service mountpoint"
return
fi
# Try to move restored bind-mount aside and exit if Failed
# Nothing to do, if we Failed
save_mountpoint $mountpoint || return
$JOIN_CT systemctl restart $service
if [ $? -ne 0 ]; then
echo "Failed to restart $service service"
return
fi
echo "$service restarted"
# Try to move saved monutpoint back on top of autofs
restore_mountpoint $mountpoint
}
for service in $AUTOFS_SERVICES; do
status=$($JOIN_CT systemctl is-active $service)
if [ $status == "active" ]; then
restart_service $service
else
echo "$service skipped ($status)"
fi
done
exit 0
|