Computer >> Hướng Dẫn Máy Tính >  >> Xử Lý Sự Cố >> Android

Cách cập nhật Android Kernel lên Linux Stable mới nhất

Chúng tôi đã có hướng dẫn về Android kernel như "How to Build a Custom Kernel" và "Best Custom Kernels for Android", nhưng hôm nay sẽ chỉ cách upstream kernel của bạn với Linux stable mới nhất.

Hãy biết đây là việc nâng cao - nếu chưa bao giờ compile kernel, làm theo hướng dẫn "How to Build a Custom Kernel" link trên, hướng dẫn này liên quan cherry-pick và merge commit từ Linux-stable kernel mới nhất với Android kernel trước khi compile.

Upstream Android kernel lên Linux stable mới mang lại lợi ích lớn: cập nhật commit bảo mật và bugfix mới - chúng tôi sẽ giải thích ưu/nhược điểm sau.

Linux-Stable kernel là gì?

Cách cập nhật Android Kernel lên Linux Stable mới nhất

Linux-stable như tên gọi là nhánh stable của Linux kernel. Nhánh kia là "mainline" - master branch. Tất cả dev Linux kernel xảy ra ở mainline, quy trình chung:

  1. Linus Torvalds nhận patch từ maintainer 2 tuần.
  2. Sau 2 tuần, release rc1 (ví dụ 4.14-rc1).
  3. Mỗi tuần 6-8 tuần tiếp theo, release RC khác (4.14-rc2, 4.14-rc3...), chỉ chứa fix bug và regression.
  4. Khi deemed stable, release tarball download trên kernel.org (ví dụ 4.14).

LTS kernels là gì?

Mỗi năm, Greg chọn 1 kernel maintain 2 năm (LTS) hoặc 6 năm (extended LTS). Dành cho sản phẩm cần ổn định (Android phone, IoT). Quy trình giống hệt trên, chỉ lâu hơn. Hiện có 6 LTS kernel (xem trên kernel.org releases page):

  • 4.14 (LTS), maintain bởi Greg Kroah-Hartman
  • 4.9 (LTS), maintain bởi Greg Kroah-Hartman
  • 4.4 (eLTS), maintain bởi Greg Kroah-Hartman
  • 4.1 (LTS), maintain bởi Sasha Levin
  • 3.16 (LTS), maintain bởi Ben Hutchings
  • 3.2 (LTS), maintain bởi Ben Hutchings

Lợi ích upstream Android kernel lên Linux Stable?

Khi vulnerability quan trọng bịكشف/fix, stable kernel nhận fix đầu tiên. Android kernel của bạn sẽ an toàn hơn trước tấn công, lỗi bảo mật, bug chung.

Linux stable bao gồm fix driver Android không dùng, có thừa không?

Có và không, tùy định nghĩa "phần lớn". Linux kernel có nhiều code không dùng trong Android, nhưng không bảo đảm không conflict khi merge version mới! Hiểu rằng hầu như không ai build mọi phần kernel, kể cả distro phổ biến Ubuntu/Mint. Điều này KHÔNG nghĩa không nên lấy fix vì CÓ fix cho driver bạn CHẠY. Ví dụ arm/arm64 và ext4 - kiến trúc và filesystem phổ biến nhất Android. Từ 4.4.78 (Oreo CAF tag mới nhất) đến 4.4.121 (upstream tag mới nhất), số commit:

nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 | wc -l
2285
nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 arch/arm | wc -l
58
nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 arch/arm64 | wc -l
22
nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 fs/ext4 | wc -l
18

Phần tốn thời gian nhất là bring up ban đầu; khi đã up-to-date, merge release mới mất rất ít thời gian, thường không quá 100 commit. Lợi ích (ổn định hơn, bảo mật tốt hơn cho user) buộc phải làm quy trình này.

Cách Merge Linux Stable Kernel vào Android Kernel

Đầu tiên xác định kernel version thiết bị Android chạy.

Dù tầm thường, cần biết bắt đầu từ đâu. Chạy lệnh trong kernel tree:

make kernelversion

Trả về version bạn đang ở. 2 số đầu dùng xác định branch (ví dụ linux-4.4.y cho kernel 4.4) và số cuối xác định version bắt đầu merge (ví dụ 4.4.21, merge 4.4.22 tiếp theo).

Lấy kernel source mới nhất từ kernel.org

kernel.org lưu source mới nhất trong repo linux-stable. Cuối trang có 3 link fetch. Theo kinh nghiệm, mirror Google nhanh nhất nhưng kết quả có thể khác. Chạy:

git remote add linux-stable https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
git fetch linux-stable

Quyết định merge toàn bộ kernel hay cherry-pick commit

Tiếp theo, chọn merge commit hay cherry-pick. Ưu/nhược điểm và khi nào dùng:

LƯU Ý: Nếu kernel source dạng tarball, sẽ cần cherry-pick, không thì sẽ conflict hàng ngàn file vì git populate history dựa trên upstream thuần túy, không phải OEM/CAF đã thay đổi. Bỏ qua sang bước 4.

Cherry-picking:

Ưu:

  • Dễ resolve conflict vì biết chính xác commit nào gây issue.
  • Dễ rebase vì mỗi commit riêng biệt.
  • Dễ bisect nếu gặp vấn đề.

Nhược:

  • Mất thời gian hơn vì pick từng commit.
  • Hơi khó biết commit từ upstream ở nhìn đầu tiên.

Merge

Ưu:

  • Nhanh hơn vì không chờ clean patches merge.
  • Dễ thấy commit từ upstream vì committer là upstream maintainer, không phải bạn.

