Kernel reverse bisecting – Μια αξέχαστη εμπειρία

ΑΥΤΗ Η ΔΗΜΟΣΙΕΥΣΗ ΕΧΕΙ ΓΙΝΕΙ ΠΑΝΩ ΑΠΟ ΕΝΑ ΧΡΟΝΟ ΠΡΙΝ!

Καθότι το bug triaging έχει μόλις τελειώσει και επειδή έχω αναφερθεί και παλιότερα στο ότι, ούτε προγραμματιστής είμαι, ούτε επαγγελματίας kernel developer ή κάτι παρόμοιο, θα γράψω εδώ την «αξέχαστη» (για μένα) εμπειρία στην οποία (μόνος μου αποφάσισα και) μπήκα πρόσφατα.

Πραγματικά, ήταν μια διαδικασία που μπορεί να προσφέρει διάφορα συναισθήματα, όπως θυμό, απογοήτευση και αποθάρρυνση και ξανά απογοήτευση, μέχρι που στο τέλος έρχεται η επιτυχία και ξεχνάει κάποιος όλα τα προηγούμενα. Βέβαια από όλο αυτό το πιο αξιόλογο είναι εκείνο που μένει και δεν είναι άλλο από τη γνώση.

Αυτά έχει το active testing

Και όταν εδώ λέω «active» εννοώ να έχεις εγκαταστήσει μια διανομή και να την τεστάρεις για σφάλματα σχεδόν καθημερινά. Όχι την εγκατέστησα και την αναβαθμίζω μια φορά στις δυο εβδομάδες και μετά κλείνω τον υπολογιστή. Αυτό περισσότερο το λέω στον εαυτό μου, γιατί το έχω κάνει κι εγώ σε κάποιες εκδόσεις/διανομές.
Όταν λοιπόν τεστάρεις συνεχώς, όλο και κάτι θα βρεις. Αυτό που εγώ βρήκα, ήταν ένα bug στον πυρήνα. Σιγά ρε μεγάλε, βρήκες ένα bug και ; 1.000.000 bugs έχει ή αποκτά κάθε μέρα που περνά ο πυρήνας.
Ακριβώς αυτό. Μέσα από αυτό το ένα bug με το οποίο αποφάσισα να ασχοληθώ πιο ενεργά από άλλες φορές, και όχι απλά να το αναφέρω και να αποχωρήσω, πλέον δείχνω απεριόριστο respect σε όσους ασχολούνται με kernel debugging / bug triaging.. κλπ. Πολύ δουλειά λέμε.

Το πρόβλημα και η αποσφαλμάτωση

Πρώτα απ’ όλα έχουμε το ίδιο το πρόβλημα το οποίο οφείλουμε να εντοπίσουμε τι το δημιουργεί. Στην δική μου περίπτωση ήταν ένα αποτυχημένο resume από hibernation. Και σιγά την λειτουργία δηλαδή, δεν την χρησιμοποιώ και ποτέ, απλά αποφάσισα ότι θέλω να ασχοληθώ ενεργά με αυτό και να το λύσω. Ήταν σίγουρα κάτι στον πυρήνα ή σε κάποιον οδηγό (που συμπεριλαμβάνεται στον πυρήνα) ή σε κάποια συσκευή που δεν είναι συμβατή, ή στο BIOS ή στο ACPI ή σε κάποιο builtin module… για πολλή σιγουριά λέμε, έτσι;
Καταρχήν για το hibernation υπάρχει συγκεκριμένο τεστ που μπορεί να τρέξει κάποιος/α για να δει αν λειτουργεί σωστά ή όχι

sudo -i
cd /sys/power/
echo core > pm_test
echo disk > state

με το που δώσουμε την τελευταία εντολή ξεκινά η διαδικασία του hibernate και resume. Στην «ανάνηψη» λοιπόν, η οθόνη μου ήταν απλά «νεκρή» και δεν μπορούσα να την επαναφέρω, παρά μόνο με hard reboot (κουμπάκι κι έτσι). Το core στην δεύτερη εντολή υποδηλώνει ότι θέλουμε να τρέξουμε ένα full hibernation test. Υπάρχουν άλλα τέσσερα επίπεδα με το μικρότερο να είναι το freezer, όπου απλά «παγώνει» και επαναφέρει κάποιες διεργασίες. Το σημαντικότερο στάδιο κι εκεί που συνήθως κάποιος αντιμετωπίζει πρόβλημα είναι το devices (το οποίο συμπεριλαμβάνεται στο core). Τα επίπεδα είναι έτσι κατασκευασμένα ώστε το επόμενο να συμπεριλαμβάνει το προηγούμενο.
Κάνοντας ένα τεστ και στο devices, είδα ότι όντως εκεί υπάρχει πρόβλημα. Άρχισα να ψάχνω για logs, αλλά ήθελα current logs. Εκείνης της στιγμής, να δω τι συμβαίνει, που κολλάει. Δεν είχα όμως οθόνη, δεν είχα τίποτα. Οπότε αποφάσισα να συνδεθώ μέσω ssh από το laptop και να δω live που λένε, τι συμβαίνει. Ο υπολογιστής παρέμενε ανοιχτός και σε φουλ λειτουργία, αλλά δεν λειτουργούσαν τα γραφικά. Μαύρη οθόνη και χωρίς καν σήμα.
Πατάτες!! Τίποτα και καμία αναφορά στα logs για κάποια αποτυχία error, έστω και warning. Ήξερα όμως ότι φταίνε τα γραφικά και μιας και έτρεχα (τρέχω και θα τρέχω) τον ανοιχτό οδηγό nouveau, είχα πολλές επιλογές. Καταρχήν να δούμε αν όντως ευθύνεται ο nouveau. Blacklist λοιπόν, μια επανεκκίνηση και ξανά το τεστ. Ωπ, δουλεύει ! οπότε το «κλειδώνω» εκεί. Φταίει ο nouveau.

