Infrant (now Netgear) ReadyNAS 600, Sparc based, kernel: 2.6.17.14ReadyNAS
A Linux system running Ubuntu (would work with live image: Lucid Lynx used for this.) with 4x SATA ports.
Trying to recover data off the disks from a ReadyNAS 600 on Ubuntu is not as straightforward as the existing guides might lead one to believe, especially getting ext2fuse to compile.
First, the guides:
Written specifically for Ubuntu, and succinct. - Useful for an overview.
Recovering a failed ReadyNAS 1100 array - Has a bit more information.
Mounting Sparc-based ReadyNAS Drives in x86-based Linux - Step by step instructions; this is the most detailed, and the one I'm working off of; please refer to this one to make sense of the rest of this post.
If working off a LiveCD, or a new system, be sure to start off making your editor readable, after opening your terminal.
(This post assumes limited to no Linux experience, beyond being capable of burning an Ubuntu .iso to disc. Anyone attempting recovery of a failed RAID is assumed to have basic problem solving skills and the capacity to learn.)
sudo su
cat >> ~/.vimrc
highlight Normal ctermbg=black ctermfg=white
set background=dark
syntax on
CTRL-D to exit
Now,
agt-get install libfuse-dev
prior to making ext2fuse. Doing so should avoid this:
In file included from readdir.c:1:
readdir.h:6:27: error: fuse_lowlevel.h: No such file or directory
In file included from readdir.c:1:
readdir.h:8: error: expected ‘)’ before ‘req’
readdir.c:7: error: expected ‘)’ before ‘req’
readdir.c:46: error: expected ‘)’ before ‘req’
make[2]: *** [ext2fuse-readdir.o] Error 1
make[2]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1'
make: *** [all] Error 2
You will want to do the following when presented with the library errors, but can safely skip steps 6 thru 8.
ln -s /lib/libcom_err.so.2.1 /lib/libcom_err.so
ln -s /lib/libext2fs.so.2.4 /lib/libext2fs.so
What follows are the errors from running make, and the solutions, with reference as necessary. If you don't get the errors on your system, due to newer headers and the like, you can disregard the (non)relevant solution. Also, I've 'shown my work', so to speak, so as to lend to evaluation whether my solution is correct or not; after all, one shouldn't blindly follow advice from strangers on the intertubes. For the inpatient, simply scroll to the necessary fix.
First compile error:
imager.c:41: error: conflicting types for ‘ssize_t’
/usr/include/unistd.h:221: note: previous declaration of ‘ssize_t’ was here
make[2]: *** [libext2fs_a-imager.o] Error 1
make[2]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1/lib/ext2fs'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1'
make: *** [all] Error 2
in /usr/include/unistd.h around line 221 we see:
#ifndef __ssize_t_defined
typedef __ssize_t ssize_t;
# define __ssize_t_defined
#endif
and __ssize_t gets defined in: /usr/include/bits/types.h:180
__STD_TYPE __SSIZE_T_TYPE __ssize_t; /* Type of a byte count, or error. */
__SSIZE_T_TYPE is defined in: /usr/include/bits/typesizes.h:60
#define __SSIZE_T_TYPE __SWORD_TYPE
And __SWORD_TYPE is defined in /usr/include/bits/types.h:60
# define __SWORD_TYPE int
So, the solution is to simply comment out the redefinition in imager.c
lib/ext2fs/imager.c
#ifndef HAVE_TYPE_SSIZE_T
#ifndef __FreeBSD__
typedef int ssize_t;
#endif
#endif
Solution:
vi lib/ext2fs/imager.c
//typedef int ssize_t;
Next error:
In function ‘open’,
inlined from ‘check_mntent_file’ at ismounted.c:153:
/usr/include/bits/fcntl2.h:51: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT in second argument needs 3 arguments
make[2]: *** [libext2fs_a-ismounted.o] Error 1
make[2]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1/lib/ext2fs'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1'
make: *** [all] Error 2
From here: https://wiki.ubuntu.com/CompilerFlags:
When using open() with O_CREAT, best-practice is to define a valid mode argument. For the least modes, try using (S_IRUSR|S_IWUSR) first. If that doesn't work as expected in the program, then start adding back perms. For example, user and group: (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); user, group, and other: (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH).
And additionally: http://opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html
So, the simple solution is:
vi lib/ext2f/ismounted.c, around line 153
from:
fd = open(TEST_FILE, O_RDWR|O_CREAT);
to:
fd = open(TEST_FILE, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
Next (snipped some duplicate lines for brevity):
llseek.c:68: error: expected declaration specifiers or ‘...’ before ‘_llseek’
llseek.c:68: error: expected declaration specifiers or ‘...’ before ‘fd’
llseek.c:68: error: expected declaration specifiers or ‘...’ before ‘offset_high’
llseek.c:69: error: expected declaration specifiers or ‘...’ before ‘offset_low’
llseek.c:69: error: expected declaration specifiers or ‘...’ before ‘result’
llseek.c:70: error: expected declaration specifiers or ‘...’ before ‘origin’
llseek.c: In function ‘_syscall5’:
llseek.c:74: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
llseek.c:68: error: parameter name omitted
llseek.c:117: error: expected ‘{’ at end of input
make[2]: *** [libext2fs_a-llseek.o] Error 1
make[2]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1/lib/ext2fs'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/bin/ext2fuse-src-0.8.1'
make: *** [all] Error 2
I found a solution here: http://www.mail-archive.com/sisuite-users@lists.sourceforge.net/msg03353.html:
in lib/ext2fs/llseek.c: around line 66
#ifndef __i386__
static int _llseek (unsigned int, unsigned long,
unsigned long, ext2_loff_t *, unsigned int);
static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
unsigned long, offset_low,ext2_loff_t *,result,
unsigned int, origin)
comment out, and do:
static int _llseek (unsigned int fd, unsigned long oh,
unsigned long ol, long long *result,
unsigned int origin) {
return syscall (__NR__llseek, fd, oh, ol, result, origin);
}
With any luck, it'll compile, and you can `make install` now. Then, this command is needed, from a developer post on the Netgear forums:
mdadm --create /dev/md2 -f -c 16 -l 5 -p la -n 4 /dev/sdb3 /dev/sdc3 /dev/sdd3 missing
Modify the above to suit your actual system (fdisk -lu to see your drives). Then, if you're unfortunate enough not to have a clean volume, you've a bit more work to do (this is with 250gb drives):
pvscan
Incorrect metadata area header checksum
PV /dev/md2 lvm2 [691.11 GiB]
Total: 1 [691.11 GiB] / in use: 0 [0 ] / in no VG: 1 [691.11 GiB]
pvdisplay /dev/md2
Incorrect metadata area header checksum
"/dev/md2" is a new physical volume of "691.11 GiB"
--- NEW Physical volume ---
PV Name /dev/md2
VG Name
PV Size 691.11 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID Epe2Ox-iNYp-T6nY-fD3F-9zag-HWmq-tMs5rq
So, this is the part you shouldn't do unless it's a last resort. (Reference: http://www.tldp.org/HOWTO/LVM-HOWTO/recovermetadata.html)
(volc.txt was created by doing:
dd if=/dev/md2 bs=512 count=255 skip=1 of=nasconfig
and then manually extracting the LVM config with ghex and putting it in a text file (see references at end))
pvcreate --uuid "Epe2Ox-iNYp-T6nY-fD3F-9zag-HWmq-tMs5rq" --restorefile /etc/lvm/archive/c_00000.vg /dev/md2
Incorrect metadata area header checksum
Incorrect metadata area header checksum
Physical volume "/dev/md2" successfully created
vgcfgrestore -f volc.txt c
Restored volume group c
Reading all physical volumes. This may take a while...
Found volume group "c" using metadata type lvm2
vgdisplay
--- Volume group ---
VG Name c
System ID nas-00-xx-xx 1221946398
Format lvm2
Metadata Areas 1
Metadata Sequence No 2
VG Access read/write
VG Status resizable
MAX LV 256
Cur LV 1
Open LV 0
Max PV 256
Cur PV 1
Act PV 1
VG Size 691.06 GiB
PE Size 32.00 MiB
Total PE 22114
Alloc PE / Size 22114 / 691.06 GiB
Free PE / Size 0 / 0
VG UUID ghNwGu-XNBV-Rnyc-ojT7-D5IE-hRCp-07uygA
vgchange -ay c
1 logical volume(s) in volume group "c" now active
lvdisplay
--- Logical volume ---
LV Name /dev/c/c
VG Name c
LV UUID 000000-0000-0000-0000-0000-0000-000000
LV Write Access read/write
LV Status available
# open 0
LV Size 691.06 GiB
Current LE 22114
Segments 1
Allocation normal
Read ahead sectors 1024
Block device 252:0
If you're lucky, or sacrificed the requisite virginal nerd while chanting source from the Editor of the Beast, you can now mount and retrieve data, wiser and forever having learned that a NAS device doesn't count as 'backing up'.
Further Reference:
http://www.readynas.com/forum/viewtopic.php?t=14828 - Forum thread on the Netgear forums.
http://www.linuxjournal.com/article/8874?page=0,2 - Format of the LVM metadata; good for creating the .txt file to feed back in.
http://www.akadia.com/services/logical_volume_manager.html - An excellent guide to LVM, with pretty pictures!