Git’te Yama Uygularken Oluşan Çakışmaları Çözmek


Yazma iznimizin olmadığı depodaki projeye katkı verme işlemini yama dosyası oluşturarak yaparız. Yama dosyaları karşı tarafa yaptığımız değişiklikleri insan okuyabilir şekilde özetler. Bu konu hakkında kısa bir yazı yazmışım, buradan bakabilirsiniz.

Github üzerinden geliştirdiğim kendi projelerime olan katkıları kabul ederken terminal kullanmadan, web sayfası üzerinden hallediyorum.

Linux çekirdeğinde her takım farklı alt dizinlere baktığından ve çoğu github kullanmadığından işlemleri konsol üzerinden yapmak gerekiyor.

Linux çekirdeğinde uzunca bir süredir büyük bir yama  setini kabul ettirmeye çalışıyorum. İnsanlık için küçük olabilir ama benim için büyük demeden geçmeyelim. Yamanın konusu özetle bellek üzerinde büyük bir baskı olduktan sonra swapten dönerken, ihtiyaç duyulmayan sayfaları da swapten belleğe getirip büyük sayfa oluşturarak, performans sağlamak.

Bu yama uzun bir sürece girdiğinden, linux çekirdeği sürekli güncelleniyor ve benim değişikliklerim deponun eski halindeki gibi kalıyor. Bu durumda karşı taraf uygulamaya çalışırken çakışma oluşacak, yama bu nedenle reddedilecek.

Eskiden hep küçük değişiklikler yaptığımdan ve daha kısa süreçte bittiğinden, kendi yamamı güncel depoya uygulama ihtiyacı duymadım. Her satırı tekrar kontrol ederek yeniden oluşturuyordum. Yama büyük olduğunda işler böyle olmadı. Her satırı tekrar oluşturmak çok zor ve derlemede hata almıyorsam bile mantıksal hata yapma ihtimalim çok yüksek.

Değişiklikleri uygulamadan önce git apply --check yama_dosyası şeklinde yamanın uygulanabilir olup olmadığını kontrol edebiliriz. Eğer git apply yama_dosyası komutunu verirsek, yamayı commit yapmadan depoya ekler. Bu durumda değişiklikler commitlenmediği için de git diff ile farkları görebiliriz. Bu bize yama dosyasını ekleyip, commit yapmayarak elle başka değişiklikler yapmaya olanak verir. Tüm değiştirmek istediğimiz dosyalar bittikten sonra kendimiz git commit -a komutuyla değişiklikleri loglayabiliriz.

Yamanın commit yapılarak depoya eklenmesini istiyorsak git am < yama_dosyası şeklinde uygulamalıyız.

Eğer daha önceden yaptığımız commitlerde düzenlemeler istiyorsak git rebase harika bir araç. Onunla ilgili daha önceden bir yazı yazmıştım, buradan bakabilirsiniz.

Yama uygularken geçenlerde karşılaştığım durum, yamanın (muhtemelen) güncel depoyla uyumlu olmamasından kaynaklıyordu. Hata aldığım makine çok sık kullandığım bir makine değildi, belki daha önceki başka bir şeyden kaynaklanıyor da olabilir. Hata mesajı şu şekilde:

Applying: mm: add tracepoint for scanning pages
error: include/trace/events/huge_memory.h: already exists in working directory
error: patch failed: mm/huge_memory.c:2673
error: mm/huge_memory.c: patch does not apply
Patch failed at 0001 mm: add tracepoint for scanning pages
The copy of the patch that failed is found in:
   /home/ebru/linux-stable/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

Bunu görünce daha önceden aynı commitler depoda vardı, bu yüzden bir yerde indeksleri tutuluyor düşündüm. mv linux-stable/.git/rebase-apply ..path/ ile rebase-apply dizinini başka bir yere taşıdım. Tekrar yamayı uygulamaya çalıştım yine aynı hatayı aldım (kaldırdığım dizin tekrar oluştu).

Bunun çözümü şu şekilde hatayı aldıktan sonra, git apply linux-stable/.git/rebase-apply/patch --reject komutunu veriyoruz. Bu sayede yamanın çakışma oluşturmayan kısımları depoda oluşturuluyor.