Nhược:

  • Resolve conflict khó hơn vì cần git log/git blame tìm commit gây conflict, không báo trực tiếp.
  • Rebase khó vì không rebase được merge, sẽ đề xuất cherry-pick từng commit. Tuy nhiên không nên rebase thường, dùng git revert và git merge khi có thể.

Khuyến nghị: cherry-pick trước tìm conflict/problem commit, rồi merge, sau đó revert problem commit để update sau dễ hơn (merge nhanh sau up-to-date).

Thêm commit vào source, từng version một

Phần quan trọng nhất: từng version một. CÓ THỂ có patch gây vấn đề trong upstream series, gây lỗi boot hoặc break sound/charging (giải thích ở tips). Làm incremental version change quan trọng vì dễ tìm issue trong 50 commit hơn 2000+ commit. Chỉ khuyến nghị full merge khi biết tất cả problem commit và conflict resolution.

Cherry-picking

Format:

git cherry-pick <previous_tag>..<next_tag>

Ví dụ:

git cherry-pick v3.10.73..v3.10.74

Merge

Format:

git merge <next_tag>

Ví dụ:

git merge v3.10.74

Khuyến nghị track conflict trong merge commit bằng cách xóa marker #.

Cách Resolve Conflicts

Không thể hướng dẫn step-by-step resolve mọi conflict, cần kiến thức C, nhưng vài gợi ý:

Nếu merge, tìm commit gây conflict. 2 cách:

  1. git log -p v$(make kernelversion)..<latest_tag> lấy thay đổi giữa version hiện tại và upstream mới. Flag -p cho thay đổi mỗi commit để xem.
  2. Chạy git blame trên file lấy hash từng commit ở vùng đó. Chạy git show --format=fuller xem committer từ mainline/stable, Google, hay CodeAurora.
  • Kiểm tra đã có commit chưa. Vendor như Google/CAF có thể backport fix critical (như Dirty COW) từ upstream, backport của họ conflict với upstream. Chạy git log --grep="<part_of_commit_message>" xem có trả về gì. Nếu có, skip commit (cherry-pick: git reset --hard && git cherry-pick --continue) hoặc ignore conflict (xóa <<<<<< và giữa ====== và >>>>>>).
  • Kiểm tra backport làm hỏng resolution. Google/CAF backport patch stable không có. Stable adapt resolution mainline commit cho vắng mặt patch Google backport. Xem mainline commit bằng git show <hash> (mainline hash có trong commit message của stable commit). Nếu backport làm hỏng, discard changes hoặc dùng version mainline (thường cần làm).
  • Đọc commit làm gì, xem vấn đề đã fix chưa. CAF có thể fix bug độc lập upstream, nghĩa là overwrite fix của họ cho upstream hoặc discard.

Ngoài ra, có thể chỉ do thêm của CAF/Google/OEM, trường hợp shuffle code.

Luôn đảm bảo final diff match upstream bằng cách chạy 2 cửa sổ:

git diff HEAD
git diff v$(make kernelversion)..$(git tag --sort=-taggerdate -l v$(make kernelversion | cut -d . -f 1,2)* | head -n1)

Bật rerere

Git có feature rerere (Reuse Recorded Resolution) - khi detect conflict, ghi nhớ cách bạn resolve để reuse sau. Rất hữu ích cho chronic rebaser cả merge và cherry-pick, chỉ cần git add . && git <merge|cherry-pick> --continue khi redo upstream bringup vì conflict resolved như trước.

Bật bằng lệnh trong kernel repo:

git config rerere.enabled true

Cách git bisect khi gặp compiler hoặc runtime error

Với số commit lớn thêm vào, rất có thể gây compiler/runtime error. Thay vì bỏ cuộc, dùng git bisect built-in tìm root cause! Lý tưởng: build và flash mỗi kernel version khi thêm để bisect nhanh hơn nếu cần, nhưng bisect 5000 commit cũng ổn.

Git bisect lấy range commit, từ nơi issue present đến nơi không present, chia đôi range, cho build/test và báo good/bad. Lặp cho đến khi ra commit gây issue. Lúc đó fix hoặc revert.

  1. Start bisect: git bisect start
  2. Label current revision bad: git bisect bad
  3. Label revision good: git bisect good <sha1>
  4. Build với revision mới
  5. Dựa kết quả (issue present hay không), báo git: git bisect good HOẶC git bisect bad
  6. Lặp bước 4-5 cho đến khi tìm thấy problem commit!
  7. Revert hoặc fix problem commit.

LƯU Ý: Merger cần tạm chạy git rebase -i <good_sha> apply tất cả patch lên branch để bisect proper, vì bisect với merge trong place thường checkout lên upstream commit, nghĩa là không có commit Android-specific. Có thể deep dive hơn nếu yêu cầu nhưng tin tôi, cần thiết. Khi xác định problem commit, revert hoặc rebase vào merge.

KHÔNG squash upstream updates

Nhiều dev mới muốn làm này vì "cleaner" và "easier" manage. Điều này tệ vì:

  • Mất authorship. Bất công với dev khác khi credit bị gạt cho work của họ.
  • Bisect impossible. Squash series commit, issue trong series thì không thể biết commit nào gây issue trong squash.
  • Future cherry-pick khó hơn. Cần rebase với squashed series, khó/bất khả thi biết conflict từ đâu.

Subscribe Linux Kernel mailing list để update kịp thời

Để nhận thông báo khi có upstream update, subscribe linux-kernel-announce list. Cho phép nhận email mỗi khi kernel mới release để update và push nhanh nhất.