리눅스 커널 기여(Contribution) - 패치 작성 및 패치 반영(Upstream) 확인하기

AustinKim의 이미지

이전 시간에는 리눅스 커널 기여(Contribution) 하기 전에 준비해야 할 사항을 소개했습니다.
- gmail 계정 생성
- mutt 설치 및 설정

이번 시간에는 커널 패치를 작성해보고 패치를 리눅스 매인테이너(Maintainer)에게 보내는 과정을 소개합니다.
그리고 업스트림(Upstream)된 패치를 확인하는 방법도 말씀드리겠습니다.

<< 오류 코드 확인하기 >>

먼저 패치를 작성하기 전 커널 코드를 볼까요?
참고로 다음 함수는 AMD/PowerPlay 드라이버입니다.

 
[drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c]
01 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
02 {
03	struct amdgpu_device *adev = hwmgr->adev;
04 
05 	uint32_t index = SMN_MP1_SRAM_START_ADDR +
06 			 SMU8_FIRMWARE_HEADER_LOCATION +
07 			 offsetof(struct SMU8_Firmware_Header, Version);
08
09 	if (hwmgr == NULL || hwmgr->device == NULL)
10 		return -EINVAL;
11 
12 	cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
13 	hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
14 	pr_info("smu version %02d.%02d.%02d\n",

먼저 03번째 줄 코드를 보겠습니다.

 
03	struct amdgpu_device *adev = hwmgr->adev;

위 코드 왼쪽 부분을 눈으로 따라가 봅시다.
struct pp_hwmgr 타입인 hwmgr 포인터의 adev 필드를 struct amdgpu_device 구조체 타입인 adev에 저장합니다.

뭐가, 문제란 소리지?

조금만 더 읽어주세요. 다음 09~10번째 줄 코드를 분석하겠습니다.

 
09 	if (hwmgr == NULL || hwmgr->device == NULL)
10 		return -EINVAL;


smu8_start_smu() 함수 인자로 전달된 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL이면
-EINVAL를 반환합니다.

여기까지 코드를 분석하고 나면 '뭐가 문제지?'란 생각이 들 수 있습니다. 하지만 논리적인 오류가 있습니다.

09~10번째 줄 코드와 같이 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL을 체크한 다음에
다음 코드를 실행했어야 합니다.
03 struct amdgpu_device *adev = hwmgr->adev;

'hwmgr' 포인터가 NULL이면 03번째 줄에서 NULL Pointer Dereference(NULL 포인터 역참조)로 커널 패닉이 먼저 발생합니다.

<< 패치 코드 작성하기 >>

오류 코드를 확인한 다음에 패치 코드를 작성했습니다.

 
[drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c]
01 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
02 {
03 	struct amdgpu_device *adev;
04 
05 	uint32_t index = SMN_MP1_SRAM_START_ADDR +
06 			 SMU8_FIRMWARE_HEADER_LOCATION +
07 			 offsetof(struct SMU8_Firmware_Header, Version);
08 
09 	if (hwmgr == NULL || hwmgr->device == NULL)
10 		return -EINVAL;
11 
12 	adev = hwmgr->adev;
13 
14 	cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
15 	hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
16 	pr_info("smu version %02d.%02d.%02d\n",

09~10번째 줄 코드와 같이 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL을 먼저 체크한 다음에
다음 12번째 줄 코드를 실행합니다.

 
12 	adev = hwmgr->adev;


이제 패치 코드 포멧으로 확인해보겠습니다.
 
austindh.kim~/src/linux_kernel_source/linux-next$ git diff 
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
index 8189fe4..4728aa2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
 
 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
 {
-       struct amdgpu_device *adev = hwmgr->adev;
+       struct amdgpu_device *adev;
 
        uint32_t index = SMN_MP1_SRAM_START_ADDR +
                         SMU8_FIRMWARE_HEADER_LOCATION +
                         offsetof(struct SMU8_Firmware_Header, Version);
 
-
        if (hwmgr == NULL || hwmgr->device == NULL)
                return -EINVAL;
 
+       adev = hwmgr->adev;
+
        cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
        hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
        pr_info("smu version %02d.%02d.%02d\n", 

<< 패치 커밋 생성하기 >>

이제는 리눅스 커널 메인테이너에게 보낼 커밋 패치를 작성해보겠습니다.
먼저 'git status' 명령어를 입력해볼까요?

 
austindh.kim~/src/linux_kernel_source/linux-next$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
        modified:   drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c


이번에는 커밋을 하나 생성합니다.
 
austindh.kim~/src/linux_kernel_source/linux-next$ git add drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c		
austindh.kim~/src/linux_kernel_source/linux-next$ git commit -m "drm/amdgpu: Move null pointer dereference check"


커밋에 대한 설명이 필요하니 'git commit --amend' 명령어를 입력해 패치 내용을 추가합니다.
 
austindh.kim~/src/linux_kernel_source/linux-next$ git commit --amend 
 
  1 drm/amdgpu: Move null pointer dereference check
  2
  3 Null pointer dereference check should have been checked, 
  4 ahead of below routine.
  5		struct amdgpu_device *adev = hwmgr->adev;
  6 
  7 With this commit, it could avoid potential NULL dereference.
  8 # Please enter the commit message for your changes. Lines starting
  9 # with '#' will be ignored, and an empty message aborts the commit.
 10 #
 11 # Date:      Thu Aug 30 17:07:04 2019 +0900
 12 #
 13 # On branch master
 14 # Your branch is ahead of 'origin/master' by 1 commit.
 15 #   (use "git push" to publish your local commits)
 16 #
 17 # Changes to be committed:
 18 #   modified:   drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
 19 #

다음 3~7번째 줄 메시지를 추가했습니다. 패치가 무엇인지 정확히 기입했습니다.

 
  1 drm/amdgpu: Move null pointer dereference check
  2
  3 Null pointer dereference check should have been checked, 
  4 ahead of below routine.
  5		struct amdgpu_device *adev = hwmgr->adev;
  6 
  7 With this commit, it could avoid potential NULL dereference.


이번에는 'git log -p' 명령어를 입력해 소스 내역과 커밋을 함께 확인합시다.
 
austindh.kim~/src/linux_kernel_source/linux-next$ git log -p
commit 27b1f563c69f6a4af66ea8ccd8a1643c072b8299
Author: Austin Kim <austindh.kim@gmail.com>
Date:   Thu Aug 29 17:08:38 2019 +0900
 
    drm/amdgpu: Move null pointer dereference check
 
    Null pointer dereference check should have been checked,
    ahead of below routine.
            struct amdgpu_device *adev = hwmgr->adev;
 
    With this commit, it could avoid potential NULL dereference.
 
Signed-off-by: Austin Kim <austindh.kim@gmail.com>
---
 drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
 
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
index 8189fe4..4728aa2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
 
 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
 {
-       struct amdgpu_device *adev = hwmgr->adev;
+       struct amdgpu_device *adev;
 
        uint32_t index = SMN_MP1_SRAM_START_ADDR +
                         SMU8_FIRMWARE_HEADER_LOCATION +
                         offsetof(struct SMU8_Firmware_Header, Version);
 
-
        if (hwmgr == NULL || hwmgr->device == NULL)
                return -EINVAL;
 
+       adev = hwmgr->adev;
+
        cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
        hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
        pr_info("smu version %02d.%02d.%02d\n",

이번에는 'git format-patch -1' 명령어를 입력해 패치 파일을 하나 생성합니다.

 
austindh.kim~/src/linux_kernel_source/linux-next$ git format-patch -1
0001-drm_amdgpu_Move_null_pointer_dereference_check.patch

ls '파일명' 포멧으로 명령어를 입력하니 '0001-drm_amdgpu_Move_null_pointer_dereference_check.patch' 파일이 생성됐음을 확인할 수 있습니다.

 
austindh.kim~/src/linux_kernel_source/linux-next$ ls 
0001-drm_amdgpu_Move_null_pointer_dereference_check.patch

이번에는 './scripts/checkpatch.pl' 스크립트를 실행해 패치 코드의 포멧을 확인합니다.

 
austindh.kim~/src/linux_kernel_source/linux-next$ ./scripts/checkpatch.pl 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch
 
0001-drm_amdgpu_Move_null_pointer_dereference_check.patch has no style problems, please review.
 
NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

이제 mutt 프로그램을 사용해 작성한 패치 세트를 커널 메인테이너에게 송부합니다.

 
austindh.kim~/src/linux_kernel_source/linux-next$ mutt -H 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch 

<< 패치 확인하기 >>

아래 커널 메일링 리스트 아카이브 사이트에 가보면,
https://lkml.org/lkml/2019/8/30/644

제가 올린 패치를 확인할 수 있는데 drm/amdgpu subsystem maintainer께서 다음과 같은 커맨드를 하셨음을 알 수 있습니다.

 
   Applied.  thanks!
 
   Alex

커맨트 내용은 다음과 같습니다.

 
From	Alex Deucher <>
Date	Fri, 30 Aug 2019 11:09:43 -0400
Subject	Re: [PATCH] drm/amdgpu: Move null pointer dereference check
share
On Fri, Aug 30, 2019 at 8:43 AM Austin Kim <austindh.kim@gmail.com> wrote:
>
> Null pointer dereference check should have been checked,
> ahead of below routine.
>         struct amdgpu_device *adev = hwmgr->adev;
>
> With this commit, it could avoid potential NULL dereference.
>
> Signed-off-by: Austin Kim <austindh.kim@gmail.com>
 
Applied.  thanks!
 
Alex
 
> ---
>  drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> index 8189fe4..4728aa2 100644
> --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> @@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
>
>  static int smu8_start_smu(struct pp_hwmgr *hwmgr)
>  {
> -       struct amdgpu_device *adev = hwmgr->adev;
> +       struct amdgpu_device *adev;
>
>         uint32_t index = SMN_MP1_SRAM_START_ADDR +
>                          SMU8_FIRMWARE_HEADER_LOCATION +
>                          offsetof(struct SMU8_Firmware_Header, Version);
>
> -
>         if (hwmgr == NULL || hwmgr->device == NULL)
>                 return -EINVAL;
>
> +       adev = hwmgr->adev;
> +
>         cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
>         hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
>         pr_info("smu version %02d.%02d.%02d\n",
> --
> 2.6.2
>

3일 후에 아래 사이트에서 가보니,
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/

제가 작성한 패치가 리눅스 커널 메인 소스 코드에 반영(Upstream)된 것을 확인할 수 있습니다.

위치
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=9c9284f9cee9052da4cad575da8dc5f2bbb31065&fbclid=IwAR17yKXJDCQMmR595PQ3JszAADTXVjmInVyVgVDoqqEv9amWNPKzAbPNsys

리눅스 커널 프로젝트 Contribution(기여)에 관심이 있는 분은 이 포스팅의 글을 참고하시면 좋을 것 같습니다.

(개인블로그)
http://rousalome.egloos.com/

Forums: 
파이썬3의 이미지

제가 C언어를 몰라서 이 글타래를 이해는 못했지만,,,
그 느낌만은 진짜 멋있습니다!!! 그저 순수하게 +1 좋아요를 누르고 싶어요!!!
리눅스를 좋아해주셔서 정말 감사드립니다^^^

[크롬북 우분투 18.04에서 댓글을 적었어요]

AustinKim의 이미지

이렇게 리눅스를 좋아하시는 분이 있어 기쁩니다.

(개인블로그)
http://rousalome.egloos.com

황병희의 이미지

진심으로 축하드립니다! 그리고 감사드립니다^^^

[크롬북 우분투 18.04에서 적었어요]

댓글 첨부 파일: 
첨부파일 크기
Image icon 스크린샷, 2019-09-07 22-18-47.png281.4 KB

--
ㄱㅅㅎㄴㄷ!

AustinKim의 이미지

제가 올린 패치의 리눅스 커널 메일링 리스트 '인증 샷'까지 올려주셨군요.
감사합니다.

(개인블로그)
http://rousalome.egloos.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.