No-copy Method of DNS-321 RAID-1 Upgrade/Upsize Using Swap Partitions

Photo by 🇨🇭 Claudio Schwarz | @purzlbaum on Unsplash

TL;DR

  1. Software RAID-1 normally do not support dynamic resizing of capacity if larger hard drives are swapped into the RAID array.

Introduction

Yes, the photo above shows a Synology DiskStation. Unfortunately, my early NAS was not a Synology, but a D-Link DNS-321. It does its job well for many years. I opted for a RAID-1 configuration providing me a realtime backup of all my files (I had hard drives failed on me many times).

The Synology NAS’ has the SHR (Synology Hybrid RAID) file system which provides a lot of cool features like

  1. Mixing hard disks of various sizes

Back to topic, I have a D-Link DNS-321 with 250GB x2 drives. Fortunately, I was able to salvage 2x 2 TB hard drives from my newly upgraded servers.

How would I upgrade the D-Link DNS-321 without manually copying of files across the network or using a separate rig?

Premise

Here in my DNS-321 configuration

SYSTEM INFO
Firmware version: 1.03
Volume Type: RAID 1
HARD DRIVE INFO
Slot: Left
Manufacturer: WD20EFRX-68AX9N
Model: WD20EFRX-68AX9N
Size: 2000 GB
Slot: Right
Manufacturer: WD20EFRX-68AX9N
Model: WD20EFRX-68AX9N
Size: 2000 GB

This model does not have a USB port, so I cannot even boot from a USB stick.

It is also worth noting that you would be executing all disk operations using the processor of the DNS-321, which is not too great by 2021 standards.

# cat /proc/cpuinfo
Processor : ARM926EJ-S rev 0 (v5l)
BogoMIPS : 266.24
Features : swp half thumb fastmult edsp
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 0
Cache type : write-back
Cache clean : cp15 c7 ops
Cache lockdown : format C
Cache format : Harvard
I size : 32768
I assoc : 1
I line length : 32
I sets : 1024
D size : 32768
D assoc : 1
D line length : 32
D sets : 1024
Hardware : Feroceon
Revision : 0000
Serial : 0000000000000000

Hence, please allow plenty of hours (aka overnight jobs). Else, you can utilize the same steps by hooking up the drives on a more powerful rig.

Fun_Plug

Various NAS devices allows the execution of a script: fun_plug in Volume 1 of the NAS. Fonz Fun_Plug is a collection of scripts and tools to be used in a NAS setup; including telnet and ssh capabilities.

First, download these files:

fun_plug

You MUST download the following gist into a fun_plug file in order to complete the steps in this article.

Lines 17–40 are the added logic that I added to the original ffp distribution, which can be found here: fun_plug (original)

The reason why the SWAP partition is used is so that we will be able to perform disk checks on the RAID mount. If the utilities are running from the RAID mount, we would not be able to perform such operations on the RAID device.

fun_plug.tgz

DNS-321/323 are OABI-devices, sporting the Marvell 88F5181 or 88F5182 processors. Download the “OABI” versions here and here.

(For completeness), DNS-320/325/345 are EABI-devices, sporting the Marvell 88F6281/88F6282 processors. Download the “ARM” versions here and here if you have these devices.

Steps

  1. Install FFP’s fun_plug into your DNS-321 using the above files. Follow the steps in this well written article to install it: http://www.consumedconsumer.org/2010/10/hacking-dns-323-and-dns-321-nas.html
    Follow the steps to eventually enable SSH and disable TELNET only.
