1. Το Ξεκίνημα της Ιστορίας
Μιας και τα hardware failures δίνουν και παίρνουν τον τελευταίο καιρό, δεν ξέφυγα κι εγώ από την ανάγκη αντικατάστασης ενός σκληρού δίσκου σε FreeBSD Server με ZFS-Only σύστημα αρχείων!
Πιο συγκεκριμένα, πριν από λίγες ημέρες και ενώ ξύπνησα το πρωί και έκανα λίγο chat με τα μέλη του Chania-LUG, κάποια στιγμή το γραφικό περιβάλλον στον υπολογιστή μου πάγωσε! Η οθόνη γέμισε με πράσινες γραμμές, το ποντίκι κόλλησε και γενικά το μηχάνημα σταμάτησε να αποκρίνεται. Η πρώτη κίνηση που έκανα ήταν να μπω στο σύστημα μέσω δικτύου με ssh (από το κινητό γιατί το να στήσω laptop τα χαράματα ήταν μια διαδικασία... Αλλά αυτό δεν έχει καμιά σημασία). Είδα ότι το σύστημα είχε απόκριση, αλλά αρκετά αργή. Το ίδιο έκανα και με τον browser, όπου έλεγξα ότι ο υπολογιστής ανταποκρίνεται σε http requests κ.λ.π. Βασικά έκανα έλεγχο σε όλες τις υπηρεσίες που ήθελα να δουλεύουν. Παντού το ίδιο. Το γραφικό περιβάλλον παγωμένο με τους μπλε και πράσινους κόκκους και γραμμές, ενώ οι υπηρεσίες δουλεύαν όλες, αλλά με αρκετά μικρότερη ταχύτητα απόκρισης. Φυσικά αφού το μηχάνημα έχει και γραφικό περιβάλλον θα καταλάβατε ότι το χρησιμοποιώ και σαν desktop :P
Η πρώτη μου σκέψη ήταν "Μπόρα είναι θα περάσει! Κάτι κάνει το μηχάνημα από πίσω και την κάνει τη δουλειά. Το απόγευμα που θα γυρίσω σπίτι από τη δουλειά θα είναι όλα μια χαρά!" Σωστά σκέφτηκα γιατί όντως το μηχάνημα έκανε δουλειά. Για την ακρίβεια το ZFS Subsystem δούλευε για λογαριασμό μου. Για την ακρίβεια διόρθωνε και έσωζε δεδομένα που έβρισκε εσφαλμένα, εξ αιτίας του σκληρού δίσκου...
Το απόγευμα και αφού γύρισα σπίτι, είδα το μηχάνημα στην ίδια ακριβώς κατάσταση. Ξαναέκανα τον έλεγχο των υπηρεσιών και την έπεσα για έναν υπνάκο μιας και έβλεπα πως θα χρειαζόμουν όλες μου τις δυνάμεις για να μπορέσω να δω τι γίνεται...
Τι θα δούμε σε αυτό το άρθρο
- Ώρα Να Χάσουμε το uptime... (πάλι...): Τα μηνύματα λάθους κατά την εκκίνηση
- Λίγες σχετικές πληροφορίες: Πληροφορίες σχετικές με το ZFS
- Γνωριμία με το σύστημα: Πληροφορίες σχετικές με τη δομή του συστήματός μας
- Έλεγχος και διόρθωση των δεδομένων: Το ZFS διορθώνει όσα σφάλματα δεδομένων μπορεί
- Δημιουργία του backup των δεδομένων μας: Με τη βοήθεια του ZFS send/receive
- Προετοιμασία του καινούργιου σκληρού δίσκου: Δημιουργία των απαραίτητων κατατμήσεων κ.λ.π.
- Αντικατάσταση των τμημάτων των pools: Ανάκτηση δεδομένων και μεταφορά στον καινούργιο σκληρό δίσκο
- ΔΕΝ ΤΕΛΕΙΩΣΑΜΕ!!!!: Πρέπει να γίνει διόρθωση και του αρχείου zpool.cache
2. Ώρα Να Χάσουμε το uptime... (πάλι...)
Ήρθε η ώρα, λοιπόν, να κάνουμε μια επανεκκίνηση στον υπολογιστή... Μέσω ssh (από το laptop αυτή τη φορά) δίνω τη μαγική εντολή...
eliaschr@pluto:~ > su Password: pluto# shutdown -r now pluto#
Μέχρι το σημείο που είδα ότι... Connection to pluto closed. Από εκεί και πέρα η εργασία γίνεται επάνω στον ίδιο τον υπολογιστή.
Στο σημείο όπου το monitor άρχισε να δείχνει κανονικά τα μηνύματα του πυρήνα άρχισα να βλέπω κάποια μηνύματα του στυλ
ad0: FAILURE - READ_DMA48 status=51error=40 LBA=383250045 ad0: FAILURE - READ_DMA48 status=51 error=1 LBA=383250045 ZFS: vdev I/O failure, zpool=zroot path=/dev/gpt/disk0 offset=191928776192 size=120320 error=5 ZFS: vdev I/O failure, zpool=zroot path=/dev/gpt/disk0 offset=191928776192 size=120320 error=5 ZFS: zpool I/O failure, zpool=zroot error=5 . . .
και πολλά ακόμα τέτοιου τύπου μηνύματα... Ο σκληρός δίσκος είχε αρχίσει να παραδίδει το πνεύμα του. Χμμμμ. Ήρθε η ώρα να μελετήσουμε το ZFS Administration Handbook, να δούμε τι εργαλεία μας δίνει το ZFS για την περίπτωση. Φυσικά το συγκεκριμένο κείμενο το έχω σε έντυπη μορφή για παν ενδεχόμενο.
Αυτό που μου έκανε εντύπωση είναι ότι ακόμα και με την κατάσταση του σκληρού δίσκου, το μηχάνημα κατάφερε και ξεκίνησε, χωρίς να σηκώσει, φυσικά, γραφικό περιβάλλον. Μέσα σε όλα τα λάθη του σκληρού δίσκου, το ZFS χρησιμοποίησε τη μαγεία του και τα δεδομένα, ακόμα, ήταν κατά κάποιο τρόπο ασφαλή! Αυτό και αν δεν το ονειρευόμουν ποτέ!
3. Μήπως Πρέπει Να Πάρω Backup;
Φυσικά και την ξέρω την απάντηση. Απλά ήρθε η ώρα να περιγράψω μερικές λειτουργίες του ZFS που βοηθάνε σε αυτό. Παρότι οι λέξη "partition" είναι κάτι τελείως διαφορετικό από το "σημείο διαχείρισης" στο ZFS, στο ακόλουθο κείμενο θα χρησιμοποιώ τη λέξη "partition" σα να είναι ταυτόσημη με την έννοια "σημείο διαχείρισης". Ο λόγος είναι πως ένας καινούργιος χρήστης του ZFS μπορεί να μην έχει ξεκαθαρίσει τις διαφορές και με αυτό τον τρόπο προσπαθώ να γίνω πιο κατανοητός.
Η πρώτη λειτουργία του ZFS που μας ενδιαφέρει είναι η δημιουργία snapshots. Τα snapshots είναι και αυτά κάποια σημεία διαχείρισης του ZFS τα οποία μπορούμε να τα κάνουμε mount και να τα χρησιμοποιήσουμε κανονικά, ως Read-Only Partitions. Το μέγεθός τους αρχικά είναι ελάχιστο, ίσα ίσα για να κρατηθούν πληροφορίες για το κομμάτι από το οποίο κρατήσαμε το snapshot. Όσο εμείς αλλάζουμε αρχεία μέσα στο σύστημα αρχείων από το οποίο προέρχεται το snapshot, το ZFS γράφει τις παλιές πληροφορίες που υπήρχαν μέσα στο κομμάτι του snapshot και μετά αλλάζει τα δεδομένα που θέλουμε στο κανονικό partition. Έτσι, το μέγεθος του snapshot στον σκληρό μας δίσκο έχει το ελάχιστο δυνατό γιατί στην ουσία κρατάει μόνο τις αλλαγές που έχουμε κάνει. Ή καλύτερα την κατάσταση των αλλαγμένων αρχείων, πριν τις αλλαγές μας.
Η δεύτερη λειτουργία που μας ενδιαφέρει να γνωρίζουμε (δεν θα την χρησιμοποιήσουμε εδώ) είναι οι κλώνοι - clones. Οι κλώνοι μπορούν να προέρχονται μόνο από ένα snapshot και στην ουσία είναι ένα αντίγραφο των αρχείων που περιέχει το snapshot σε άλλο σημείο του σκληρού. Ένας κλώνος, λοιπόν, μπορεί να χρησιμοποιηθεί σαν ένα Read/Write partition το οποίο περιέχει όλα τα αρχεία τα οποία αντιστοιχούν στο snapshot από το οποίο προέρχεται. Δε μιλάμε μόνο για τα αρχεία που έχουν αλλαχθεί, αλλά για όλα τα αρχεία που περιέχει το partition από το οποίο προέρχεται και το snapshot. Προσέξτε ότι υπάρχει μια σχέση snapshot προς τον κλώνο. Το snapshot είναι ο "μπαμπάς" του κλώνου. Η σχέση αυτή μπορεί να αντιστραφεί αν το θελήσουμε. Για περισσότερες πληροφορίες σχετικές με τους κλώνους ανατρέξτε στο ZFS Administration Handbook. Δεν θα τους αναλύσουμε περισσότερο γιατί δε θα μας απασχολήσουν στο εγχείρημα αλλαγής του ελαττωματικού σκληρού δίσκου.
Η τρίτη λειτουργία που έχει και τη δύναμη που θέλουμε είναι η send/receive. Μοιάζει πολύ με το dump/restore που όσοι ασχολούμαστε με το FreeBSD πρέπει να γνωρίζουμε καλά. Το ZFS έχει τη δυνατότητα να στείλει ένα ολόκληρο σημείο διαχείρισης σε ένα stream. Αυτό εμείς μπορούμε, είτε να το σώσουμε σαν αρχείο, είτε να το οδηγήσουμε μέσω pipe π.χ. σε ssh για να το στείλουμε σε ένα remote σύστημα. Μοιάζει πολύ με το dump(8). Αυτό που δεν θα πρέπει να παραλείψουμε είναι ότι η λειτουργία send μπορεί να εφαρμοστεί σε snapshot και όχι σε χρησιμοποιούμενο σημείο διαχείρισης!
Η αντίστροφη διαδικασία είναι η receive η οποία μοιάζει με την εντολή restore(8). Η λειτουργία receive παίρνει τα δεδομένα από ένα stream και ξαναδημιουργεί το σημείο διαχείρισης. Θα μπορούσαμε, λοιπόν, σε ένα απομακρυσμένο μηχάνημα να δημιουργήσουμε το σημείο διαχείρισης που στέλνουμε μέσω ssh με τη λειτουργία send.
Με όλες αυτές τις δυνατότητες που γνωρίσαμε, μπορούμε να καταλάβουμε ότι το ZFS μας παρέχει πολλά εργαλεία για να μπορέσουμε να φτιάξουμε αντίγραφο ασφάλειας του συστήματός μας. Είτε χρησιμοποιώντας κλώνους, είτε με το να κάνουμε ενός είδους dump αρχείο, είτε ακόμα και να έχουμε ένα μηχάνημα απομακρυσμένο το οποίο να παίζει τον ρόλο του backup server σε περίπτωση αστοχίας του πρώτου!
Είναι κατανοητό πως πρώτα θα πρέπει να δούμε την κατάσταση των ZFS Pools που έχει το σύστημά μας. Με αυτό τον τρόπο θα εξηγήσω τη δομή του εν λόγω μηχανήματος για να μπορέσουμε να δούμε τι συμβαίνει, αλλά ταυτόχρονα θα εξηγήσω γιατί προτίμησα να κάνω αυτή τη διαρρύθμιση στους αποθηκευτικούς μου χώρους. Το μηχάνημα περιέχει ένα σκληρό δίσκο 1.5TB και δύο σκληρούς δίσκους 500GB. Το ακόλουθο σχήμα μπορεί να δώσει λίγο φως στην εξήγηση της διαρρύθμισης:

