Skip to content
isdnetworks
Go back

마커를 맨 마지막에 쓴다

펌웨어 설치 스크립트의 끝부분을 봤다.

flash_erase /dev/mtd0 0x1040000 0x1
nandwrite -p -s 0x1040000 /dev/mtd0 ./upgrade-marker.bin
sync

upgrade-marker.bin 을 쓴다. 그리고 이것이 맨 마지막이다.

Table of contents

Open Table of contents

마커가 맨 마지막에 있었다

앞에서 이미 네 가지를 다 썼다.

부트로더
디바이스트리
커널
루트 파일시스템

BOOT.bin 부터 rootfs.jffs2 까지 쓰고 나서 마커다. 실제 내용이 전부 들어간 뒤에 표시가 붙는 순서다.

읽다 보니 upgrade-marker.bin 의 자리가 우연이 아니었다. 어디에 두느냐가 그 마커의 뜻을 정한다.

원인 — 순서가 만드는 뜻

같은 파일을 쓰는데 앞에 두느냐 뒤에 두느냐로 의미가 갈린다.

[마커 먼저]  마커 있음 = 시작함
[마커 나중]  마커 있음 = 전부 끝남

앞에 두면 시작 표시가 되고 뒤에 두면 완료 표시가 되는데 nandwrite 로 쓰는 내용은 양쪽이 똑같다.

다음 부팅에서 이 마커를 보고 업그레이드를 다시 할지 말지를 정한다. 그러니 이 한 줄의 위치가 재시도 여부를 결정한다.

중간에 죽으면 어떻게 되나

전원이 나가거나 flash_erase 가 실패해 도중에 멈추는 상황을 놓고 보면 차이가 분명해진다.

[마커 먼저 쓴 경우]
  마커 있음 + 커널은 옛것

  "업그레이드 됐다"고 판단 → 실제로는 안 됨

[마커 나중에 쓴 경우]
  마커 없음 + 일부만 써짐

  "안 됐다"고 판단 → 다시 시도

앞에 쓰면 uImage 만 옛것인 장비가 완료로 보이고 그 상태로 계속 돈다. 뒤에 쓰면 안 된 것으로 보여 다시 시도한다.

둘 다 실패인데 한쪽만 복구 경로가 있고 그 차이를 마커의 위치 한 줄이 만든다.

완료 표시의 원칙

여기서 정리되는 원칙이 하나 있는데 완료 표시는 실제로 완료된 뒤에 쓴다는 것이다.

당연해 보이는데 앞에 쓰기가 쉽고 시작했으니 표시해 두자는 생각이 코드를 쓰는 순서와도 맞는다.

[앞에]  "시작했으니 표시해 두자"
[뒤에]  "다 됐으니 표시하자"

앞에 쓰면 중간 실패가 성공으로 보인다. 표시가 사실보다 앞서 나가는 것이라 그 뒤의 판단이 전부 어긋난다.

sync가 붙어 있었다

마커를 쓴 다음 줄에 sync 가 있다. 그런데 앞의 쓰기들에는 없다.

[앞]   플래시에 직접 씀 — 버퍼를 안 거침
[마커]  같은데 sync 를 붙임

같은 nandwrite 인데 sync 를 여기만 붙인 이유가 있을 것으로 보이고 마지막이라서로 짐작된다.

여기까지 하고 나면 사람이 전원을 내리거나 다시 켤 수 있으므로 그 전에 확실히 반영시키고 끝내겠다는 것으로 보인다.

마지막 확정 지점에만 sync 를 두는 셈이다. 앞의 것들은 뒤에 더 할 일이 남아 있어 그 사이에 반영될 여유가 있다.

재부팅이 주석 처리돼 있었다

스크립트 맨 끝이 이랬다.

rm -rf *.tar.gz

#/sbin/reboot -f &

reboot 줄이 주석이다. 자동으로 다시 켜지면 편할 텐데 일부러 막아 둔 것으로 보인다.

막아 둔 이유는 몇 가지로 짐작된다. 장비가 여러 대면 동시에 다 꺼지는 것이 곤란하다. dmesg 나 상태를 먼저 확인하고 싶을 수도 있다.

셋째가 가장 커 보인다. 잘못 써졌으면 재부팅하는 순간 안 뜬다.

[쓰기 완료]  아직 옛 커널로 돌고 있음
[재부팅]     새 것으로 뜸 — 여기가 진짜 확정

재부팅 전까지는 아직 옛 커널로 돌고 있으니 손쓸 여지가 있다. 그 마지막 순간을 사람에게 맡긴 것으로 보인다.

마지막에 패키지를 지우는 이유

끝에서 두 번째 줄이 자기 패키지를 지운다.

rm -rf *.tar.gz

장비의 저장 자리가 작으니 다 쓴 tar.gz 가 남아 있으면 다음 업그레이드 때 풀 자리가 없다. 그리고 남아 있으면 누가 또 풀어서 돌릴 수도 있다.

앞에서 본 파일별 삭제와 같은 발상으로 보이는데 다 쓴 것은 그 자리에서 없앤다는 것이다.

주의 — 꺼져 있는 사전 검사

스크립트 곳곳에 주석 처리된 덩어리가 있었다.

#    ubiattach /dev/ubi_ctrl -m 2
#    mount -t ubifs ubi1:rootfs /mnt/upgrade
#    cd /mnt/upgrade/upgrade
#    rm -rf /mnt/upgrade/upgrade/*
#    cp -rf ./xilinx/angstrom_rootfs.jffs2 /mnt/upgrade/upgrade
#    umount /mnt/upgrade
#    ubidetach -d 1 /dev/ubi_ctrl

ubiattach 로 파일시스템을 붙이고 cp 로 복사하는 방식이다. 지금 살아 있는 줄들은 플래시에 직접 쓰므로 방식을 바꾼 흔적으로 보인다.

앞쪽에도 주석 덩어리가 있었다.

#    if [ ! -e /dev/ubi_ctrl ];then
#            echo "File system isn't UBI, Please update ubi package first!"
#            exit 1
#    fi

이쪽은 사전 검사이고 /dev/ubi_ctrl 이 있는지 보고 아니면 안내한 뒤 exit 1 한다.

방식을 바꾸면서 /dev/ubi_ctrl 검사가 필요 없어졌을 수는 있다. 다만 사람에게 무엇을 먼저 하라고 알려 주던 문구가 함께 사라진 것은 남는다.

주석으로 남기면 되살리기는 쉽다. 대신 runme.sh 안에 그대로 보이므로 읽는 사람이 도는 줄로 착각한다.

정리


Share this post on:

Previous Post
100%가 안 되면 어디까지 되는지
Next Post
하나 고쳤더니 다음 것이 나왔다