PART="$1"
MNT_POINT="$2"
log "[Info] Deleting btrfs snapshot"
- "$MOUNT" -o remount,rw "${MNT_POINT}"
+ # we have to delete /fota/RO_update subvolume form root volume
+ # so ensure that root volume is mounted
+ if ! "$UMOUNT" "$MNT_POINT"; then
+ log "[Error] Unable to umount $MNT_POINT"
+ return 1
+ fi
+ if ! "$MOUNT" -o subvolid=5,rw "$PART" "$MNT_POINT"; then
+ log "[Error] Unable to mount $PART root subvolume to: $MNT_POINT"
+ return 1
+ fi
+ # delete subvolume /fota/RO_update containing checkpoint data
"$BTRFS" subvolume delete "$MNT_POINT/fota/RO_update"
+ # delete /fota directory, as it is no longer needed
+ # because data was already restored
rm -rf -- "$MNT_POINT/fota"
+ if ! "$UMOUNT" "$MNT_POINT"; then
+ log "[Error] Unable to umount $MNT_POINT"
+ return 1
+ fi
+ # mount default volume
+ if ! "$MOUNT" "$PART" "$MNT_POINT"; then
+ log "[Error] Unable to mount default subvolume $PART to $MNT_POINT"
+ return 1
+ fi
}
restore_btrfs_snapshot() {
PART="$1"
MNT_POINT="$2"
- if [ ! -d "$MNT_POINT/fota/RO_update" ]; then
- log "[Info] btrfs snapshot not found"
- return
- fi
- if "$BTRFS" subvolume list "$MNT_POINT/fota/RO_update"; then
+ DEST_DIR="$MNT_POINT/ROOTFS"
+
+ if [ -d "$MNT_POINT/fota/RO_update" ] && "$BTRFS" subvolume list "$MNT_POINT/fota/RO_update"; then
+ # There is snapshot form previously failed update
+ # Use snapshot as source data.
log "[Info] Got previous snapshot."
- # remove files from mountpoint because they will be restored from snapshot
- # it is necessary otherwise files created during os-upgrade will be still there
- for var in $(ls "$MNT_POINT" | grep -vE 'fota'); do
- rm -rf -- "$MNT_POINT/$var"
- done
- # remove special directories /dev /proc /sys content
- # it is needed because "btrfs subvolume snapshot" copies some fies from this directories
- rm -rf -- "$MNT_POINT/fota/RO_update/dev/"* "$MNT_POINT/fota/RO_update/proc/"* "$MNT_POINT/fota/RO_update/sys/"*
- # restore files from snapshot
- cp -a -- "$MNT_POINT/fota/RO_update/"* "$MNT_POINT"
- delete_btrfs_snapshot "$PART" "$MNT_POINT"
+ SOURCE_DIR="$MNT_POINT/fota/RO_update"
+ # root volume 5 has to be set as default otherwise /ROOTFS subvolume can not be deleted
+ # as it is default subvolume
+ if ! "$BTRFS" subvolume set-default "$MNT_POINT"; then
+ log "[Error] Unable to set $DEST_DIR as default subvolume"
+ return 1
+ fi
+ "$BTRFS" subvolume delete "$DEST_DIR"
+ rm -rf "$DEST_DIR"
+ elif [ ! -d "$MNT_POINT/ROOTFS" ]; then
+ # There is no /ROOTFS subvolume, create it and set is as default one.
+ # This will execute during first update when data on root volume 5 exist.
+ # After this update /ROOTFS will be default subvolume. Automatically mounted by mount.
+ # Use / (root volume 5) as source data.
+ log '[Info] Create initial /ROOTFS subvolume'
+ SOURCE_DIR="$MNT_POINT"
else
+ # There is no data to restore because there was not previous update attempts.
+ # Howether data is stored in /ROOTFS instead off inside root volume 5 /
+ # Therefore there is no need to restore anything so remove any leftover data
+ # and proceed with the update.
log "[Info] Removing leftover data from previous snapshot."
rm -rf -- "$MNT_POINT/fota"
+ return 0
+ fi
+ if ! "$BTRFS" subvolume snapshot "$SOURCE_DIR" "$DEST_DIR"; then
+ log "[Error] Unable to create snapshot from: $SOURCE_DIR to $DEST_DIR"
+ return 1
fi
+ # Remove special directories /dev /proc /sys content
+ # it is required because "btrfs subvolume snapshot" copies some files from this directories
+ rm -rf -- "$DEST_DIR/proc/"* "$DEST_DIR/sys/"*
+
+ # Make $DEST_DIR (/ROOTFS) as new root (/).
+ # From now on it will become new default filesystem mounted by mount command.
+ if ! "$BTRFS" subvolume set-default "$DEST_DIR"; then
+ log "[Error] Unable to set $DEST_DIR as default subvolume"
+ return 1
+ fi
+ if [ -d "$MNT_POINT/fota" ]; then
+ delete_btrfs_snapshot "$PART" "$MNT_POINT"
+ # Remount root volume 5 because delete_btrfs_snapshot will mount default subvolume
+ # which is /ROOTFS.
+ if ! "$UMOUNT" "$MNT_POINT"; then
+ log "[Error] Unable to umount $MNT_POINT"
+ return 1
+ fi
+ if ! "$MOUNT" -o subvolid=5,rw "$PART" "$MNT_POINT"; then
+ log "[Error] Unable to mount $PART root subvolume to: $MNT_POINT"
+ return 1
+ fi
+ fi
+ # delete all files in root volume except new rootfs /ROOTFS
+ for var in "$MNT_POINT"/* "$MNT_POINT"/.[!.]*; do
+ test "$var" = "$MNT_POINT/ROOTFS" && continue
+ rm -rf -- "$var"
+ done
}
LABEL=${1}
PARTITION=${2}
DIRECTORY=${3}
- if ! "${MOUNT}" -o rw "${PARTITION}" "${DIRECTORY}"; then
+ # mount btrfs root subvolume
+ if ! "${MOUNT}" -o rw,subvolid=5 "${PARTITION}" "${DIRECTORY}"; then
log "[Error] Cannot mount ${PARTITION} into ${DIRECTORY}"
return 1
fi
- if ! "$MKDIR" -p "${DIRECTORY}/fota"; then
- log "[Error] Cannot create directory for btrfs snapshot"
- return 1
- fi
log "[Debug] Mounted ${PARTITION} as btrfs" "${INT_LOG_FILE}"
}
return 1
fi
restore_checkpoint "${PARTITION}" "${DIRECTORY}"
- # restore deletes snapshot directory
- "$MKDIR" -p "$DIRECTORY/fota"
- "$BTRFS" subvolume snapshot "$DIRECTORY" "$DIRECTORY/fota/RO_update"
+ # Create new checkpoint
+ if ! "$MKDIR" -p "$DIRECTORY/fota"; then
+ log "[Error] Unable to create $DIRECTORY/fota dir."
+ return 1
+ fi
+ if ! "$BTRFS" subvolume snapshot "$DIRECTORY/ROOTFS" "$DIRECTORY/fota/RO_update"; then
+ log "[Error] Unable to create snapshot from $DIRECTORY/ROOTFS to $DIRECTORY/fota/RO_update"
+ retun 1
+ fi
+ # mount /ROOTFS partition instead of root volume
+ if ! "$UMOUNT" "${PARTITION}"; then
+ log "[Error] Cannot umount ${PARTITION}"
+ return 1
+ fi
+ if ! "$MOUNT" "${PARTITION}" "${DIRECTORY}"; then
+ log "[Error] Cannot mount ${PARTITION} into ${DIRECTORY}"
+ return 1
+ fi
+
else
"${MOUNT}" "${PARTITION}" "${DIRECTORY}"
log "[Info] Unsupported filesystem ${FSTYPE} on ${PARTITION}" "${INT_LOG_FILE}"