Checking patch include/linux/mm.h...
Checking patch include/trace/events/huge_memory.h...
error: include/trace/events/huge_memory.h: already exists in working directory
Checking patch mm/huge_memory.c...
Hunk #1 succeeded at 30 (offset 1 line).
Hunk #2 succeeded at 2270 (offset 53 lines).
Hunk #3 succeeded at 2307 (offset 53 lines).
Hunk #4 succeeded at 2319 (offset 53 lines).
Hunk #5 succeeded at 2327 (offset 53 lines).
....
       ........
Hunk #13 applied cleanly.
Hunk #14 applied cleanly.
Hunk #15 applied cleanly.
Hunk #16 applied cleanly.
Rejected hunk #17.
Hunk #18 applied cleanly

Bu şekilde uygulanan/uygulanamayan kısımları özetliyor. Uygulamada sorun oluşturan her dosya için uygulanamayan kısımları dosya_adı.rej uzantılı diff dosyası oluşturarak bize gösteriyor. Bu dosyaları git status ile bakarsak görebiliriz. Bu süreçte depo aslında rebase etme gibi git apply sürecinde oluyor. Yamanın uygulanmayan kısımlarına .rej uzantılı dosyalardan bakıp, kendimiz dosyaları açıp değişiklikleri yapıyoruz. git status ile tekrar bakıp eklememiz gereken dosyaları git add ile ekledikten git am --resolved ile işlemi sonlandırıyoruz. Bu şekilde çakışma oluşan yama dosyalarını depoya uygulamış olduk.

Çakışma çözme işlemini bu yazıdan okuyarak öğrendim. Umarım benim yazım da faydalı olmuştur.

8 Eylül 2015

Posted In: çekirdek, Gezegen, git, git am, git apply, github, kernel, linux, yama

Linux Kernel Ekibiyle Staj

Geçtiğimiz yaz haziran sonunda mezun oldum. Mezuniyetten sonra bir işe girip çalışmak, her gün işe gidip gelmek, birkaç ay işim dışında bir şeye bakmamak, sonrasında iş temposuyla birlikte neler yapabileceğime karar vermek gibi bir düşüncem vardı. Ancak tabi ki böyle olmadı :).

Ağustos başında Google İrlanda ofisinden iş görüşmesi için e-posta aldım, benim ile başlangıç bir telefon görüşmesi yapmak istediklerini söylediler. Hemen kabul ettim. İlk üç aşamayı geçtim, son görüşme için Irlanda'ya gittim ancak son görüşmede başarılı olamadım. Sorular beklediğim gibi değildi, internetten çalıştığım gibi de değildi.

Ben evde son görüşmeye hazırlanırken Gnome OPW için başvurular da başlamıştı. Ben daha önce ilk Gnome'un araçlarına sonra da Linux Kernel'a başvurmuştum. Gnome'a katkı verirken katkı vermek için masaüstü bilgisayarınızda ortam oluşturmak zor. En son Fedora 19'un alfa sürümünü kullanmak zorunda kalmam ve alfanın hiç kullanışlı olmaması üzerine katkı vermeyi sonlandırdım :). Aslında jhubild'de kullanabiliriz ama onda ortamı hazırlaması .. bana bir tane geliştiricisi o zamanlar Fedora beta sürümü varken, beta kullanmamı önermişti, beta yine kullanılabilirdi ancak bir sonraki sürüme geçtiklerinde alfa kullanmak zorunda kalmam pek iyi olmadı. Bir de Gnome Continuous var, onu yeni gördüm ama henüz denemedim.

Linux Kernel'a katkı verdiğim sene aslında alınmayı beklemiştim gerçekten ama olmadı. Bu dönem başvuru süresi 2 ay gibi uzundu :), geçen sene 3 hafta gibi bir süreydi. Necdet hoca "Aslında sen başvursan çok şey yaparsın" dedi, ben de başvurdum ve alındım :). Alınmayı gerçekten beklemiyordum ve çok güzel bir sürpriz oldu.

