첫 Linux 기여

첫 Linux 기여

Linux git 에 내 이름이 올라갔다! 하하
보통 말하는 contribute 을 한 것은 아니고, 그냥 bug report 이다.
Linux git 에는 그래도 bug 가 해결되는 commit 이 올라가면 reporter 도 올려주더라.

linux-git-1
(Linux git 에서 볼 수 있다. )

이런 사소한 것도, 사실 내가 다 한건 아니고 우리 팀 고수형(헌진이형 압도적 감사!)의 도움을 받아 하게 되었고, 문제 자체는 다른 쪽에서 해결해달라고 요청이 들어오면서 보게 되었다.
본 포스트에서는 해결 요청이 들어온 문제점과 분석 과정부터 linux git 에 올리게 된 내용까지 쓰고자 한다.

  1. 발단: hyper-v instance 가 죽는다고??
  2. 추적 (상): 어떤 코드가 hyper-v instance 를 죽였누
  3. 추적 (하): linux 버그네... 나쁜 commit 넣은 범인 찾아라 (네놈추)
  4. 보고: 직접 문의, 버그 질라에 버그 올리기
  5. 해결: Linux git 에 올라가기 / 버그 질라 닫기

추가. 리눅스 버저닝

--

1. 발단, hyper-v instance 가 죽는다고??

어느날 연락이 왔다.
우리가 개발하는 TmaxOS에는 windows app 을 실행시켜주는 호환 기능이 있다.
그런데, hyper-v instance 에 올라간 TmaxOS 에서 이 호환 기능을 수행하면 hyper-v 가 죽는다더라.
(응? app 이 죽는 것도 아니고 hyper-v 가 죽는다고....??!!)

죽는 장면을 녹화해서 올릴라고 했는데, 재현이 안된다.
특정 kernel version 과 config 조합도 까먹었고, hyper-v 가 바뀌었을 수도 있다.
묘사를 글로하자면, hyper-v 에 올린 linux에서 특정 코드를 실행하면 hyper-v가 그냥 꺼진다.
kernel 에 log 도 남아있지 않다. 패닉이 나는 것도 아니다.

이러저러한 실험을 해보았는데, 요약하자면.
hyper-v 에 32bit linux 4.19.20 을 올리고, 특정 코드를 돌리면 죽는다.

  • hyper-v 대신에 vmware 를 사용하면 문제가 없다. (hyper-v 가 문제네)
  • 32bit linux 대신에 64bit linux를 올리면 문제가 없다.
  • 버전을 기준으로 탐색해본 결과, 4.18 에서 되고, 4.19-rc1 에서 안된다.
    (그 사이에 들어간 커밋에 문제가 있다!!)

범인 찾기에 앞서서 상황설명을 더 하기위해 특정 코드 가 무엇인지 살펴보자.

2.추적(상), 어떤 코드가 hyper-v instance를 죽였누

원인을 찾기 위해 실제로 어떤 코드가 동작하다가 죽는지 찾아보았다.
코드는 내 github에서 확인 가능하다.
(hyper-v 죽였던 코드 에서 볼 수 있다.)

코드를 잠시만 설명하자면,

void set_fs_register(unsigned int val){
  __asm__ __volatile__(
      "push %%eax\n\t\
       movl %0, %%eax\n\t\
       movl %%eax, %%fs\n\t\
       pop %%eax" ::"r"(val): "%eax");

}

fs register 값을 바꾸는 요 코드를 pthread파서 여러 thread 애서 수행하면 된다. 하하.

나머지 코드들은 저 fs register에 올바른 값을 넣기 위해 규칙에 맞게 수정하는 것이 끝이다.
(그 규칙은 본 포스트에서 다룰 내용은 아니고, 궁금한 사람들은 LDT를 검색해 보시라.)

fs register는 x86 아키텍쳐에 존재하는 register로 사실 현대 Linux에서는 사용을 하지 않는다.
windows에서는 이 fs register에다가 TEB(Thread Environment Block) 이라는 global 구조체의 주소를 저장한다.
언제, 어디서든 fs register 에 접근을 하면 TEB를 볼 수 있는 것이다.
Thread가 바뀌면 당연히 이 주소도 바뀐다.

어쨋든 이 코드는 linux 기반 시스템에서 windows binary를 돌릴 때 사용하고 있었고,
hyper-v가 죽으면 안되는데 죽었다.

어떤 코드가 죽이는지는 알았는데, 이것만 가지고는 무엇이 문제인지 알아낼 수는 없었다.
그래서, linux 버전과 vm 을 바꿔가며 테스트를 해 본 것이었다.

3.추적(하), linux 버그였네. 범인을 찾아라.