Αρχίζει το ματς

Από αυτό το σημείο και μετά αρχίζουν τα τρελά. Φορτώνω με διάφορες παραμέτρους στον πυρήνα και ξανά το τεστ και ξανά παραμέτρους και ξανά το τεστ, μέχρι που δεν εντοπίζω κάτι αποτελεσματικό.
Σειρά έχει το Internet. Μη πω τώρα πόσες αναφορές λαθών(bugs) υπάρχουν για τον nouveau έτσι; όσα ευρώ κληρώνει το Joker την επόμενη εβδομάδα. Και μιλάμε για τις πιο πρόσφατες. Με τα πολλά, οδηγήθηκα σε μια αναφορά (upstream) που μου κέντρισε το ενδιαφέρον. Διαβάζω όλη την αναφορά και όλα τα σχόλια και βλέπω ότι υπάρχει «ψωμί». Αποφασίζω λοιπόν να ανοίξω μια αναφορά στο Launchpad (α δε το ανέφερα ε; για το Ubuntu 15.04 μιλάω, όπου μέχρι αυτή τη στιγμή φοράει τον πυρήνα του 14.10) και να συμπεριλάβω και την upstream αναφορά καθώς και τα αποτελέσματα από τα τεστ.
Ξέχασα να πω (που να μείνει μυαλό, το έφαγε ο kernel), ότι τέσταρα τον τελευταίο mainline πυρήνα και το πρόβλημα εκεί έχει διορθωθεί.

Το μαγικό tag

Και εκεί που έχω ανοίξει την αναφορά στο Launchpad και περιμένω κάποια απάντηση, έρχεται το «μαγικό» tag το οποίο δεν είναι άλλο από το #needs-revese-bisect και με οδηγίες εδώ. Ανοίγω τη σελίδα, sorry που θα το πω αλλά αυτή είναι η αλήθεια, μένω μαλάκας εντελώς. OK, ήξερα πάνω-κάτω τι είναι το bisect, αλλά κατευθείαν reverse bisect και στον πυρήνα κιόλας; Το σκέφτηκα κάμποση ώρα και το αποφάσισα. Θα συμμετάσχω λέω. Έτσι, για να δω, να μάθω και να αποκτήσω εμπειρίες. Όχι για το bug, το bug εκτός του ότι έχει διορθωθεί σε επόμενη έκδοση πυρήνα, αναφερόμαστε τώρα και σε μια έκδοση που θα λήξει σε 9 μήνες (ναι μεν αναφέρθηκε για το Vivid το bug, αλλά ο πυρήνας είναι του Utopic). Το μόνο ίσως σημαντικό εδώ, είναι ότι ο συγκεκριμένος πυρήνας θα περάσει στην 14.04 LTS ως backport με τα λεγόμενα HWE stacks, ως linux-image-generic-lts-utopic.

Το μυστικό

Όχι δεν αναφέρομαι στο γνωστό best seller, αναφέρομαι στο IRC. Αυτό είναι το μυστικό. Αν ενδιαφέρεστε πραγματικά να λυθεί κάποιο πρόβλημα και θέλετε να ασχοληθείτε με αυτό, ψάξτε και βρείτε κάποιο επίσημο (ή και ανεπίσημο) κανάλι στο IRC (στο freenode συνήθως), σχετικά με το project με το οποίο ασχολείστε.
Καταρχήν, εκεί που γράφω παραπάνω «οδηγήθηκα σε μια αναφορά (upstream)», δεν οδηγήθηκα ακριβώς, με οδήγησαν. Γιατί μετά από αρκετό google it, και όταν δεν κατάφερα να εντοπίσω μια αναφορά «της προκοπής», μπήκα στο επίσημο κανάλι του #nouveau στο freenode και ρώτησα. Κάποιος με οδήγησε σε αυτό το bug report και τα υπόλοιπα απλά ακολούθησαν.

Λίγα λόγια για το bisecting

