我已經創建了5個1TB硬碟分割區( /dev/sda1
、/dev/sdb1
、/dev/sdc1
、/dev/sde1
和/dev/sdf1
) 中磁碟陣列6在 Ubuntu 14.04 LTS Trusty Tahr 上/dev/md0
呼叫的陣列。mdadm
sudo 指令mdadm --detail /dev/md0
用於顯示所有磁碟機主動同步。
然後,為了進行測試,我透過在陣列中仍處於活動狀態/dev/sdb
時執行這些命令來模擬長 I/O 阻塞:/dev/sdb1
hdparm --user-master u --security-set-pass deltik /dev/sdb
hdparm --user-master u --security-erase-enhanced deltik /dev/sdb
警告
不要在您關心的數據上嘗試此操作!
由於此 ATA 操作,我最終損壞了 455681 個 inode。我承認我的疏忽。
用於安全擦除的 ATA 命令預計將運行 188 分鐘,從而阻止所有其他命令至少在這段時間內運行。
我原本希望md
像正常的 RAID 控制器一樣丟棄無響應的驅動器,但令我驚訝的是,它/dev/md0
也被阻止了。
mdadm --detail /dev/md0
查詢被阻止的設備,因此它凍結並且不會輸出。
/proc/mdstat
這是我無法使用時的佈局mdadm --detail /dev/md0
:
root@node51 [~]# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4] [linear] [multipath] [raid0] [raid1] [raid10]
md0 : active raid6 sdf1[5] sda1[0] sdb1[4] sdc1[2] sde1[1]
2929887744 blocks super 1.2 level 6, 512k chunk, algorithm 2 [5/5] [UUUUU]
unused devices: <none>
我試圖mdadm /dev/md0 -f /dev/sdb1
強行失敗/dev/sdb1
,但也被阻止了:
root@node51 [~]# ps aux | awk '{if($8~"D"||$8=="STAT"){print $0}}'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 3334 1.2 0.0 42564 1800 ? D 03:21 3:37 parted -l
root 4957 0.0 0.0 13272 900 ? D 06:19 0:00 mdadm /dev/md0 -f /dev/sdb1
root 5706 0.0 0.0 13388 1028 ? D 06:19 0:00 mdadm --detail /dev/md0
root 7541 0.5 0.0 0 0 ? D Jul19 6:12 [kworker/u16:2]
root 22420 0.0 0.0 11480 808 ? D 07:48 0:00 lsblk
root 22796 0.0 0.0 4424 360 pts/13 D+ 05:51 0:00 hdparm --user-master u --security-erase-enhanced deltik /dev/sdb
root 23312 0.0 0.0 4292 360 ? D 05:51 0:00 hdparm -I /dev/sdb
root 23594 0.1 0.0 0 0 ? D 06:11 0:07 [kworker/u16:1]
root 25205 0.0 0.0 17980 556 ? D 05:52 0:00 ls --color=auto
root 26008 0.0 0.0 13388 1032 pts/23 D+ 06:32 0:00 mdadm --detail /dev/md0
dtkms 29271 0.0 0.2 58336 10412 ? DN 05:55 0:00 python /usr/share/backintime/common/backintime.py --backup-job
root 32303 0.0 0.0 0 0 ? D 06:16 0:00 [kworker/u16:0]
更新(2015 年 7 月 21 日):在我等待了整整 188 分鐘以清除 I/O 區塊後,當我看到將md
完全空白的資料/dev/sdb
視為完全完好無損時,驚訝變成了恐懼。
我認為這md
至少會看到奇偶校驗不匹配,然後就會下降/dev/sdb1
。
我慌了,mdadm /dev/md0 -f /dev/sdb1
又跑了,由於I/O塊已經解除,命令很快就完成了。
隨著輸入/輸出錯誤的出現,檔案系統損壞已經發生。仍然驚慌失措,我懶惰地卸載了 RAID 陣列中的資料分區,因為reboot -nf
我認為情況不會變得更糟。
在對分區進行了一番艱苦的努力之後e2fsck
,455681 個 inode 進入了lost+found
.
我已經重新組裝了數組,數組本身現在看起來很好:
root@node51 [~]# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Mon Feb 16 14:34:26 2015
Raid Level : raid6
Array Size : 2929887744 (2794.16 GiB 3000.21 GB)
Used Dev Size : 976629248 (931.39 GiB 1000.07 GB)
Raid Devices : 5
Total Devices : 5
Persistence : Superblock is persistent
Update Time : Tue Jul 21 00:00:30 2015
State : active
Active Devices : 5
Working Devices : 5
Failed Devices : 0
Spare Devices : 0
Layout : left-symmetric
Chunk Size : 512K
Name : box51:0
UUID : 6b8a654d:59deede9:c66bd472:0ceffc61
Events : 643541
Number Major Minor RaidDevice State
0 8 1 0 active sync /dev/sda1
1 8 97 1 active sync /dev/sdg1
2 8 33 2 active sync /dev/sdc1
6 8 17 3 active sync /dev/sdb1
5 8 113 4 active sync /dev/sdh1
md
沒有我期望的兩道保護線,這仍然讓我感到相當震驚:
- 設備鎖定時發生故障
- 當設備回傳的資料是垃圾時,設備會發生故障
問題
md
為什麼沒有回應的磁碟機/分割區不會發生故障?- 當磁碟機被封鎖時,我可以從陣列中刪除該磁碟機/分割區嗎?
- 是否可以設定逾時,以便
md
自動使不回應 ATA 命令的磁碟機發生故障? - 為什麼
md
繼續使用資料無效的設備?
答案1
德爾蒂克,您誤解了 Linux 軟體 RAID ( md
) 的工作原理。
md
從多個設備或分割區建立虛擬區塊設備,並且不知道您正在向虛擬設備傳輸什麼資料或從虛擬設備傳輸什麼資料。
你希望它可以做一些它沒有設計要做的事情。
答案
md
1. 為什麼沒有回應的磁碟機/分割區不會故障?
這是因為md
不知道是否
- 驅動器正忙於處理
md
自身請求的 I/O 或 - 由於某些外部情況(例如驅動器本身的錯誤恢復或在您的情況下是 ATA 安全擦除),因此驅動器被阻止,
因此md
將等待查看驅動器返回的內容。驅動器最終沒有傳回任何讀取或寫入錯誤。如果存在讀取錯誤,md
則會自動從奇偶校驗中修復它,如果存在寫入錯誤,md
則會導致裝置故障(請參閱「復原」部分)md
手冊頁)。
由於既沒有讀取錯誤也沒有寫入錯誤,因此md
在核心等待設備回應後繼續使用該設備。
2. 當磁碟機被封鎖時,我可以從陣列中刪除該磁碟機/分割區嗎?
不可以/dev/md0
。
您將-f
或--fail
標誌傳遞給mdadm
“管理”模式。
以下是其實際作用的演練:
case 'f': /* set faulty */
/* FIXME check current member */
if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
(sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
rdev))) {
if (errno == EBUSY)
busy = 1;
pr_err("set device faulty failed for %s: %s\n",
dv->devname, strerror(errno));
if (sysfd >= 0)
close(sysfd);
goto abort;
}
if (sysfd >= 0)
close(sysfd);
sysfd = -1;
count++;
if (verbose >= 0)
pr_err("set %s faulty in %s\n",
dv->devname, devname);
break;
注意來電write(sysfd, "faulty", 6)
。 sysfd
是檔案前面設定的變數:
sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");
sysfs_open()
是一個函數這個文件:
int sysfs_open(char *devnm, char *devname, char *attr)
{
char fname[50];
int fd;
sprintf(fname, "/sys/block/%s/md/", devnm);
if (devname) {
strcat(fname, devname);
strcat(fname, "/");
}
strcat(fname, attr);
fd = open(fname, O_RDWR);
if (fd < 0 && errno == EACCES)
fd = open(fname, O_RDONLY);
return fd;
}
如果您遵循這些函數,您會發現它mdadm /dev/md0 -f /dev/sdb1
基本上是這樣做的:
echo "faulty" > /sys/block/md0/md/dev-sdb1/block/dev
該請求將等待,不會立即通過,因為/dev/md0
被封鎖。
3. 是否可以設定逾時,以便md
自動使不回應 ATA 指令的磁碟機發生故障?
是的。實際上,預設情況下,超時時間為 30 秒:
root@node51 [~]# cat /sys/block/sdb/device/timeout
30
您的假設的問題在於您的驅動器實際上正忙於運行 ATA 命令(持續 188 分鐘),因此它沒有超時。
有關這方面的詳細信息,請參閱Linux 核心 SCSI 錯誤處理文檔。
4. 為什麼md
繼續使用資料無效的設備?
當 ATA 安全性擦除完成時,磁碟機沒有報告任何問題,例如中止的命令,因此md
沒有理由懷疑有問題。
此外,在您使用分割區作為 RAID 裝置而不是整個磁碟的情況下,核心的記憶體分割表不會被告知已擦除磁碟機上的分割區已消失,因此md
將繼續存取您的分割區,/dev/sdb1
就像沒有任何問題一樣。
這是來自md
手冊頁:
擦洗和不匹配
由於儲存裝置隨時可能產生壞區塊,因此定期讀取陣列中所有裝置上的所有區塊以儘早捕獲此類壞區塊非常有價值。這個過程稱為擦洗。
md 陣列可以透過寫入來擦除查看或者維修到文件md/sync_action在裡面系統檔案系統設備的目錄。
請求清理將導致 md 讀取陣列中每個裝置上的每個區塊,並檢查資料是否一致。對於 RAID1 和 RAID10,這表示檢查副本是否相同。對於 RAID4、RAID5、RAID6,這表示檢查奇偶校驗區塊(或多個區塊)是否正確。
我們可以由此推斷,奇偶校驗通常不會在每次磁碟讀取時進行檢查。 (此外,每次讀取時檢查奇偶校驗都會增加完成讀取所需的事務並執行奇偶校驗與資料讀取的比較,從而對效能造成很大的負擔。)
在正常操作下,md
只是假設它正在讀取的資料是有效的,使其容易受到無聲資料損壞。就您而言,由於您擦除了驅動器,整個驅動器中的資料都已悄然損壞。
您的檔案系統不知道損壞。您在檔案系統層級看到輸入/輸出錯誤,因為檔案系統無法理解為什麼它有錯誤的資料。
為了避免靜默資料損壞,首先,永遠不要再做你做過的事。其次,考慮使用ZFS,一個專注於資料完整性並檢測和糾正靜默資料損壞的檔案系統。