맨 위에서 설명했지만, 이리저리 테스트를 해보니, hyper-v 와 특정 linux 에서만 문제가 있었다.
이제 범인을 찾자.
linux에 나쁜 커밋이 있는 건 확실하고, hyper-v에도 있을 수도 있다. (hyper-v는 내가 볼 수 없으니..)

Linux 소스 트리에는 linux/arch/x86/hyperv/ directory 가 있다. 역시나 여기가 가장 의심스럽다.
x86 에서만, hyperv에서만 발생하니 말이다.
여기서 4.18 -> 4.19-rc1 사이의 커밋들을 보자.

linux-gitlog

많은 사람들이 익숙할만한 github mirror의 history 화면이다.

사실 저 뒤에 조금 더 있지만, 어쨌든 의심스러운 commit 이 보인다.
내용과 사람을 확인해보자.

hyperv_commit

우선 microsoft 사람이다!
내용을 이해는 잘 못하겠지만, vm/pm mapping 관련하여 뭘 flush 한덴다.
주소를 찾아가는 우리의 상황과 무언가 연관이 있을 것 같다.

문의를 해보자. (네놈추!!)

4. 보고, 직접 문의 & 버그 질라에 올리기

우선은 확실히 문제를 모르기 때문에 메일을 썼다.
동시에 버그질라에도 올렸다.

버그질라는 linux 의 모든 버그들을 올리는 곳이다.
linux에 기여하고 싶으면 가서 이슈들 보고, 해결하면 된다.

bugzilla
지금은 다 해결되어서 이렇게 되었다.
여기 에서 볼수있다.
누구나 이슈를 찾으면 올릴 수 있다.
대충쓰면 안된다고 가이드도 잘 되어있더라.

결론부터 얘기하자면, tianyu에게 메일을 써서 잘 해결이 되었다.
그 메일의 내용을 요약하자면 아래와 같다.

나: 요러요러한 상황이다. 네놈이 의심스러운데 한번 확인해줄래?
tianyu: 로그랑 kernel config 를 달라.
나: ㅇㅋ
tianyu: page table isolation 이란 관련있는 문제같은데, nopti 주고 확인해볼래?
나: 해봤더니 이거 아닌데....??
tianyu: 흠 내 문제였네. 고쳐서 올리고 알려줄게. 리포팅해줘서 감사.
나: 오키, 감사.
tianyu: 버그질라 좀 닫아주셈.
나: 오키!

tianyu: 내 문제였네. 고쳐서 올리고 알려줄게. 리포팅해줘서 감사.

녜놈이 범인이 맞았군! 하하.

5. 해결: Linux git 에 올라가기 / 버그 질라 닫기

tianyu 가 범인이 맞았고, 알아서 해결도 했다.
덕분에(?) 우리 제품의 문제도 해결이 되었다.

해결한 커밋은 linux git 중 tip repository (x86 과 core kernel에 관련한 repository인 것 같다.)로 들어갔다.
브랜치는 x86-urgent. 해당 commit 이 들어가면서 tip-bot 이 메일을 보내줬다.

tip_mail

커밋에 대한 설명이다. 역시 reporter로 내가 등록되어있고, cc로 linus도 있다. (신기)
뭐... tianyu가 작성한 설명을 읽어보니 hyperv tlb flush 추가 후, 32bit에서 overflow나는 것을 처리를 안했나 보다.
Guest virtual adderss로 메모리가 채워진덴다.
어쨰서, fs register를 건드린 것이 이 문제를 야기했는지는 아직도 모르겠다.
(hyper-v 코드를 모르니 당연한건가...)

그리고 나서 4.14 , 4.19 , 5.2 버전에 각각 커밋이 들어갓다고 메일이 왔다.

이 메일은 5.2에 들어간 것이다. 이렇게 3가지가 왔다.
linux_patch_mail

tip repo에 들어가고 mainline 이랑 계속 유지가 되는 (백포팅을 하는?) 버전에 각각 꼽혀들어가는 것 같다.

그리고, 버그질라도 닫아달라고 연락이 와서 resolve로 처리했다.

이상. 간접적으로 나마 경험한 linux contribution 썰이다.

--

추가. linux의 version 관리

이번에 처음으로 linux 버전이 어떻게 관리하는지 보았다.
역시, git을 만든 사람들이 쓰는 git 이란.

이제까지 보았던 것들과 다른 점은 mainline은 minor만 찍고 앞으로 계속 나간다는 것이었다.
minor version tag를 찍고 브랜치를 내는 것이 아니라, repo를 분리시켜 거기에 따로 관리를 한다.
linux git repo를 보면 태그들은 minor 버전 까지만 있고, patch 버전은 없다.
그래서, 메일이 3개씩 오는거였구만!

대규모 프로젝트는 이렇게 해야하는 것이구만.