Στο σχήμα φαίνονται οι κατατμήσεις του σκληρού δίσκου, δηλαδή partitions και όχι σημεία διαχείρισης του ZFS. Οι σκληροί έχουν χωριστεί σε partitions με το σχήμα GPT και όχι με το κλασικό σχήμα geom(4).
Τα πρώτα 500GB του σκληρού έχουν διατεθεί στο λειτουργικό σύστημα. Εδώ μας χρειάζονται τα ακόλουθα partitions:
- ad0p1: Partition που περιέχει τον κώδικα για το boot του λειτουργικού. Έχει μικρό μέγεθος, της τάξης των 256KB. Ο τύπος του είναι freebsd-boot και περιέχει τον κώδικα gptzfsboot.
- ad0p2: Partition της εικονικής μνήμης του λειτουργικού μας. Έχει μέγεθος 4GB και είναι τύπου freebsd-swap. Το όνομά του είναι το swap0
- ad0p3: Εδώ περιέχεται το λειτουργικό μας. Το μέγεθος του partition είναι τα υπόλοιπα από τα 500GB που περίσσεψαν. Μιας και εκεί μέσα θα βρίσκονται τα σημεία διαχείρισης του ZFS, ο τύπος του partition είναι freebsd-zfs.
Στο μεγάλο κομμάτι βρίσκονται επίσης πληροφορίες που δεν μας ενδιαφέρει τόσο πολύ το να έχουμε mirrored.
Άλλα δύο partitions που έχουμε στον σκληρό μεγέθους 1.5TB είναι και αυτά μεγέθους 500GB. Αυτά τα δύο partitions (ad0p4 και ad0p5 αντίστοιχα) γίνονται mirrored με δύο άλλους σκληρούς δίσκους μεγέθους 500GB ο καθένας (ad1p1 και ad2p1 αντίστοιχα). Ο λόγος που κάνουμε το mirroring είναι για να έχουμε ένα αυτόματο backup των δεδομένων και σε άλλους σκληρούς. Έτσι, ό,τι περιέχεται στο partition ad0p4 περιέχεται αυτόματα και στον σκληρό δίσκο ad1 και ό,τι περιέχεται στο partition ad0p5 περιέχεται αυτόματα και στον σκληρό ad2.
Ο λόγος που προτιμήθηκε αυτός ο διαχωρισμός είναι η ευκολία εύρεσης σκληρών δίσκων 500GB πρόχειρων και σε χαμηλό κόστος. Είναι, λοιπόν, μια τακτική την οποία ακολουθούμε περισσότερο για να μπορούμε ανά πάσα στιγμή να ανακτήσουμε τα δεδομένα μας. Επίσης, αν κάποιος σκληρός δίσκος πάθει κάποια ζημιά (που είναι και ο λόγος ύπαρξης αυτού του άρθρου) τότε είναι καλύτερα να χάσουμε δεδομένα 500GB παρά περισσότερα... Στη δικιά μας περίπτωση ο σκληρός δίσκος που έπαθε τη ζημιά είναι, ποιος άλλος σύμφωνα με το φίλο μας τον Murfy, ο ad0 χωρητικότητας 1.5TB
Για να μπορέσουμε να σώσουμε το σύστημά μας θα χρειαστούμε έναν αντικαταστάτη σκληρό δίσκο χωρητικότητας 1.5TB, τον οποίο θα συνδέσουμε σε ένα USB, εξωτερικά. Αυτό σημαίνει πως η ονομασία του σκληρού θα είναι η da0. Το ακόλουθο σχήμα δείχνει ποια είναι η κατάτμηση που θα κάνουμε στον αντικαταστάτη σκληρό και ποια η σχέση του με τον παλιό και ελαττωματικό.

