#!/bin/bash ############################################################################### # # # IPFire.org - A linux based firewall # # Copyright (C) 2022 IPFire Team # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # # # ############################################################################### # # This script is supposed to repair any broken RAID installations # where the system has been booted from only one of the RAID devices # without the software RAID being activated first. # # This script does as follows: # # * It tries to find an inactive RAID called "ipfire:0" # * It will then destroy any devices that are still part of this RAID. # This is required because if the RAID is being assembled correctly, # data from the disk that has NOT been mounted will be replicated # back to the device that has been changed. That causes that any # data that has been written to the mounted disk will be lost. # To avoid this, we will partially destroy the RAID. # * We will then erase any partition tables and destroy any filesystems # on the devices so that they do not get accidentially mounted again. # * The system will then need to be rebooted where the RAID will be # mounted again in a degraded state which might take some extra # time at boot (the system stands still for about a minute). # * After the system has been booted up correctly, we will re-add # the devices back to the RAID which will resync and the system # will be back to its intended configuration. find_inactive_raid() { local status local device local arg local args while read -r status device args; do if [ "${status}" = "INACTIVE-ARRAY" ]; then for arg in ${args}; do case "${arg}" in name=ipfire:0) echo "${device}" return 0 ;; esac done fi done <<< "$(mdadm --detail --scan)" return 1 } find_root() { local device local mp local fs local args while read -r device mp fs args; do if [ "${mp}" = "/" ]; then echo "${device:0:-1}" return 0 fi done < /proc/mounts return 1 } find_raid_devices() { local raid="${1}" local IFS=, local device for device in $(mdadm -v --detail --scan "${raid}" | awk -F= '/^[ ]+devices/ { print $2 }'); do echo "${device}" done return 0 } destroy_everything() { local device="${1}" local part # Destroy the RAID superblock mdadm --zero-superblock "${device}" # Wipe the partition table wipefs -a "${device}" # Wipe any partition signatures for part in ${device}*; do wipefs -a "${part}" done } raid_rebuild() { local devices=( "$@" ) cat > /etc/rc.d/rcsysinit.d/S99fix-raid </dev/null # Destroy any useful data on all remaining RAID devices local device for device in ${devices[@]}; do # Skip root [ "${device}" = "${root}" ] && continue destroy_everything "${device}" done &>/dev/null # Re-add devices to the RAID raid_rebuild "${device}" return 0 } main "$@" || return $?