Peter Davies

Ramblings

Recovering a NAS RAID with mdadm and LVM

A consumer NAS had died, but the disks were fine. These boxes almost always run Linux underneath, laying the data out as a Linux software RAID (md) with LVM on top, so you can pull a drive, attach it to any Linux machine and read it directly. I did this from a Kali live system, but any recent Debian or Ubuntu will do.

The one rule throughout: mount everything read only. If the array is degraded you do not want the recovery host writing to it.

Tools

apt-get install mdadm lvm2
modprobe dm-mod

Look at what is on the disk

Plug the disk in and see the partitions:

lsblk

A NAS disk has a lot of small partitions (the firmware, swap, config and so on) and one big one for your data. file -s on the data partition confirms it is a RAID member:

file -s /dev/sdb10
/dev/sdb10: Linux Software RAID version 1.2 (1) UUID=... level=1 disks=2

Now read the RAID superblock. The key field is Data Offset, which is how far into the partition the actual filesystem starts:

mdadm --examine /dev/sdb10
/dev/sdb10:
        Version : 1.2
     Raid Level : raid1
   Raid Devices : 2
  Avail Dev Size : 3898521911 (1858.96 GiB 1996.04 GB)
    Data Offset : 2048 sectors
   Super Offset : 8 sectors
          State : clean
   Device Role : Active device 0
   Array State : A. ('A' == active, '.' == missing, 'R' == replacing)

That A. means device 0 is present and its mirror is missing. For a RAID 1 that is fine, as one half of a mirror is a complete copy. The data is all there.

Option 1: let mdadm assemble it

The clean way is to let mdadm assemble the array from the member, force it to run even though it is degraded, then bring up the LVM volume group that lives inside it:

mdadm -A -R /dev/md9 /dev/sdb10
vgchange -ay
mkdir -p /mnt/recovery
mount /dev/<vg-name>/<lv-name> /mnt/recovery -o ro,user

vgchange -ay activates whatever volume group it finds; lsblk or vgs afterwards will show you the volume group and logical volume names to use in the mount.

Option 2: skip mdadm and go straight to the data

Sometimes mdadm will not assemble the array (wrong metadata version, no matching mirror, a fussy live environment). Because this is RAID 1, the filesystem sits as a plain copy at the data offset, so you can expose it as a loop device and let LVM find it directly.

Take the Data Offset from mdadm --examine and multiply by the 512-byte sector size. For an offset of 2048 sectors that is 2048 * 512:

losetup --find --show --read-only --offset $((2048*512)) /dev/sdb10
vgscan
vgchange -ay
mount /dev/<vg-name>/<lv-name> /mnt/recovery -o ro,user

Older firmware used a much smaller offset; on one older box it was 272 sectors, so always read the real value from the superblock rather than assuming.

When the filesystem will not mount cleanly

If the kernel driver refuses the filesystem (a slightly nonstandard ext variant, or minor corruption), fuseext2 will often mount it read only where the kernel will not:

fuseext2 -o ro -o sync_read /dev/mapper/<vg-name>-<lv-name> /mnt/recovery

Get the data off

Once it is mounted, copy everything to a known-good disk and walk away. rsync with --progress lets you see it working and resume if it stops:

mkdir /backup
mount /dev/sdc1 /backup
rsync -a --progress /mnt/recovery/ /backup/

The whole job comes down to three layers in order: the partition, the md RAID on top of it, and the LVM volume inside that. Peel them back one at a time, keep it read only, and a dead NAS is just a disk full of files.