# fdisk -u=cylinders -lDisk /dev/md0: 248.0 GB, 248041439232 bytes
2 heads, 4 sectors/track, 60556992 cylinders
Units = cylinders of 8 * 512 = 4096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/md0 doesn't contain a valid partition tableDisk /dev/sda: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00066296
Device Boot Start End Blocks Id System
/dev/sda1 1 311 2490240 fd Linux raid autodetect
/dev/sda2 311 572 2097152 fd Linux raid autodetect
/dev/sda3 588 243201 1948788912 f W95 Ext'd (LBA)
/dev/sda5 589 243201 1948780864 fd Linux raid autodetect
Disk /dev/sdb: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0003bf4a
Device Boot Start End Blocks Id System
/dev/sdb1 1 66 530113+ 82 Linux swap / Solaris
/dev/sdb2 131 243201 1952467807+ 83 Linux
/dev/sdb4 67 130 514080 83 Linux
Partition table entries are not in disk order# fdisk -lDisk /dev/md0: 248.0 GB, 248041439232 bytes
2 heads, 4 sectors/track, 60556992 cylinders, total 484455936 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/md0 doesn't contain a valid partition tableDisk /dev/sda: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders, total 3907029168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00066296
Device Boot Start End Blocks Id System
/dev/sda1 256 4980735 2490240 fd Linux raid autodetect
/dev/sda2 4980736 9175039 2097152 fd Linux raid autodetect
/dev/sda3 9437184 3907015007 1948788912 f W95 Ext'd (LBA)
/dev/sda5 9453280 3907015007 1948780864 fd Linux raid autodetect
Disk /dev/sdb: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders, total 3907029168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0003bf4a
Device Boot Start End Blocks Id System
/dev/sdb1 63 1060289 530113+ 82 Linux swap / Solaris
/dev/sdb2 2088450 3907024064 1952467807+ 83 Linux
/dev/sdb4 1060290 2088449 514080 83 Linux
Partition table entries are not in disk order

7. The next step is to duplicate the configuration on the new drive except for partition 2. This is the tricky part.
Notice that the old drive’s sector starts at 63. This would not be used by default on newer drives. To do that, make sure you enable the dos compatibility flag when creating new partitions:

# fdisk -c=dos -u=cylinders /dev/sdaWARNING: DOS-compatible mode is deprecated. It's strongly recommended to
switch off the mode (with command 'c').
WARNING: cylinders as display units are deprecated. Use command 'u' to
change units to sectors.
Command (m for help): d
Partition number (1-5): 5
Command (m for help): d
Partition number (1-5): 3
Command (m for help): d
Partition number (1-4): 2
Command (m for help): d
Selected partition 1
Command (m for help): pDisk /dev/sda: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00066296
Device Boot Start End Blocks Id SystemCommand (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4, default 1): 1
First cylinder (1-243201, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-243201, default 243201): 66
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4, default 2): 4
First cylinder (67-243201, default 67):
Using default value 67
Last cylinder, +cylinders or +size{K,M,G} (67-243201, default 243201): 130
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4, default 2): 2
First cylinder (131-243201, default 131):
Using default value 131
Last cylinder, +cylinders or +size{K,M,G} (131-243201, default 243201):
Using default value 243201
Command (m for help): pDisk /dev/sda: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00066296
Device Boot Start End Blocks Id System
/dev/sda1 1 66 530113+ 83 Linux
/dev/sda2 131 243201 1952467807+ 83 Linux
/dev/sda4 67 130 514080 83 Linux
Partition table entries are not in disk orderCommand (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): 82
Changed system type of partition 1 to 82 (Linux swap / Solaris)
Command (m for help): pDisk /dev/sda: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00066296
Device Boot Start End Blocks Id System
/dev/sda1 1 66 530113+ 82 Linux swap / Solaris
/dev/sda2 131 243201 1952467807+ 83 Linux
/dev/sda4 67 130 514080 83 Linux
Partition table entries are not in disk orderCommand (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.

8. Format partition 1 as a swap partition and partition 4 as an ext3 file system. Note that your drive might not be at /dev/sda

# mkswap /dev/sda1
Setting up swapspace version 1, size = 530108 KiB
no label, UUID=########-####-####-####-############
# mke2fs -j /dev/sda4
mke2fs 1.41.14 (22-Dec-2010)
warning: Unable to get device geometry for /dev/sda4
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
128520 inodes, 514080 blocks
25704 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67633152
63 block groups
8192 blocks per group, 8192 fragments per group
2040 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 31 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

9. Activate the old drive as a degraded array

# mdadm --examine --scan > /etc/mdadm.conf
# mdadm --assemble --scan

10. View the status of the array

# cat /proc/mdstat
Personalities : [linear] [raid0] [raid1]
md0 : active raid1 sdb2[1]
242227968 blocks [2/1] [_U]
unused devices: <none>

11. Add the new drive to the array and recheck the status.

# mdadm /dev/md0 --add /dev/sda2
mdadm: added /dev/sda2
# cat /proc/mdstat
Personalities : [linear] [raid0] [raid1]
md0 : active raid1 sda2[0] sdb2[1]
242227968 blocks [2/2] [UU]
unused devices: <none>

12. Repeat steps 3–11 on the remaining hard drive.

13. At this point, you will have the upgraded both hard drives of higher capacity, albeit with the previously lower capacity on the RAID array.

14. In order to complete the next few steps, we have to unmount the RAID array. Find out where the mount is from the RAID (/dev/md0) and the processes that are using that mount.

# grep "/dev/md0" /etc/mtab | awk '{ print $2 }'
/mnt/HD_a2
# lsof | grep HD_a2
smbd 2364 nobody cwd DIR 9,0 4096 2 /mnt/HD_a2

15. Stop the services / processes that are using that mount, and unmount the drive.

# smb stop
# umount /mnt/HD_a2

16. Grow the array size to the maximum. Then, check the filesystem.

# mdadm --grow /dev/md0 --size=max
mdadm: component size of /dev/md0 has been set to 1952467712K
# e2fsck -f /dev/md0
e2fsck 1.41.14 (22-Dec-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
/lost+found not found. Create<y>? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/md0: ***** FILE SYSTEM WAS MODIFIED *****
/dev/md0: 17493/15147008 files (2.6% non-contiguous), 58106646/60556992 blocks

17. Resize the file system to the maximum. Then, check the filesystem.

# resize2fs /dev/md0
resize2fs 1.41.14 (22-Dec-2010)
Resizing the filesystem on /dev/md0 to 488116928 (4k) blocks.
The filesystem on /dev/md0 is now 488116928 (4k) blocks long.
root@arthur-server:~# e2fsck -f /dev/md0
e2fsck 1.41.14 (22-Dec-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/md0: 17493/122036224 files (2.6% non-contiguous), 64817418/488116928 blocks

18. Now, you can remount and restart the services

# mount -t ext2 -o rw,usrquota,grpquota /dev/md0 /mnt/HD_a2
# smb start

19. You will have to execute the following command to prevent the NAS firmware from prompting you to reformat your newly added hard drives in the future.

# hd_verify -w
hd verify v1.21.08122009
Force write verify to hd
WriteMagicNumToMTD 185557
WriteMagicNumToHD 185557

20. To clean things up, you may want to remove the ffp fun_plug folder from the SWAP folders and replace the script using the original fun_plug script. You can even remove FFP’s fun_plug completely by the following the steps here.

# **** Remove FFP tool folders and files in SWAP partitions
# rm -rf /mnt/HD_a4/ffp*
# rm -rf /mnt/HD_b4/ffp*

21. You are now a proud owner of a refreshed NAS. Check the size and admire your effort.

# cat /proc/mdstat
Personalities : [linear] [raid0] [raid1]
md0 : active raid1 sda2[0] sdb2[1]
1952467712 blocks [2/2] [UU]
unused devices: <none>

Conclusion

Do you find these steps useful? Let me know what other simpler ways to upgrade the diskspace on the DNS-321.

Love understanding how different pieces can make something beautiful. Still comprehending that building software is part engineering, art and social science.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store