To bisect όπως το λέει και η λέξη είναι ο διαχωρισμός. Αυτή τη διεργασία την κάνει το git. Το git έχει μυαλό, του μιλάς και σου απαντάει. Για να το πούμε πιο σωστά, εκείνοι που το έφτιαξαν έχουν μυαλό. Αυτή η διεργασία έχει να κάνει με καλά και κακά commits. Στέλνει κάποιος ένα κομμάτι κώδικα, το οποίο σπάει μια λειτουργία σε επερχόμενη έκδοση λογισμικού. Μέσα από την διαδικασία του bisect εντοπίζουμε την τελευταία καλή έκδοση λογισμικού και την πρώτη (αμέσως επόμενη) κακή και tag-αρουμε(όπως λέμε) τα δυο λογισμικά στο git ως καλό(good) και κακό(bad) αντίστοιχα. Τότε ξεκινάει και η διαδικασία του «διαίρει και βασίλευε» με το git να σπάει ολόκληρα δένδρα με commits αναλόγως τι του απαντάμε εμείς (good or bad) και στο τέλος να μας οδηγεί στο πρώτο κακό commit (αυτό που ψάχνουμε δηλαδή για να το αφαιρέσουμε/αντιστρέψουμε/διορθώσουμε) που πέρασε στην επόμενη έκδοση.
Το revese bisect τώρα, είναι η ίδια διαδικασία, μόνο που λέμε ψέμματα(απαντάμε ανάποδα) στο git στις ερωτήσεις που μας κάνει. Ξεκινάμε tag-αροντας τα λογισμικά ανάποδα (το πρώτο κακό ως καλό και το πρώτο καλό ως κακό) και συνεχίζουμε. Ρωτάει το git, «είναι καλό αυτό το commit;» το τεστάρουμε εμείς και αν είναι καλό του λέμε «όχι δεν είναι καλό», αν είναι κακό του λέμε «ναι, είναι καλό», αυτό γίνεται συνεχώς μέχρι να τελειώσει η διαδικασία του bisect. Στο τέλος θα μας βγάλει το πρώτο κακό commit (που στην περίπτωση του reverse bisect είναι το καλό), κι έτσι θα προσπαθήσουμε να το ενσωματώσουμε σε προγενέστερη έκδοση για να δούμε αν λειτουργεί σωστά.
Αυτό έγινε και στην περίπτωση του bug που ανέφερα. Αφού το bug έχει διορθωθεί σε επόμενη έκδοση πυρήνα, ψάχνουμε να βρούμε το commit (ή τα commits) που διορθώνουν το πρόβλημα και να τα τεστάρουμε σε προηγούμενη έκδοση πυρήνα (που υπάρχει το πρόβλημα) για να μπορέσουμε εν τέλει να τα κάνουμε backport.
Τι; δεν νομίζω να ζαλιστήκαμε ε; Αν ναι, ας φανταστούμε όλοι μαζί παρέα(βασικά όσοι έχουν περάσει τη διαδικασία, ας θυμηθούν) ότι η διαδικασία αυτή εμπεριέχει μεταγλώττιση-χτίσιμο-εγκατάσταση-τεστ του λογισμικού σε κάθε commit που μας προτείνει το git.

Το φινάλε

Δεν θα μπω εδώ σε λεπτομέρειες για το τι ακριβώς έκανα και πως το έκανα. Απλά θα αναφέρω ότι απέτυχα ίσα με ένα εκατομμύριο φορές, μέχρι να βρω τελικά το σωστό δρόμο και επίσης ότι χωρίς το μυστικό(το IRC που λέγαμε παραπάνω), μάλλον δεν θα είχα κάνει τίποτα. Έπεσε πολλή βοήθεια από εκεί και αρκετή καθοδήγηση.
Έχτισα και τέσταρα τόσους πυρήνας σε 2-3 μέρες, όσους δεν έχω χτίσει τα τελευταία πέντε χρόνια που ασχολούμαι με το Linux. Χωρίς υπερβολές, περί τους 40.
Στο τέλος κατάφερα (καταφέραμε να το πω πιο δίκαια) και εντόπισα 3 commits που περιέχουν τον κώδικα που διορθώνει το πρόβλημα. Από εδώ και πέρα θέλουν εκκαθάριση, διότι όπως είναι ατόφια, σπάνε (conflict) τον κώδικα του πυρήνα του Ubuntu. Αφού «μεταμορφωθούν» κατάλληλα, θα περάσουν κατά πάσα πιθανότητα σε έναν επόμενο πυρήνα του Utopic (και κατ’ επέκταση στην 14.04 με την αλλαγή του HWE stack).

Αν λοιπόν σας τύχει/ζητηθεί κάτι τέτοιο και δεν έχετε εμπειρία, ετοιμαστείτε για ένα «New York big style fuck» που λένε. Αν το αποφασίσετε να συμμετάσχετε ενεργά σε ένα Kernel bisecting (ή reverse), σίγουρα θα μάθετε αρκετά και σίγουρα θα χάσετε αρκετό χρόνο (εκτός και αν έχετε κάποιο δυνατό build box που χτίζει πυρήνες σε λίγα λεπτά).

Ωχ, ξέχασα να δώσω την αναφορά στο Launchpd (δε σου είπα ότι μου έφαγε το μυαλό ο kernel; bisecting κι εκεί έγινε). Εδώ.

Συμβάλετε κι εσείς με ένα σχόλιο

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s