BaffaloのTeraStation(テラステーション)のディスクにエラーがでた。4台でRAID5を組んでいた。
Disk1に赤ランプがついた。
なので、Disk1を交換してリビルドを開始したらDisk2に赤ランプがついた。
リビルド中の故障という最悪の事態。
テラステーションの電源を再投入すると、RAIDセットが見当たらない。
すべてのファイルを失うかと思ったが、以下の手法で幸いほとんどすべてのファイルを救うことが出来た。
ただし、手順を間違えるととどめを刺す可能性もあるので注意。
※ファイルを救える条件は、Diskがエラーカウントが増えてRAID的にはfailしただけで、物理的にはまだ完全には壊れていないこと。
※ここに書いてあることをやって、うまくいかなくても責任は取りません。
先人たちの努力に感謝したい。以下、参考にしたページたち。
1.Linux PCの準備
適当なLinux PCを用意する。今回の場合はCentosLive 6.8を使った。この場合、OSはDVDでブートするので、LinuxをHDDにインストー ルする必要が無い。
テラステーションのディスクを取り出し、今回は全部のディスク、Disk1, Disk2, Disk3, Disk4を繋げた。
2. RAID5の状態の確認
cat /etc/mdstat
でRAID状態の確認。md126が実際にデータが入っている領域。
RAIDを止める。
mdadm --stop /dev/md126
各Diskの状態の確認
mdadm --examine /dev/sda6
mdadm --examine /dev/sdb6
mdadm --examine /dev/sdc6
mdadm --examine /dev/sdd6
今回の場合、sdc6とsdd6は正しくRAID5の情報が見れた。
sda6の場合はsuper blockが無いと言われた。
sdbについてはパーティション情報も消えていた。
念のためsdbにpartedを使って他のsdc6と同じ容量でパーティションを切ってみたところ、まだディスクの中にはRAID5のデータは残され ているようであった。
ここではDisk1 (sda6), Disk3 (sdc6), Disk4 (sdd6)の3台を使ってデータの復旧を試みる。
※3台以上のディスクでsuper blockが確認できるのであれば、mdadm -A /dev/md126 -u UUID --run --force で強制的にRAID5を起動出来 ると思われる。super blockが消えているものがある場合、または--forceで強制起動できない場合は、Super blockの復旧を行う必要があ る。
以下に正しく取得できたsuper blockの情報を書いた。NameとArrayy UUIDとDevice UUIDは伏せてある。
Disk3とDisk4はActiveであるが、Disk1とDisk2がmissingになっている。
/dev/sdd6: Magic : a92b4efc Version : 1.2 Feature Map : 0x0 Array UUID : XXXXXXXX:XXXXXXXX:XXXXXXXX:XXXXXXXX Name : HOGEHOGE Creation Time : Wed Jul 27 02:04:37 2011 Raid Level : raid5 Raid Devices : 4 Avail Dev Size : 1923500032 (917.20 GiB 984.83 GB) Array Size : 2885248512 (2751.59 GiB 2954.49 GB) Used Dev Size : 1923499008 (917.20 GiB 984.83 GB) Data Offset : 2048 sectors Super Offset : 8 sectors Unused Space : before=1968 sectors, after=1024 sectors State : clean Device UUID : YYYYYYYY:YYYYYYYY:YYYYYYYY:YYYYYYYY Update Time : Wed Dec 28 01:14:21 2016 Checksum : df1f1fcf - correct Events : 34982066 Layout : left-symmetric Chunk Size : 512K Device Role : Active device 2 Array State : ..AA ('A' == active, '.' == missing, 'R' == replacing)3. 健全なSuper Blockの抽出
mdadm --examineでRAID情報を見るとバージョンは1.2であった。
これはSuper blockのversionが1であることを示していて、以下ではSuper block version 1の場合について書く。
他のWebサイトではversion 0のSuper blockであったとの報告もあるようなので、その場合は別サイトを参照願いたい。
まずは健全なSuper Blockを抽出する。
mdadm --examineの情報によると、Super Offset は8 sectorsなので、512 * 8 = 4096 BytesからSuper blockが書かれていることがわかる。
また、Super block version 1の場合は、一般に最大1KBytesの領域を使うので、ここをごっそりコピーしてくる。
bs1dump.cというプログラムを作成した。コンパイルして、 ./bs1dump /dev/sdd6 のようにして使う。
dump1.datというファイルにバイナリが出力される。 od -X dump1.dat でバイナリを確認できる。
bs1show.cを使うと、わかり易い内容で表示できる。./bs1show dump1.dat
※今回作ったプログラムはこのページの最後にまとめて載せておきます。
4. Super Blockの改変
RAID5の4台のディスク中3台は生きていますよ、という情報を作ってあげないとならない。
Disk3とDisk4の場合は、Super blockが生きているので、Disk1も元気ですよという情報に改変する。
Disk1も同様なのだが、Super blockが消えているので、dev_numberとdevice_UUIDを適当に決めてあげる必要がある。今回は dev_numberは0にして、device_UUIDはuuidegenというコマンドから適当に作ったUUIDを使った。
Disk3とDisk4用のプログラムは bs1renew.c で、./bs1renew sdd6org.dat sdd6new.dat
のようにする。sdd6org.datは先ほどbs1dump.cで抽出したdump1.datをコピーしたもの。
Disk1用のプログラムはbs1recre.cで./bs1recre sdd6org.dat sda6new.dat とやる。
ベースとなるSuper blockのdev_numberとdevice_UUIDを改変して新しいSuper blockを作る。
変えるべきdev_numberとdevice_UUIDの値はプログラムの上部で直接書くようにしているので、そこを編集すべし。
5. Super Blockの上書きとRAIDの起動
bs1update.cを使って、改変したSuper blockを書き込んでいく。
./bs1update /dev/sda6 sda6new.dat
./bs1update /dev/sdc6 sdc6new.dat
./bs1update /dev/sdd6 sdd6new.dat
これでmdadm --examine /dev/sdda6 等やって、
Device Role : Active device 0 Array State : A.AA ('A' == active, '.' == missing, 'R' == replacing)となれば良い。その他Check SumやUUID等に間違えが無いかも確認。
ここまで来たら、mdadm -A /dev/md126 -u Array_UUID
とやって、RAIDを起動させる。
場合によってはxfsファイルシステムがおかしい場合もあるので、
/sbin/xfs_repair /dev/md126
をやる。ただし、repairしてとどめを刺す可能性もあるので、やらない方が良いかもしれない。運まかせ。
※centosliveにはxfs_repairが見当たらなかったので、別のLinuxからバイナリをコピーして使いました。
※xfs_repair -nをやると診断だけ行う。今回の場合は、xfsには問題はなかった。
で、最後にマウント。
mount /dev/md126 /raid 等。
これで、/raid以下のファイルが見えたら成功。
rsync 等でごっそり別コンピュータや別ディスクにコピーするのも良いが、ファイルによってはディスクのダメなブロックに当たる可能性 もあるので、特に重要なファイルからコピーして、その後rsyncをかけると良いと思われる。
今回の場合は、上記の方法ですべてのファイルを救い出すことが出来た。ディスクが完全には壊れていなかったのがラッキーであった。
ちなみにパーティション情報が消えていたDisk2のSMART情報を見てみるとPre-failが出ていた。それでもまだ完全には壊れていない。 Disk1は特に何も出ていなかった。
6. プログラムたち
bs1dump.c
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#define _LARGEFILE64_SOURCE
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <linux/types.h>#include <string.h>static void dump1(char *dev){
int ifd, ofd;
char buff[1024], name[256]={0};
sprintf(name, "dump1.dat"); if((ifd = open(dev,O_RDONLY) ) > 0 ) { lseek64(ifd,4096,SEEK_SET); read(ifd, buff, 1024); close(ifd); }else{ printf("faild to open %s\n", dev); return; } if((ofd = open(name,O_WRONLY|O_CREAT, 0644)) > 0 ){ write(ofd,buff,1024); close(ofd); }else{ printf("failed to write %s\n", name); }}int main(int argc, char *argv[]){ if(argc < 2){ printf("bs1dump DEVICE\n"); return 0; } dump1(argv[1]); return 0;}bs1show.c
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#define _LARGEFILE64_SOURCE
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <linux/types.h>#include <libgen.h>#include <string.h>#include "super1.h"static void show1(char *file){
int ifd, i;
char buff[1024], name[256]={0};
struct mdp_superblock_1 super; if((ifd = open(file,O_RDONLY) ) > 0 ) { read(ifd, buff, 1024); close(ifd); }else{ printf("faild to open %s\n", file); return; } memcpy((char *)&super, buff, sizeof(super)); printf("%-20s : %08x\n", "magic", super.magic); printf("%-20s : %u\n", "major_version", super.major_version); printf("%-20s : %u\n", "feature_map", super.feature_map); printf("%-20s : %u\n", "pad0", super.pad0); printf("%-20s : ", "set_uuid"); for(i=0;i<16;i++){ printf("%02x", super.set_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %s\n", "set_name", super.set_name); printf("%-20s : %llu\n", "ctime", super.ctime); printf("%-20s : %u\n", "level", super.level); printf("%-20s : %u\n", "layout", super.layout); printf("%-20s : %llu\n", "size", super.size); printf("%-20s : %u\n", "chunksize", super.chunksize); printf("%-20s : %u\n", "raid_disks", super.raid_disks); printf("%-20s : %u\n", "bitmap_offset", super.bitmap_offset); printf("%-20s : %u\n", "new_level", super.new_level); printf("%-20s : %llu\n", "reshape_position", super.reshape_position); printf("%-20s : %u\n", "delta_disks", super.delta_disks); printf("%-20s : %u\n", "new_layout", super.new_layout); printf("%-20s : %u\n", "new_chunk", super.new_chunk); printf("%-20s : %u\n", "new_offset", super.new_offset); printf("%-20s : %llu\n", "data_offset", super.data_offset); printf("%-20s : %llu\n", "data_size", super.data_size); printf("%-20s : %llu\n", "super_offset", super.super_offset); printf("%-20s : %llu\n", "recovery_offset", super.recovery_offset); printf("%-20s : %u\n", "dev_number", super.dev_number); printf("%-20s : %u\n", "cnt_corrected_read", super.cnt_corrected_read); printf("%-20s : ", "device_uuid"); for(i=0;i<16;i++){ printf("%02x", super.device_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %u\n", "devflags", super.devflags); printf("%-20s : %u\n", "bblog_shift", super.bblog_shift); printf("%-20s : %u\n", "bblog_size", super.bblog_size); printf("%-20s : %u\n", "bblog_offset", super.bblog_offset); printf("%-20s : %llu\n", "utime", super.utime); printf("%-20s : %llu\n", "events", super.events); printf("%-20s : %llu\n", "resync_offset", super.resync_offset); printf("%-20s : %x\n", "sb_csum", super.sb_csum); printf("%-20s : %u\n", "max_dev", super.max_dev); printf("%-20s : ", "pad3"); for(i=0;i<32;i++){ printf("%u", super.pad3[i]); } printf("\n"); printf("%-20s : %x\n", "dev_roles", super.dev_roles[0]);}int main(int argc, char *argv[]){ if(argc < 2){ printf("bs1show FILE\n"); return 0; } show1(argv[1]); return 0;}super1.h
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*//* originaly from mdadm-3.3.4 super1.c */struct mdp_superblock_1 { /* constant array information - 128 bytes */ __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ __u32 major_version; /* 1 */ __u32 feature_map; /* 0 for now */ __u32 pad0; /* always set to 0 when writing */ __u8 set_uuid[16]; /* user-space generated. */ char set_name[32]; /* set and interpreted by user-space */ __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ __u32 layout; /* only for raid5 currently */ __u64 size; /* used size of component devices, in 512byte sectors */ __u32 chunksize; /* in 512byte sectors */ __u32 raid_disks; __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts * NOTE: signed, so bitmap can be before superblock * only meaningful of feature_map[0] is set. */ /* These are only valid with feature bit '4' */ __u32 new_level; /* new level we are reshaping to */ __u64 reshape_position; /* next address in array-space for reshape */ __u32 delta_disks; /* change in number of raid_disks */ __u32 new_layout; /* new layout */ __u32 new_chunk; /* new chunk size (sectors) */ __u32 new_offset; /* signed number to add to data_offset in new * layout. 0 == no-change. This can be * different on each device in the array. */ /* constant this-device information - 64 bytes */ __u64 data_offset; /* sector start of data, often 0 */ __u64 data_size; /* sectors in this device that can be used for data */ __u64 super_offset; /* sector start of this superblock */ __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ __u32 dev_number; /* permanent identifier of this device - not role in raid */ __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ __u8 device_uuid[16]; /* user-space setable, ignored by kernel */ __u8 devflags; /* per-device flags. Only one defined...*/#define WriteMostly1 1 /* mask for writemostly flag in above */ /* bad block log. If there are any bad blocks the feature flag is set. * if offset and size are non-zero, that space is reserved and available. */ __u8 bblog_shift; /* shift from sectors to block size for badblocklist */ __u16 bblog_size; /* number of sectors reserved for badblocklist */ __u32 bblog_offset; /* sector offset from superblock to bblog, signed */ /* array state information - 64 bytes */ __u64 utime; /* 40 bits second, 24 btes microseconds */ __u64 events; /* incremented when superblock updated */ __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ __u32 sb_csum; /* checksum upto dev_roles[max_dev] */ __u32 max_dev; /* size of dev_roles[] array to consider */ __u8 pad3[64-32]; /* set to 0 when writing */ /* device state information. Indexed by dev_number. * 2 bytes per device * Note there are no per-device state flags. State information is rolled * into the 'roles' value. If a device is spare or faulty, then it doesn't * have a meaningful role. */ __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */};bs1renew.c
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#define _LARGEFILE64_SOURCE
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <linux/types.h>#include <libgen.h>#include <string.h>#include "super1.h"#define __cpu_to_le16(_x) (unsigned int)(_x)#define __cpu_to_le32(_x) (unsigned int)(_x)#define __cpu_to_le64(_x) (unsigned long long)(_x)#define __le16_to_cpu(_x) (unsigned int)(_x)#define __le32_to_cpu(_x) (unsigned int)(_x)#define __le64_to_cpu(_x) (unsigned long long)(_x)// specify your disks and device state// 0xfffe = fail, numerical numbers = active#define NOFDISK 4const __u16 devstate[NOFDISK] = {0, 0xfffe, 2, 3};/* originaly from mdadm-3.3.4 super1.c */static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb){ unsigned int disk_csum, csum;
unsigned long long newcsum;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
unsigned int *isuper = (unsigned int*)sb;
/* make sure I can count... */ if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
offsetof(struct mdp_superblock_1, utime) != 192 ||
sizeof(struct mdp_superblock_1) != 256) {
fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
}
disk_csum = sb->sb_csum;
sb->sb_csum = 0;
newcsum = 0;
for (; size>=4; size -= 4 ) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}
if (size == 2)
newcsum += __le16_to_cpu(*(unsigned short*) isuper);
csum = (newcsum & 0xffffffff) + (newcsum >> 32);
sb->sb_csum = disk_csum;
return __cpu_to_le32(csum);
}static void renew1(char *file, char *out){
int ifd, ofd, i;
char buff[1024], name[256]={0};
struct mdp_superblock_1 super; __u32 revcsum; if((ifd = open(file,O_RDONLY) ) > 0 ) { read(ifd, buff, 1024); close(ifd); }else{ printf("faild to open %s\n", file); return; } memcpy((char *)&super, buff, sizeof(super)); printf("%-20s : %08x\n", "magic", super.magic); printf("%-20s : %u\n", "major_version", super.major_version); printf("%-20s : %u\n", "feature_map", super.feature_map); printf("%-20s : %u\n", "pad0", super.pad0); printf("%-20s : ", "set_uuid"); for(i=0;i<16;i++){ printf("%02x", super.set_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %s\n", "set_name", super.set_name); printf("%-20s : %llu\n", "ctime", super.ctime); printf("%-20s : %u\n", "level", super.level); printf("%-20s : %u\n", "layout", super.layout); printf("%-20s : %llu\n", "size", super.size); printf("%-20s : %u\n", "chunksize", super.chunksize); printf("%-20s : %u\n", "raid_disks", super.raid_disks); printf("%-20s : %u\n", "bitmap_offset", super.bitmap_offset); printf("%-20s : %u\n", "new_level", super.new_level); printf("%-20s : %llu\n", "reshape_position", super.reshape_position); printf("%-20s : %u\n", "delta_disks", super.delta_disks); printf("%-20s : %u\n", "new_layout", super.new_layout); printf("%-20s : %u\n", "new_chunk", super.new_chunk); printf("%-20s : %u\n", "new_offset", super.new_offset); printf("%-20s : %llu\n", "data_offset", super.data_offset); printf("%-20s : %llu\n", "data_size", super.data_size); printf("%-20s : %llu\n", "super_offset", super.super_offset); printf("%-20s : %llu\n", "recovery_offset", super.recovery_offset); printf("%-20s : %u\n", "dev_number", super.dev_number); printf("%-20s : %u\n", "cnt_corrected_read", super.cnt_corrected_read); printf("%-20s : ", "device_uuid"); for(i=0;i<16;i++){ printf("%02x", super.device_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %u\n", "devflags", super.devflags); printf("%-20s : %u\n", "bblog_shift", super.bblog_shift); printf("%-20s : %u\n", "bblog_size", super.bblog_size); printf("%-20s : %u\n", "bblog_offset", super.bblog_offset); printf("%-20s : %llu\n", "utime", super.utime); printf("%-20s : %llu\n", "events", super.events); printf("%-20s : %llu\n", "resync_offset", super.resync_offset); printf("%-20s : %08x\n", "sb_csum", super.sb_csum); printf("%-20s : %u\n", "max_dev", super.max_dev); printf("%-20s : ", "pad3"); for(i=0;i<32;i++){ printf("%u", super.pad3[i]); } printf("\n"); printf("%-20s : %x\n", "dev_roles", super.dev_roles[0]); memset(buff, 0xff, sizeof(buff)); memcpy(buff, (char *)&super, sizeof(super)); for(i=0;i<super.raid_disks;i++){ memcpy(buff+sizeof(super)+i*2, (char *)&devstate[i], 2); } revcsum = calc_sb_1_csum((struct mdp_superblock_1 *)buff); printf("%-20s : %08x\n", "sb_csum org ", super.sb_csum); printf("%-20s : %08x\n", "sb_csum reviced", revcsum); super.sb_csum = revcsum; memcpy(buff, (char *)&super, sizeof(super)); if((ofd = open(out,O_WRONLY|O_CREAT, 0644) ) > 0 ) { write(ofd, (char *)&buff, 1024); close(ofd); }else{ printf("faild to write %s\n", file); return; }}int main(int argc, char *argv[]){ if(argc < 2){ printf("bs1show IN-FILE OUT-FILE\n"); return 0; } renew1(argv[1], argv[2]); return 0;}bs1recre.c
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#define _LARGEFILE64_SOURCE
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <linux/types.h>#include <libgen.h>#include <string.h>#include "super1.h"#define __cpu_to_le16(_x) (unsigned int)(_x)#define __cpu_to_le32(_x) (unsigned int)(_x)#define __cpu_to_le64(_x) (unsigned long long)(_x)#define __le16_to_cpu(_x) (unsigned int)(_x)#define __le32_to_cpu(_x) (unsigned int)(_x)#define __le64_to_cpu(_x) (unsigned long long)(_x)// specify your disks and device state// 0xfffe = fail, numerical numbers = active#define NOFDISK 4const __u16 devstate[NOFDISK] = {0, 0xfffe, 2, 3};// specify your number and device uuidconst __u32 new_dev_number = 0;const __u8 new_device_uuid[16] = {0xc9, 0x7b, 0x4b, 0x36, 0xc4, 0x5a, 0x41, 0x51, 0x95, 0x74, 0xb7, 0x18, 0xa6, 0x31, 0x3f, 0x89};/* originaly from mdadm-3.3.4 super1.c */static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb){ unsigned int disk_csum, csum;
unsigned long long newcsum;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
unsigned int *isuper = (unsigned int*)sb;
/* make sure I can count... */ if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
offsetof(struct mdp_superblock_1, utime) != 192 ||
sizeof(struct mdp_superblock_1) != 256) {
fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
}
disk_csum = sb->sb_csum;
sb->sb_csum = 0;
newcsum = 0;
for (; size>=4; size -= 4 ) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}
if (size == 2)
newcsum += __le16_to_cpu(*(unsigned short*) isuper);
csum = (newcsum & 0xffffffff) + (newcsum >> 32);
sb->sb_csum = disk_csum;
return __cpu_to_le32(csum);
}static void recre1(char *file, char *out){
int ifd, ofd, i;
char buff[1024], name[256]={0};
struct mdp_superblock_1 super; __u32 revcsum; if((ifd = open(file,O_RDONLY) ) > 0 ) { read(ifd, buff, 1024); close(ifd); }else{ printf("faild to open %s\n", file); return; } memcpy((char *)&super, buff, sizeof(super)); printf("%-20s : %08x\n", "magic", super.magic); printf("%-20s : %u\n", "major_version", super.major_version); printf("%-20s : %u\n", "feature_map", super.feature_map); printf("%-20s : %u\n", "pad0", super.pad0); printf("%-20s : ", "set_uuid"); for(i=0;i<16;i++){ printf("%02x", super.set_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %s\n", "set_name", super.set_name); printf("%-20s : %llu\n", "ctime", super.ctime); printf("%-20s : %u\n", "level", super.level); printf("%-20s : %u\n", "layout", super.layout); printf("%-20s : %llu\n", "size", super.size); printf("%-20s : %u\n", "chunksize", super.chunksize); printf("%-20s : %u\n", "raid_disks", super.raid_disks); printf("%-20s : %u\n", "bitmap_offset", super.bitmap_offset); printf("%-20s : %u\n", "new_level", super.new_level); printf("%-20s : %llu\n", "reshape_position", super.reshape_position); printf("%-20s : %u\n", "delta_disks", super.delta_disks); printf("%-20s : %u\n", "new_layout", super.new_layout); printf("%-20s : %u\n", "new_chunk", super.new_chunk); printf("%-20s : %u\n", "new_offset", super.new_offset); printf("%-20s : %llu\n", "data_offset", super.data_offset); printf("%-20s : %llu\n", "data_size", super.data_size); printf("%-20s : %llu\n", "super_offset", super.super_offset); printf("%-20s : %llu\n", "recovery_offset", super.recovery_offset); super.dev_number = new_dev_number; printf("%-20s : %u\n", "dev_number", super.dev_number); printf("%-20s : %u\n", "cnt_corrected_read", super.cnt_corrected_read); for(i=0;i<16;i++){ super.device_uuid[i] = new_device_uuid[i]; } printf("%-20s : ", "device_uuid"); for(i=0;i<16;i++){ printf("%02x", super.device_uuid[i]); if(i==3 || i==5 || i==7 || i==9){ printf("-"); } } printf("\n"); printf("%-20s : %u\n", "devflags", super.devflags); printf("%-20s : %u\n", "bblog_shift", super.bblog_shift); printf("%-20s : %u\n", "bblog_size", super.bblog_size); printf("%-20s : %u\n", "bblog_offset", super.bblog_offset); printf("%-20s : %llu\n", "utime", super.utime); printf("%-20s : %llu\n", "events", super.events); printf("%-20s : %llu\n", "resync_offset", super.resync_offset); printf("%-20s : %08x\n", "sb_csum", super.sb_csum); printf("%-20s : %u\n", "max_dev", super.max_dev); printf("%-20s : ", "pad3"); for(i=0;i<32;i++){ printf("%u", super.pad3[i]); } printf("\n"); printf("%-20s : %x\n", "dev_roles", super.dev_roles[0]); memset(buff, 0xff, sizeof(buff)); memcpy(buff, (char *)&super, sizeof(super)); for(i=0;i<super.raid_disks;i++){ memcpy(buff+sizeof(super)+i*2, (char *)&devstate[i], 2); } revcsum = calc_sb_1_csum((struct mdp_superblock_1 *)buff); printf("%-20s : %08x\n", "sb_csum org ", super.sb_csum); printf("%-20s : %08x\n", "sb_csum reviced", revcsum); super.sb_csum = revcsum; memcpy(buff, (char *)&super, sizeof(super)); if((ofd = open(out,O_WRONLY|O_CREAT, 0644) ) > 0 ) { write(ofd, (char *)&buff, 1024); close(ofd); }else{ printf("faild to write %s\n", file); return; }}int main(int argc, char *argv[]){ if(argc < 2){ printf("bs1show IN-FILE OUT-FILE\n"); return 0; } recre1(argv[1], argv[2]); return 0;}bs1update.c
/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#define _LARGEFILE64_SOURCE
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <linux/types.h>#include <libgen.h>#include <string.h>static void update1(char *dev, char *file){ int ifd, ofd;
char buff[1024];
if((ifd = open(file,O_RDONLY) ) > 0 ) { read(ifd, buff, 1024); close(ifd); }else{ printf("faild to open %s\n", file); return; } if((ofd = open(dev,O_WRONLY) ) > 0 ) { lseek64(ifd,4096,SEEK_SET); write(ofd, buff, 1024); close(ifd); }else{ printf("faild to write %s\n", dev); return; }}int main(int argc, char *argv[]){ if(argc < 3){ printf("bs1update DEVICE FILE\n"); return 0; } update1(argv[1], argv[2]); return 0;}