Θα παρατηρήσατε ότι στον καινούργιο σκληρό οι κατατμήσεις είναι σχεδιασμένες με διακεκομμένη γραμμή. Αυτό δηλώνει πως οι κατατμήσεις δεν υπάρχουν αλλά θα πρέπει να δημιουργηθούν. Ας μην ξεχνάμε ότι ο σκληρός δίσκος da0 είναι ολοκαίνουργιος.
Στο σχήμα βλέπουμε πως οι κατατμήσεις που χρειάζονται μεταφορά δεδομένων είναι μόνο οι τρεις, ad0p3, ad0p4 και ad0p5. Αυτό συμβαίνει γιατί δεν υπάρχει λόγος να μεταφέρουμε την εικονική μνήμη, ούτε τον κώδικα gptzfsboot. Εξ άλλου, τον τελευταίο θα τον γράψουμε στον καινούργιο σκληρό από την αρχή!
γ. Έλεγχος και διόρθωση των δεδομένων
Πρώτη κίνηση για να μπορέσουμε να πάρουμε ένα σωστό backup είναι να προσπαθήσουμε να έχουμε τα δεδομένα μας ακέραια. Για να το κάνουμε αυτό θα πρέπει να είμαστε root. Ας ελέγξουμε πρώτα την κατάσταση των ZFS Pools:
eliaschr@pluto:~ > su
Password:
pluto# zpool status -v #it could be -x as well
pool: Common1
state: ONLINE
status: The pool is formatted using an older on-disk format. The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
pool will no longer be accessible on older software versions.
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
Common1 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/disk1 ONLINE 0 0 0
gpt/Mirror1 ONLINE 0 0 0
errors: No known data errors
pool: Common2
state: ONLINE
status: The pool is formatted using an older on-disk format. The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
pool will no longer be accessible on older software versions.
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
Common2 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/disk2 ONLINE 0 0 0
gpt/Mirror2 ONLINE 0 0 0
errors: No known data errors
pool: zroot
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: http://www.sun.com/msg/ZFS-8000-9P
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
gpt/disk0 ONLINE 198 0 0
errors: No known data errors
pluto#
Πραγματικά, εδώ βλέπουμε ότι η ZFS Pool που περιέχει το λειτουργικό μας σύστημα, zroot, παρουσιάζει προβλήματα. Ώρα να αφήσουμε το ZFS να προσπαθήσει να κάνει ένα καλό έλεγχο στην pool και αν βρει και άλλα σφάλματα να τα διορθώσει. Αυτό γίνεται ως εξής:
pluto# zpool scrub
pluto# zpool status -v
pool: Common1
state: ONLINE
status: The pool is formatted using an older on-disk format. The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
pool will no longer be accessible on older software versions.
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
Common1 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/disk1 ONLINE 0 0 0
gpt/Mirror1 ONLINE 0 0 0
errors: No known data errors
pool: Common2
state: ONLINE
status: The pool is formatted using an older on-disk format. The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
pool will no longer be accessible on older software versions.
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
Common2 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/disk2 ONLINE 0 0 0
gpt/Mirror2 ONLINE 0 0 0
errors: No known data errors
pool: zroot
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: http://www.sun.com/msg/ZFS-8000-9P
scrub: scrub completed after 23h20m with 0 errors on Mon Oct 18 23:54:39 2010
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
gpt/disk0 ONLINE 249 0 0 256K repaired
errors: No known data errors
pluto#
Σε αυτό το σημείο βλέπουμε ότι μετά από πολλές ώρες το ZFS έκανε το πρώτο του θαύμα! Παρότι παρουσιάστηκαν ακόμα περισσότερα σφάλματα διόρθωσε όσα μπορούσε. Στη δικιά μας την περίπτωση, διόρθωσε όλα όσα βρήκε.
δ. Δημιουργία του backup των δεδομένων μας
Το backup δημιουργείται σε δύο βήματα. Το πρώτο είναι να φτιαχτεί ένα snapshot της κατάστασης του συστήματος αρχείων που μας ενδιαφέρει και στη συνέχεια να δημιουργήσουμε το αρχείο που περιέχει το αντίγραφο. Η προτιμώμενη λύση για ένα σύστημα που έχει πρόβλημα είναι η λειτουργία send του ZFS:
pluto# zfs list NAME USED AVAIL REFER MOUNTPOINT Common1 274G 182G 274G /Common Common2 224G 233G 18K /Common2 Common2/Backups 73,1G 233G 73,1G /Common/Backups Common2/Datasheets 7,43G 233G 7,43G /Common/Datasheets Common2/Documentation Section 3,22G 233G 3,22G /Common/Documentation Section Common2/ECh Documents 21,4G 233G 21,4G /Common/ECh Documents Common2/Pictures 13,4G 233G 13,4G /Common/Pictures Common2/home 105G 233G 105G /usr/home Common2/www 275M 233G 275M /usr/local/www zroot 107G 346G 221M legacy zroot/tmp 380M 346G 380M /tmp zroot/usr 19,5G 346G 14,6G /usr zroot/usr/ports 4,64G 346G 270M /usr/ports zroot/usr/ports/distfiles 4,38G 346G 4,38G /usr/ports/distfiles zroot/usr/ports/packages 18K 346G 18K /usr/ports/packages zroot/usr/src 303M 346G 303M /usr/src zroot/var 2,32G 346G 13,5M /var zroot/var/crash 1024M 346G 1024M /var/crash zroot/var/db 1,15G 346G 1,09G /var/db zroot/var/db/pkg 58,6M 346G 58,6M /var/db/pkg zroot/var/empty 18K 346G 18K /var/empty zroot/var/log 92,4M 346G 92,3M /var/log zroot/var/mail 200K 346G 200K /var/mail zroot/var/run 130K 346G 111K /var/run zroot/var/tmp 67,3M 346G 67,3M /var/tmp pluto# zfs snapshot -r zroot/var@2010-10-20 pluto# zfs snapshot -r zroot/tmp@2010-10-20 pluto# zfs snapshot -r zroot/usr@2010-10-20 pluto# zfs snapshot zroot@2010-10-20 pluto# zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT zroot@2010-10-20 98K - 221M - zroot/tmp@2010-10-20 0 - 380M - zroot/usr@2010-10-20 326K - 14,6G - zroot/usr/ports@2010-10-20 0 - 270M - zroot/usr/ports/distfiles@2010-10-20 0 - 4,38G - zroot/usr/ports/packages@2010-10-20 0 - 18K - zroot/usr/src@2010-10-20 0 - 303M - zroot/var@2010-10-20 21K - 13,5M - zroot/var/crash@2010-10-20 0 - 1024M - zroot/var/db@2010-10-20 156K - 1,09G - zroot/var/db/pkg@2010-10-20 0 - 58,6M - zroot/var/empty@2010-10-20 0 - 18K - zroot/var/log@2010-10-20 85,5K - 92,3M - zroot/var/mail@2010-10-20 0 - 200K - zroot/var/run@2010-10-20 19K - 111K - zroot/var/tmp@2010-10-20 0 - 67,3M - pluto#
Τα snapshots έχουν δημιουργηθεί. Μην ξεχνάμε ότι τα snapshots είναι και αυτά σημεία διαχείρισης και μπορούν να προσαρτηθούν και αυτά στο σύστημά μας. Όμως δεν περιέχουν όλα τα δεδομένα, αλλά μόνο indexes και τα αρχεία τα οποία έχουν υποστεί αλλαγές, όπως ήταν τη στιγμή που πήραμε το snapshot.
Τώρα θα πρέπει να δημιουργήσουμε αντίγραφα των snapshots αλλά με ολόκληρα τα δεδομένα. Το πρόβλημα είναι το που θα τα αποθηκεύσουμε. Αν συνδέσουμε έναν εξωτερικό σκληρό δίσκο σε USB τότε το πιο σύνηθες είναι να είναι μορφοποιημένος ο εν λόγω σκληρός δίσκος σε σύστημα αρχείων FAT32 ή NTFS. Το FAT32 έχει το πρόβλημα του μέγιστου μεγέθους αρχείου των 4GB, το οποίο είναι απαγορευτικό γιατί τα δεδομένα στον σύστημά μας ξεπερνάνε κατά πολύ αυτό το μέγεθος... Από την άλλη, το NTFS έχει το πρόβλημα της αστάθειας στο FreeBSD. Είναι πολύ εύκολο να παρουσιαστεί σφάλμα κατά την εγγραφή των δεδομένων με αποτέλεσμα ένα πανέμορφο core dump του kernel! Άρα, αποφεύγουμε να το χρησιμοποιήσουμε.
Η λύση είναι το εσωτερικό μας mirrored τμήμα. Το καλό που έχουν τα δύο mirrors που έχουμε φτιάξει είναι ότι τα δεδομένα βρίσκονται ταυτόχρονα σε δύο σκληρούς δίσκους και έτσι αν ο ένας παρουσιάζει σφάλματα κατά την εγγραφή, το ZFS ξέρει καλά πως να τα κρατήσει σωστά με τη βοήθεια των δεύτερων σκληρών. Εναλλακτικά θα μπορούσαμε να έχουμε ένα ssh server σε ένα απομακρυσμένο μηχάνημα στο δίκτυό μας και να στείλουμε το backup εκεί. Οπότε λύσεις υπάρχουν, για κάθε γούστο! :P
Η ώρα του πραγματικού backup ήρθε:
pluto# zfs send -Rv zroot/usr@2010-10-20 > /Common2/usr.20101020 . . . pluto# zfs send -Rv zroot/tmp@2010-10-20 > /Common2/tmp.20101020 . . . pluto# zfs send -Rv zroot/var@2010-10-20 > /Common2/var.20101020 . . . pluto# zfs send -v zroot@2010-10-20 > /Common2/root.20101020 . . . pluto# ls -l /Common2 -rw-r--r-- 1 root wheel 240931640 21 Οκτ 00:25 root.20101020 -rw-r--r-- 1 root wheel 563447860 20 Οκτ 22:27 tmp.20101020 -rw-r--r-- 1 root wheel 22777054676 20 Οκτ 20:08 usr.20101020 -rw-r--r-- 1 root wheel 4975268576 20 Οκτ 22:07 var.20101020 pluto#
Τα τέσσερα αρχεία που δημιουργήθηκαν είναι το backup όλου του λειτουργικού. Αυτό δημιουργήθηκε στο δεύτερο mirror που έχει το σύστημά μας. Κατά τη διάρκεια του send βλέπουμε να υπάρχουν πολλά μηνύματα σφάλματος, αλλά αυτό είναι κάτι φυσιολογικό αφού ο σκληρός δίσκος ad0 είναι ελαττωματικός.
4. Αλλαγή του ελαττωματικού σκληρού δίσκου
Αφού τελειώσαμε με το backup, ήρθε και η ώρα να αλλάξουμε τον σκληρό δίσκο. Η λογική είναι να μη χρειαστεί να κάνουμε και πάλι εγκατάσταση στο λειτουργικό, αλλά να επαναφέρουμε όλες τις ZFS Pools σε ένα καινούργιο σκληρό δίσκο και να αποφύγουμε την υπόλοιπη ταλαιπωρία.
α. Προετοιμασία του καινούργιου σκληρού δίσκου
Δεν χρειάζεται να σβήσουμε το μηχάνημα, ούτε και να έχουμε κενό SATA δίαυλο στη μητρική μας για αυτό το βήμα. Η μεταφορά των ZFS Pools από ένα σκληρό σε έναν άλλο, απαιτεί να είναι ο καινούργιος σκληρός χωρισμένος σε partitions, όπως και ο παλιός. Αυτή είναι η προετοιμασία που πρέπει να κάνουμε στον καινούργιο σκληρό δίσκο. Θα επαναλάβουμε τα βήματα που είχαμε κάνει όταν στήναμε το FreeBSD σε ZFS. Η διαφορά είναι ότι αυτό θα το κάνουμε στον σκληρό δίσκο που θα συνδέσουμε σε μια θύρα USB. Αφού τον συνδέσουμε θα δούμε κάποια μηνύματα από το kernel που θα μας δείχνουν:
Oct 23 10:43:21 pluto kernel: ugen4.2:at usbus4 Oct 23 10:43:21 pluto kernel: umass0: on usbus4 Oct 23 10:43:21 pluto kernel: umass0: SCSI over Bulk-Only; quirks = 0x4000 Oct 23 10:43:23 pluto kernel: umass0:2:0:-1: Attached to scbus2 Oct 23 10:43:23 pluto kernel: da0 at umass-sim0 bus 0 scbus2 target 0 lun 0 Oct 23 10:43:23 pluto kernel: da0: Fixed Direct Access SCSI-2 device Oct 23 10:43:23 pluto kernel: da0: 40.000MB/s transfers Oct 23 10:43:23 pluto kernel: da0: 1430799MB (2930277168 512 byte sectors: 255H 63S/T 182401C)
Εδώ φαίνεται καθαρά ότι ο καινούργιος δίσκος έχει προσαρτηθεί στο σύστημα με το όνομα da0. Προσοχή χρειάζεται να μην μπερδέψουμε την ονομασία του με αυτή του ελαττωματικού σκληρού ad0! Η κατάτμηση του σκληρού μας γίνεται ως εξής:
pluto# gpart destroy # may fail pluto# gpart create -s gpt da0 # Create gpt scheme on external hard disc pluto# gpart add -s 256K -t freebsd-boot da0 pluto# gpart add -s 4G -t freebsd-swap da0 # Do not label it yet
Σε αυτό το σημείο έχουμε δημιουργήσει τις δύο πρώτες κατατμήσεις του σκληρού για το bootcode και τη μνήμη swap. Η τελευταία δεν έχει ακόμα ετικέτα διότι θα πάρει το όνομα την ετικέτας που ήδη χρησιμοποιείται από τον βασικό, για την ώρα, σκληρό δίσκο. Για να γράψουμε τον κώδικα boot πρέπει να εκτελέσουμε την ακόλουθη εντολή:
pluto# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0 pluto#
Αν τυχών αποτύχει η εντολή με ένα μήνυμα που μας λέει πως ήδη υπάρχει κώδικας μέσα στο Boot Record τότε απλά παραλείπουμε την επιλογή -b, δηλαδή
da0 has bootcode pluto# gpart bootcode -p /boot/gptzfsboot -i 1 da0 pluto#
Επειδή, αποκλείεται να θυμόμαστε τις ακριβείς διαστάσεις των κατατμήσεων disk0, disk1 και disk2 του βασικού σκληρού δίσκου (ελαττωματικού), καλό είναι να ζητήσουμε από το gpart να μας τις δείξει:
pluto# gpart list ad0 Geom name: ad0 fwheads: 16 fwsectors: 63 last: 2930275021 first: 34 entries: 128 scheme: GPT Providers: 1. Name: ad0p1 Mediasize: 262144 (256K) Sectorsize: 512 Mode: r0w0e0 rawtype: 83bd6b9d-7f41-11dc-be0b-001560b84f0f label: (null) length: 262144 offset: 17408 type: freebsd-boot index: 1 end: 545 start: 34 2. Name: ad0p2 Mediasize: 4294967296 (4.0G) Sectorsize: 512 Mode: r1w1e1 rawtype: 516e7cb5-6ecf-11d6-8ff8-00022d09712b label: swap0 length: 4294967296 offset: 279552 type: freebsd-swap index: 2 end: 8389153 start: 546 3. Name: ad0p3 Mediasize: 495790956544 (462G) Sectorsize: 512 Mode: r1w1e2 rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b label: disk0 length: 495790956544 offset: 4295246848 type: freebsd-zfs index: 3 end: 976730865 start: 8389154 4. Name: ad0p4 Mediasize: 500107862016 (466G) Sectorsize: 512 Mode: r1w1e2 rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b label: disk1 length: 500107862016 offset: 500086203392 type: freebsd-zfs index: 4 end: 1953504033 start: 976730866 5. Name: ad0p5 Mediasize: 500106745856 (466G) Sectorsize: 512 Mode: r1w1e2 rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b label: disk2 length: 500106745856 offset: 1000194065408 type: freebsd-zfs index: 5 end: 2930275021 start: 1953504034 Consumers: 1. Name: ad0 Mediasize: 1500300828160 (1.4T) Sectorsize: 512 Mode: r4w4e11 pluto#
Τα partitions που μας ενδιαφέρουν είναι αυτά που έχουν τις ετικέτες disk0, disk1 και disk2, δηλαδή αυτά που έχουν index number 3, 4 και 5, αντίστοιχα. Σε κάθε ένα από αυτά τα block η εντολή μας επιστρέφει δύο τιμές που μας ενδιαφέρουν. Η μια είναι η start και η δεύτερη η length. Για να βρούμε το μέγεθος που θα δώσουμε στις ακόλουθες εντολές θα πρέπει να κάνουμε την πραξη end-start+1. Για τις κατατμήσεις που φαίνονται παραπάνω θα έχουμε:
| Label | Start | End | Calculated Length |
|---|---|---|---|
| disk0 | 8389154 | 976730865 | 976730865 -8389154 +1 = 968341712 |
| disk1 | 976730866 | 1953504033 | 1953504033 -976730866 +1 = 976773168 |
| disk2 | 1953504034 | 2930277134 | 2930277134 -1953504034 +1 = 976773101 |
Τώρα μπορούμε να φτιάξουμε τις κατατμήσεις ξανά με το ίδιο μέγεθος. Το μέγεθος που υπολογίσαμε είναι σε blocks. Τα ονόματα που θα δώσουμε στις καινούργιες κατατμήσεις θα είναι τα main0, main1 και main2, αντίστοιχα. Για την τελευταία κατάτμηση δεν χρειάζεται να δηλώσουμε μέγεθος. Με αυτό τον τρόπο απλά θα καταλάβει όλο το υπόλοιπο τμήμα του σκληρού δίσκου, χωρίς να αφήσει καθόλου αχρησιμοποίητο χώρο.
pluto# gpart add -s 968341712 -t freebsd-zfs -l main0 da0 pluto# gpart add -s 976773168 -t freebsd-zfs -l main1 da0 pluto# gpart add -t freebsd-zfs -l main2 da0 pluto#
Τώρα ο καινούργιος σκληρός πληροί τις προϋποθέσεις για να αντικαταστήσει τον παλιό και ελαττωματικό. Μένει μόνο να μεταφερθούν τα δεδομένα.
β. Αντικατάσταση των τμημάτων των pools
Το ZFS έχει απίστευτες δυνατότητες για όλες τις δουλειές που μπορεί να χρειαστεί κάποιος στο σύστημα αρχείων του. Ακόμα και την αλλαγή των pools έχει προβλέψει! Αυτή τη δυνατότητα είναι που θα χρησιμοποιήσουμε και τώρα:
pluto# zpool replace zroot gpt/disk0 gpt/main0
pluto# zpool status zroot
pool: zroot
state: ONLINE
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scrub: resilver in progress for 0h4m, 1,15% done, 6h15m to go
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
replacing ONLINE 0 0 0
gpt/disk0 ONLINE 259 0 0
gpt/main0 ONLINE 0 0 0 1,23G resilvered
errors: No known data errors
pluto#
Η πρώτη εντολή (replace) ξεκινάει μια διαδικασία που ονομάζεται resilvering. Αυτή η διαδικασία παίρνει, φυσικά, πολύ χρόνο. Το ZFS Subsystem κάνει ότι χρειάζεται στο background, αφήνοντας τον χρήστη να χειρίζεται το μηχάνημα κανονικά. Απλά ο χειρισμός του μηχανήματος είναι λίγο πιο αργός, πράγμα που ούτως ή άλλως συμβαίνει λόγω της ελαττωματικής κατάστασης του σκληρού δίσκου. Τη δεύτερη (status) μπορεί να τη δίνει κάποιος όποτε θέλει, για να βλέπει σε τι κατάσταση έχει φτάσει το resilvering. Έτσι όταν τελειώσει η διαδικασία θα μπορέσει να συνεχίσει με το resilvering των άλλων δύο ZFS Pools. Οι εντολές είναι οι ακόλουθες:
pluto# zpool replace Common1 gpt/disk1 gpt/main1 #wait until this process is finished and then... pluto# zpool replace Common2 gpt/disk2 gpt/main2 #again, wait until the end of the process pluto#
Όταν, με το καλό, τελειώσει όλη η διαδικασία του resilvering σε όλες τις ZFS Pools, ο καινούργιος σκληρός δίσκος θα περιέχει τα δεδομένα του παλιού και οι Pools θα χρησιμοποιούν τον καινούργιο για να δουλέψουν. Άρα ήρθε η ώρα να σβήσει το μηχάνημα και αλλαχθεί ο εσωτερικός και ελαττωματικός σκληρός δίσκος με τον καινούργιο.
pluto# shutdown -p now
Τι έγινε ρε παιδιά! Γιατί το σύστημα δεν κάνει boot;
Κάνοντας boot το σύστημα βλέπουμε ότι μετά το μενού του loader βγαίνουμε σε mountroot με την παρατήρηση ότι δεν μπορεί να γίνει mount η zfs:zroot! Ό,τι και να κάνουμε το σύστημα δε μπορεί να ξεκινήσει το λειτουργικό μας. Αυτό αμέσως θα έπρεπε να μας πονηρέψει ότι κάτι γίνεται με το αρχείο zpool.cache. Αυτό το αρχείο, με λίγα λόγια, περιέχει πληροφορίες για τη δομή των ZFS Pools και είναι βασικό για την εκκίνηση του μηχανήματος. Κατά τη διάρκεια του resilvering το αρχείο αυτό μεταφέρθηκε από τον παλιό σκληρό στον καινούργιο, αλλά οι πληροφορίες που περιέχει είναι με βάση τον παλιό σκληρό. Έτσι, έχουμε λανθασμένες πληροφορίες για τις ZFS Pools που υπάρχουν αυτή τη στιγμή.
Θα παρατηρήσατε βέβαια ότι οι ονομασίες που είχαμε δώσει στα gpt partitions δεν είναι ίδιες με αυτές που υπήρχαν στον παλιό σκληρό δίσκο. Και όμως, όπως θα δούμε παρακάτω, αυτό δεν το ενδιαφέρει το ZFS γιατί τις κατατμήσεις που χρησιμοποιεί τις καταλαβαίνει από ένα μοναδικό ID αριθμό που έχουν από τη στιγμή της κατασκευής τους.
α. Αλλαγή των ονομάτων των gpt partitions
Από τη διαδικασία που περιγράφεται εδώ, το μόνο αναγκαίο είναι το να δώσουμε στο swap partition την ονομασία που είχε και πριν, ώστε να αποφύγουμε να διορθώσουμε το αρχείο /etc/fstab. Τα υπόλοιπα δεν είναι απαραίτητα να γίνουν. Απλά τα κάνουμε για να επανέλθουν οι ονομασίες που είχαμε συνηθίσει και όχι για κάποιον άλλο λόγο. Αυτό θα το αποδείξουμε αμέσως. Η ακόλουθη διαδικασία απαιτεί να κάνουμε boot από το livefs και να μπούμε στην κονσόλα Fixit. Εκεί, πάμε να ελέγξουμε την κατάσταση των ZFS Pools.
Fixit# #lets load the zfs subsystem Fixit# kldload /mnt2/boot/kernel/opensolaris.ko Fixit# kldload /mnt2/boot/kernel/zfs.ko Fixit# export LD_LIBRARY_PATH=/mnt2/lib
Αυτές οι εντολές θα πρέπει να εκτελούνται κάθε φορά που μπαίνουμε στην κονσόλα Fixit για να μπορέσουμε να έχουμε πρόσβαση στις ZFS Pools μας. Σειρά έχει ο έλεγχος των pools:
Fixit# zpool import
pool: Common1
id: 16786791901886102938
state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:
NAME STATE READ WRITE CKSUM
Common1 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/main1 ONLINE 0 0 0
gpt/Mirror1 ONLINE 0 0 0
errors: No known data errors
pool: Common2
id: 2880185314831596717
state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:
NAME STATE READ WRITE CKSUM
Common2 ONLINE 0 0 0
mirror ONLINE 0 0 0
gpt/main2 ONLINE 0 0 0
gpt/Mirror2 ONLINE 0 0 0
errors: No known data errors
pool: zroot
id: 1188189039061593219
state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
gpt/main0 ONLINE 0 0 0
errors: No known data errors
Fixit#
Παρατηρούμε ότι τα gpt partitions που χρησιμοποιούν οι pools είναι τα σωστά. Έτσι δεν είναι πραγματικά ανάγκη να αλλάξουμε αυτά τα ονόματα.
Για να αλλάξουμε τα labels των gpt partitions πρώτα θα πρέπει να εκτελέσουμε τις ακόλουθες εντολές:
Fixit# gpart modify -i 2 -l swap0 ad0 #label the swap partition as swap0 Fixit# gpart modify -i 3 -l disk0 ad0 Fixit# gpart modify -i 4 -l disk1 ad0 Fixit# gpart modify -i 5 -l disk2 ad0
Το μεγάλο πρόβλημα που έχουμε με τη δημιουργία του αρχείου zpool.cache είναι ότι οι pools πρέπει να έχουν γίνει import κανονικά και όχι με altroot. Δηλαδή να μη γίνει χρήση της επιλογής -R στην εντολή import. Αυτό όμως με τη σειρά του προκαλεί ένα σωρό προβλήματα γιατί η zroot κάθεται ακριβώς επάνω στο ήδη υπάρχον σύστημα από το Fixit και αντικαθιστά τα πάντα. Αυτό σημαίνει πως το αρχείο που μας ενδιαφέρει αντιγράφεται από αυτό που υπάρχει μέσα στο σύστημά μας, πριν προλάβουμε να το χρησιμοποιήσουμε. Πρέπει να βρούμε μια λύση να έχουμε το σωστό αρχείο και αυτό γίνεται αναγκαστικά σε δύο στάδια. Στο πρώτο κάνουμε import τη zroot με altroot για να μπορέσουμε τα mountpoints.
Fixit# zpool import -fR /zroot zroot Fixit# zpool import -f Common1 Fixit# zpool import -f Common2 Fixit# zfs unmount -a Fixit# zfs set mountpoint=none zroot Fixit# zpool export Common2 Fixit# zpool export Common1 Fixit# zpool export zroot Fixit#
Αυτά που έχουμε καταφέρει είναι να μην παραπονιέται το σύστημα όταν πάμε να κάνουμε import τις pools, λέγοντας πως χρειάζεται την επιλογή -f και, δεύτερον, το κεντρικό κομμάτι του filesystem της zroot να μη γίνεται mount και έτσι να μην μας απανωγράφει το σύστημα της κονσόλας Fixit. Το πρόβλημα, όμως, που υπάρχει είναι ότι ο κατάλογος /boot/zfs της zroot δεν είναι διαθέσιμος για να γράψουμε μέσα το εν λόγω αρχείο.
Για να δημιουργηθεί το αρχείο zpool.cache θα πρέπει να προϋπάρχει ο κατάλογος /boot/zfs. Αυτό δεν συμβαίνει στην κονσόλα Fixit όπότε τον δημιουργούμε μόνοι μας:
Fixit# mkdir /boot/zfs Fixit#
Το αρχείο zpool.cache θα δημιουργηθεί αυτόματα όταν γίνουν import οι pools. Έτσι:
Fixit# zpool import zroot Fixit# zpool import Common1 Fixit# zpool import Common2 Fixit#
Σε αυτό το σημείο το αρχείο /boot/zfs/zpool.cache έχει δημιουργηθεί με τα στοιχεία που χρειάζεται το σύστημά μας για να λειτουργήσει σωστά. Αρκεί να το αντιγράψουμε σε κάποιο άλλο σημείο της zroot που είναι ήδη προσβάσιμο. Το κατάλληλο μέρος είναι το /tmp. Στη συνέχεια θα κάνουμε κανονικά unmount και θα φτιάξουμε το mountpoint που πειράξαμε.
Fixit# cp /boot/zfs/zpool.cache /tmp Fixit# zfs unmount -a Fixit# zfs set mountpoint=/ zroot Fixit# zpool export Common2 Fixit# zpool export Common1 Fixit# zpool export zroot
Τώρα είμαστε σε θέση να επαναφέρουμε το αρχείο zpool.cache στη σωστή του θέση μέσα στην zroot και να φτιάξουμε και το τελικό mountpoint όπως πρέπει να είναι για να γίνει κανονικά η εκκίνηση από το σύστημα.
Fixit# zpool import -fR /zroot zroot Fixit# zpool import -f Common1 Fixit# zpool import -f Common2 Fixit# cp /zroot/tmp/zpool.cache /zroot/boot/zfs/ Fixit# zfs unmount -a Fixit# zfs set mountpoint=legacy zroot Fixit# reboot . . .
Σε αυτό το σημείο αφήνουμε το μηχάνημα να εκκινήσει κανονικά από τον σκληρό μας δίσκο. Το σύστημα θα εκκινήσει κανονικά, χωρίς προβλήματα, αν όλα έχουν πάει καλά. Γιατί, μην ξεχνάμε, είχαμε και έναν ελαττωματικό σκληρό, όπου τα δεδομένα του ανα πάσα στιγμή θα μπορούσαν να είναι τελειώς διαφορετικά από αυτά που θα έπρεπε να είναι.
Σε όσους ξεκίνησαν να κάνουν το εγχείρημα της αλλαγής του σκληρού δίσκου, τους εύχομαι καλή επιτυχία. May the source be with you!
Χρυσοχέρης Ηλίας



