Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in Log::read_head #383

Closed
Medowhill opened this issue Jan 29, 2021 · 0 comments · Fixed by #386
Closed

Bug in Log::read_head #383

Medowhill opened this issue Jan 29, 2021 · 0 comments · Fixed by #386
Assignees

Comments

@Medowhill
Copy link
Collaborator

xv6에서는 로그로부터 복구할 때 read_head에서 블록 번호만 배열에 저장한 다음 install_trans에서 저장한 번호에 해당하는 블록을 읽어 buf를 만듭니다.

read_head:

rv6/kernel/log.c

Lines 93 to 95 in 026a808

for (i = 0; i < log.lh.n; i++) {
log.lh.block[i] = lh->block[i];
}

install_trans:

struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst

반면, rv6에서는 배열에 블록 번호 대신 BufUnlocked를 저장합니다. 이로 인해 read_head에서 블록 번호로부터 BufUnlocked를 만들어 배열에 저장해야 합니다. 현재 코드에서는 블록 번호에 해당하는 BufUnlocked를 만들기 위해 buf_unforget을 호출합니다. 그러나, buf_unforget은 주어진 블록 번호에 해당하는 BufEntry가 존재하는 경우에만 Some(buf_unlocked)가 결과로 나오고, 존재하지 않는 경우에는 None이 결과로 나옵니다. 로그를 통한 복구는 부팅 시에 이루어지는 작업이므로 해당 BufEntry가 존재할 수 없고, None이 결과가 됩니다. read_head에서는 buf_unforget의 결과에 대해 unwrap을 호출하기 때문에 결국 패닉이 발생합니다.

read_head:

rv6/kernel-rs/src/fs/log.rs

Lines 110 to 113 in 026a808

for b in unsafe { &(*lh).block[0..(*lh).n as usize] } {
self.lh
.push(kernel().bcache.buf_unforget(self.dev, *b).unwrap());
}

현재의 테스트는 로그로부터 복구하는 작업이 올바르게 이루어지는지 확인할 수 없기 때문에, 위 버그는 지금까지 발견되지 않았습니다. 버그가 실재한는 사실을 확인하기 위해, commit에서 디스크에 쓰는 작업이 끝난 뒤 이미 작성한 로그를 무효화하는 줄(아래 코드)을 지운 상태에서 파일 하나를 만들고 재부팅하면 read_headunwrap에서 패닉이 발생하는 것을 확인했습니다. 또한, xv6에서 동일한 수정을 한 뒤 같은 작업을 하는 경우에는 패닉 없이 정상적으로 부팅되는 것도 확인했습니다.

unsafe { self.write_head() };

이 버그는 read_head에서 실제로 디스크를 읽어 BufUnlocked를 만들도록 수정하면 해결될 것으로 보입니다. read_head가 사용되는 곳이 로그로부터 복구하는 경우뿐이므로 다른 곳에 영향을 주지도 않습니다.

추가적으로, 로그로부터 복구하는 작업이 올바르게 진행되는지 검사하는 테스트를 추가할 필요가 있어 보입니다. 이는 별도의 이슈로 만들겠습니다.

@Medowhill Medowhill added the bug label Jan 29, 2021
@Medowhill Medowhill self-assigned this Jan 29, 2021
Medowhill added a commit to Medowhill/rv6 that referenced this issue Jan 29, 2021
Medowhill added a commit to Medowhill/rv6 that referenced this issue Jan 29, 2021
Medowhill added a commit to Medowhill/rv6 that referenced this issue Feb 1, 2021
ghost pushed a commit that referenced this issue Feb 2, 2021
386: [Closes #383] Refactoring bio.rs and log.rs r=jeehoonkang a=Medowhill

Closes #383

* `read_head`에서 `buf_unforget` 대신 `disk.read` 사용. `Arena::unforget` 삭제.
* `Buf`가 `ManuallyDrop<BufUnlocked>`를 가지게 있게 하여 `transmute` 없이 `unlock` 구현.
* 필요없는 `unsafe` 제거. `unsafe` 블록에 주석 추가.
* 가능한 경우 포인터 대신 slice 사용.

Co-authored-by: Jaemin Hong <hjm0901@gmail.com>
ghost pushed a commit that referenced this issue Feb 2, 2021
386: [Closes #383] Refactoring bio.rs and log.rs r=jeehoonkang a=Medowhill

Closes #383

* `read_head`에서 `buf_unforget` 대신 `disk.read` 사용. `Arena::unforget` 삭제.
* `Buf`가 `ManuallyDrop<BufUnlocked>`를 가지게 있게 하여 `transmute` 없이 `unlock` 구현.
* 필요없는 `unsafe` 제거. `unsafe` 블록에 주석 추가.
* 가능한 경우 포인터 대신 slice 사용.

Co-authored-by: Jaemin Hong <hjm0901@gmail.com>
ghost pushed a commit that referenced this issue Feb 2, 2021
386: [Closes #383] Refactoring bio.rs and log.rs r=Medowhill a=Medowhill

Closes #383

* `read_head`에서 `buf_unforget` 대신 `disk.read` 사용. `Arena::unforget` 삭제.
* `Buf`가 `ManuallyDrop<BufUnlocked>`를 가지게 있게 하여 `transmute` 없이 `unlock` 구현.
* 필요없는 `unsafe` 제거. `unsafe` 블록에 주석 추가.
* 가능한 경우 포인터 대신 slice 사용.

Co-authored-by: Jaemin Hong <hjm0901@gmail.com>
@ghost ghost closed this as completed in a278468 Feb 2, 2021
Gabriel4256 pushed a commit to Gabriel4256/rv6 that referenced this issue Sep 8, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant