Khi I/O Buffer trở thành “hố đen”
Bạn đang chạy lệnh rsync định kỳ để sao lưu ổ SATA 2TB cũ, và đột nhiên terminal ngừng phản hồi. Bạn kiểm tra dmesg và thấy hàng loạt lỗi I/O error, dev sdb, sector 123456. Các công cụ Linux tiêu chuẩn được thiết kế cho các hệ thống file (filesystem) khỏe mạnh. Khi gặp bad sector vật lý, chúng thường rơi vào vòng lặp thử lại vô hạn hoặc treo hoàn toàn, để lại một bản sao lưu lỗi, không đầy đủ và một chiếc ổ cứng đang tiến gần hơn tới thùng rác.
Hỏng hóc phần cứng không chờ đợi lịch bảo trì của bạn. Năm ngoái, một ổ đĩa lưu trữ của tôi bắt đầu phát ra những tiếng “cạch cạch” (click of death) đáng sợ ngay khi vừa bắt đầu đồng bộ. Trong những thời điểm đó, mỗi giây đĩa quay đều là một canh bạc. Bạn cần một công cụ không chỉ sao chép dữ liệu, mà còn phải lập bản đồ hư hỏng và ưu tiên các block dữ liệu khỏe mạnh, dễ truy cập trước khi phần cứng hoàn toàn “ngỏm”.
Điểm yếu chí tử của các lệnh tiêu chuẩn
Các tiện ích tiêu chuẩn như cp hoặc dd xử lý lỗi đĩa rất kém vì chúng thiếu cái nhìn tổng thể về tình trạng của ổ cứng. Khi kernel yêu cầu một block và ổ đĩa không đọc được, phần cứng sẽ thử lại nhiều lần trước khi báo lỗi. Điều này gây ra hai vấn đề lớn:
- cp / rsync: Chúng hoạt động ở cấp độ filesystem. Nếu một file video 1GB nằm trên một bad sector duy nhất, lệnh có thể bị treo trong nhiều phút. Nếu bạn buộc nó bỏ qua, bạn thường mất toàn bộ file, mặc dù 99,9% dữ liệu của nó hoàn toàn có thể đọc được.
- dd:
ddtiêu chuẩn hoạt động theo kiểu tuyến tính. Nếu gặp vùng lỗi, nó sẽ dừng lại hoặc lấp đầy sector đó bằng số 0. Vấn đề thực sự là hiệu suất. Nó có thể mất 30 giây để thử lại một sector hỏng trong khi hàng ngàn block khỏe mạnh phía sau vẫn chưa được sao chép. Với một ổ cứng có 500 bad sector,ddcó thể lãng phí hàng giờ đồng hồ để mài đầu đọc cơ học thành bụi.
GNU ddrescue thay đổi hoàn toàn cuộc chơi. Nó sử dụng thuật toán đa luồng (multi-pass) tinh vi để ưu tiên lấy những phần “dễ ăn” trước. Nó sao chép các vùng khỏe mạnh với tốc độ tối đa, sau đó mới quay lại để “cắt” (trim) và “vét” (scrape) những điểm khó nhằn. Nếu ổ cứng bị ngắt kết nối giữa chừng, file bản đồ (mapfile) đảm bảo bạn có thể tiếp tục chính xác tại nơi đã dừng lại.
Chiến lược: Hãy coi Mapfile là “cứu cánh”
Đừng bao giờ chạy ddrescue mà không có mapfile. File này theo dõi block nào đã xong, block nào đang chờ xử lý và block nào đã xác định là hỏng. Đây là thứ cho phép bạn ngắt quãng quá trình, đổi cáp, hoặc thậm chí kết hợp dữ liệu từ hai ổ cứng lỗi khác nhau vào một file ảnh (image) khỏe mạnh duy nhất.
1. Xác định ổ đĩa bị lỗi
Bắt đầu bằng cách xác định nguồn và đích. Đừng bao giờ cố gắng khôi phục dữ liệu lên chính ổ đĩa vật lý đó.
lsblk
dmesg | grep -i error
Trong ví dụ này, chúng ta giả sử /dev/sdb là ổ đĩa sắp hỏng và chúng ta đang lưu file ảnh vào một ổ 4TB khỏe mạnh được mount tại /mnt/recovery.
2. Giai đoạn 1: Thu thập tốc độ cao
Lượt chạy đầu tiên nên ít xâm nhập nhất có thể. Chúng ta muốn bỏ qua bất kỳ sector nào mất hơn một tích tắc để đọc. Điều này giúp bảo vệ phần lớn dữ liệu trước khi motor hoặc bộ điều khiển của ổ cứng hỏng hoàn toàn.
# Cài đặt công cụ
sudo apt update && sudo apt install gddrescue
# Chạy lượt quét nhanh ban đầu
sudo ddrescue -n -b 512 /dev/sdb /mnt/recovery/disk_image.img /mnt/recovery/rescue.map
Giải thích các tham số chính:
-n: Bỏ qua giai đoạn “vét” (scraping) để tránh lãng phí thời gian vào các sector khó ngay từ đầu.-b 512: Thiết lập kích thước sector. Hầu hết các ổ cũ dùng 512, nhưng các ổ “Advanced Format” mới hơn có thể cần 4096.rescue.map: Đây là nhật ký tiến trình của bạn. Hãy bảo vệ nó.
3. Giai đoạn 2: Thử lại có mục tiêu
Khi dữ liệu dễ lấy đã an toàn, hãy yêu cầu ddrescue quyết liệt hơn với các khoảng trống còn lại. Chúng ta sẽ sử dụng I/O trực tiếp để bỏ qua cache của kernel, điều này thường mang lại kết quả đáng tin cậy hơn trên phần cứng bị lỗi.
sudo ddrescue -d -r3 /dev/sdb /mnt/recovery/disk_image.img /mnt/recovery/rescue.map
-d: Truy cập đĩa trực tiếp (Direct I/O). Chậm hơn nhưng bỏ qua sự can thiệp của kernel.-r3: Yêu cầu công cụ thử lại mỗi bad sector 3 lần trước khi bỏ qua.
Theo dõi các chỉ số quan trọng
Hãy chú ý đến trường errsize trong màn hình trạng thái trực tiếp. Đây là chỉ số quan trọng nhất. Nếu bạn thấy errsize là 512KB trên một ổ 1TB, nghĩa là bạn đã khôi phục được 99,999% dữ liệu. Tại thời điểm đó, việc tiếp tục “cày” có thể không đáng để đánh đổi với rủi ro hỏng cơ học hoàn toàn.
Sau khi quá trình hoàn tất, bạn sẽ có một file .img thô. Đừng cố mở nó như một thư mục; nó là một bản sao y hệt từng bit của các phân vùng ổ đĩa.
Gắn (Mount) kết quả
Sử dụng losetup để ánh xạ các phân vùng bên trong file ảnh để bạn có thể mount chúng như các ổ đĩa thực sự:
sudo losetup -fP /mnt/recovery/disk_image.img
# Xác định thiết bị loop mới (thường là /dev/loop0)
lsblk
# Mount phân vùng ở chế độ chỉ đọc
sudo mount -o ro /dev/loop0p1 /mnt/data_recovered
Mẹo nhỏ: Luôn sử dụng cờ ro (read-only). Nếu hệ thống file bên trong file ảnh bị hỏng, việc mount với quyền ghi có thể kích hoạt tiến trình fsck tự động, gây ra nhiều hư hỏng hơn.
So sánh tính năng: Tại sao ddrescue chiến thắng
| Tính năng | dd / cp | GNU ddrescue |
|---|---|---|
| Xử lý lỗi | Treo hoặc hủy bỏ | Bỏ qua và ghi nhật ký |
| Khả năng tiếp tục | Không có | Mặc định (qua mapfile) |
| Bảo vệ dữ liệu | Thấp (Áp lực cao) | Cao (Ưu tiên các block khỏe mạnh) |
Tóm tắt thực thi
Ngay khi bạn nghi ngờ phần cứng bị lỗi, hãy ngừng mọi hoạt động ghi vào ổ đĩa đó. Đừng duyệt thư mục. Đừng chạy fsck. Hư hỏng vật lý là vấn đề phần cứng mà phần mềm chỉ có thể giảm thiểu bằng cách xử lý thông minh.
Quy trình tiêu chuẩn của tôi hiện gồm ba bước: Tạo file ảnh của ổ đĩa bằng ddrescue, cất phần cứng lỗi vào túi chống tĩnh điện, và thực hiện mọi thao tác trích xuất dữ liệu trên file ảnh. Cách tiếp cận này cho bạn vô số lần thử để sửa lỗi filesystem hoặc chạy các công cụ như testdisk mà không phải lo lắng về tiếng đồng hồ đếm ngược của một chiếc motor đang dần hỏng.