Şimdi Rik van Riel ile birlikte bellek yönetimi üzerinde çalışıyorum. Bellek yönetimi katkı vermeye başlamanın en zor olduğu kısımlardan biri, çünkü çekirdeğin temel fonksiyonlarını içeriyor ve daha karmaşık. Başvurduğunuz projeye göre staj sürecinde ne kadar yama gönderebileceğinizin sayısı da değişiyor. Ben projem zor olduğundan, 4 ayda otuz satır yazabilir miyim derken şimdiden bir yamayı kabul ettiler bile :).

Linux kaynak kodunda bellek yönetimi ile ilgili dizin mm/. Eğer güncel mm dizinini takip etmek istiyorsak da Linus Torvalds'ın kullandığı dalı değil de linux-next'i takip etmek gerekiyor. Yamaları Andrew Morton kabul ediyor ve günlük olarak etiketliyor. Güncel linux-next'i nasıl takip edeceğinizi görmek için buraya bakabilirsiniz.

Anladığım kadarıyla, Linux'ta bellek yönetimi üzerine çoğunlukla Redhat ekibi bakıyor, çünkü birçok sunumu ve belgeyi o ekip hazırlamış. Ben yamaları gönderirken mm dizini bakıcılarına baktığımda genelde @redhat.com alan adlı hesaplar var. Yamaları vger.kernel.org ve  akpm@linux-foundation.org listelerine gönderdiğim için de çok mutluyum. O kadar büyük listelerdeki insanların kodlara bakıyor olması oldukça heyecanlı :).

Üzerinde çalıştığım proje ise, bellek üzerinde 2kB/4kB kadar boyutlarda olabilen sayfaların dışında bir de büyük sayfalar (huge page) var. Onların boyutları ise 2MB/4MB. Peki neden büyük sayfalara ihtiyaç duyuyoruz? Çünkü sayfalar büyük olduğunda sayfa tabloları da büyük oluyor ve bir süreç için verileri bellekten atma/belleğe getirme miktarı azalıyor. Eğer sayfalar 4MB'tan büyük olursa verimsiz oluyor.

Sistemin swap kullanması gerektiğinde büyük sayfalar normal boyutlu sayfalara parçalanıyor (2kB/4kB) ve o şekilde swap alanına yerleştiriliyor. Sorun şu ki; swap alanından belleğe tekrar geri getirilmek istendiğinde büyük sayfa olarak değil, normal boyutlu sayfalar olarak getiriliyorlar bu durumda eski verim sağlanamıyor, aynı zamanda burada izlenmesi gereken bir algoritmaya da karar verilmeli. Çünkü bir süreç swap kullanıyor diyelim, ve swapte olan bir veriye ihtiyaç duyuldu, sadece tek bir verinin bulunduğu sayfa 2kB, ancak bunun yerine 2MB büyük sayfa getirmek her zaman yararlı olmaz. Burada karar verilmesi gereken noktalar var.

Geçtiğimiz dönem kod ve belge okumak üzerine geçti. Bir tane de yama gönderdim. Sadece okunabilir sayfaları büyük sayfalar şeklinde birleştirmek için. Yamayı burada görebilirsiniz.

Bundan sonraki bir süre ise; "daha önce hiç okuma/yazma isteği almamış, henüz fiziksel belleğe eşlenmemiş, sadece sanalda bulunan, bir süre sonra ilk kez okuma izni aldığında fiziksel belleğe eşlenen sayfalar" var, bunlara zero page deniliyor, bunlar üzerinde çalışacağım. Eğer sayfa içerisinde veri yoksa, ilk okuma isteği aldığında çekirdek bunu sıfırlarla dolu bir sayfa olarak üretiyor. Bunları da büyük sayfalara dahil etmek üzere çalışacağım. Aynı zamanda (emin değilim), Documentation dizininde de belgelendirme yapmam gerekecek. Muhtemelen birkaç işim daha var ancak henüz ben bilmiyorum, danışmanımla işleri bitirdikçe yenisini alma şeklinde ilerliyoruz. Henüz başlamadığımız işlerden de şuna bir ara bakarız şeklinde konuşuyoruz.

Staj sürecinde birkaç Türkçe yazı daha yazacağım (yazmadı) :).

1 Şubat 2015

Posted In: bellek yönetimi, collapse huge page, Gezegen, huge page, kernel, linux, staj, swap, yama, zero page

WP Twitter Auto Publish Powered By : XYZScripts.com