Last night I was pleasantly surprised to find that my new hard disk from Outpost.com/Fry’s had already arrived, despite ordering it on Friday and only paying for ground shipping. Note to the other folks from the Burgh, Outpost ships from Columbus, thus you get your stuff fast. Having received this nice shiny new 200GB hard disk, I needed a way to integrate into my system. I consider this disk to be a stop-gap solution until I can afford a RAID-5 setup.
Anyway, before I began this little adventure, I was running low on storage space. I keep my MythTV recordings in /mnt/store
and the 200G drive I picked up in February was now loaded down with lots of Simpsons, Family Guy, and various movies. The overall disk picture looked something like this:
patrick@dreams:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/hda6 33G 24G 6.9G 78% /
tmpfs 380M 0 380M 0% /dev/shm
/dev/hda1 90M 24M 62M 28% /boot
/dev/hdc1 190G 185G 1.9G 98% /mnt/store
/dev/hda5 9.3G 8.7G 601M 94% /home
/dev 33G 24G 6.9G 78% /.dev
none 5.0M 2.8M 2.3M 56% /dev
In addition, I have an NEC DVD dual layer burner on /dev/hdb
. My task at hand was to merge the new 200GB disk with the existing 200GB disk. I had a variety of possible tools for this, including just a bunch of symlinks to the old files, unionfs, and LVM. Symlinks might work okay, but there is a lot of manual work that needs to be done. On the bright side, if I lose a disk with that method, I only lose the recordings on that disk. UnionFS allows me to ignore the symlink problem and stack the two drives. However, one drive would be read only, so it would never get any more full. This really wasn’t desirable either. Really, I need some sort of RAID setup. Not so much for the redundancy, but for the consistent disk image across drives.
So normally what I’d be looking for is called RAID-0 or JBOD (Just a bunch of disks). The difference between the two is that RAID-0 stripes the data between the disks, meaning that different chunks of the data are on different disks. This gives increased I/O throughput provided that the disks are on different controllers. JBOD just concatenates the disks together as one big disk and when the first disk fills up, work begins on the second disk. The problem is that both of these would require me to blow away both drives to get going. I’m not about to try and find all those Simpsons expisodes again. Furthermore, if I ever wanted to add more disks to this setup, I’d still have to go this pain again. This was not desirable.
Enter the joy of LVM for Linux. LVM stands for Logical Volume Management, and it’s a method that you can be completely agnostic about the underlying disk setup for a mount point. The current version is LVM 2 and most distros ship with LVM2 support enabled (Ubuntu works just fine with LVM). The basic concept with LVM is that at the top level you have the concept of a volume group. This is a group of disks that you can create many mount points out of. For most users, you’ll be fine with just one volume group, but if you’re going to be doing a lot of moving of disks, you might want to have different volume groups to make things easier. Within a volume group you have a collection of physical volumes, which are essentially just block devices. Under Linux this means that you can either dedicate an entire disk or just a partition of a disk. In my case, I was dedicating two entire disks to LVM. This means that I get an extra 1K of space by not needing the partition table at the front of the disk. Woohoo. So, my first step was to initialize the new hard disk, now called /dev/hdb
as an LVM physical volume.
root@dreams:~# pvcreate /dev/hdb
With an initial physical volume created, it’s possible to move on and create a volume group. Like I stated earlier, for most home users, having a single volume group will be just fine. Especially if you’re just using it for MythTV. To get things started, I created a volume group called mythtv_store to indicate that I was using it for MythTV and told LVM that I would be using /dev/hdb
as the first physical volume in the group. You’ll also need to tell LVM that the volume group is accessible. This is what the second command does.
root@dreams:~# vgcreate mythtv_store /dev/hdb
rootodreams:~# vgchange -a y mythtv_store
The final thing that you’ll need if you want to access your disk is to create a logical volume on top of the volume group. It’s possible to use LVM to set up all sorts of fun stuff like striping between disks, but we’re not going to be doing that because we’re starting with just one disk. We want the setup to take up the entirety of the disk currently allocated to the volume group. To do that we first figure out how many physical extents we have in the volume group. A physical extent is a chunk of a physical disk that can be allocated to a logical volume. When we run the vgdisplay
command (more about that later), we’ll how man physical extents the drive has by looking at the line that says Total PE. For convenience and confusion sake, we’ll call our new logical volume mythtv.
root@dreams:~# vgdisplay mythtv_store | grep "Total PE"
Total PE 47695
root@dreams:~# lvcreate -l 47695 mythtv_store -n mythtv
If you’re interested in seeing what’s going on you can run pvdisplay to show the physical volumes, vgdisplay to show the volume groups you’ve just created, and lvdisplay
to show the logical volumes. Here’s the output from my system (somewhat faked as I’m writing this after creating the LVM setup):
root@dreams:~# pvdisplay
--- Physical volume ---
PV Name /dev/hdb
VG Name mythtv_store
PV Size 186.31 GB / not usable 0
Allocatable yes (but full)
PE Size (KByte) 4096
Total PE 47695
Free PE 0
Allocated PE 47695
PV UUID e5obta-U4u1-gdWB-DwGP-MTBo-Lpw5-1O7rVK
root@dreams:~# vgdisplay
--- Volume group ---
VG Name mythtv_store
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 5
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 2
Act PV 2
VG Size 186.27 GB
PE Size 4.00 MB
Total PE 47695
Alloc PE / Size 47695 / 186.27 GB
Free PE / Size 0 / 0
VG UUID 2uX3MD-1386-FqXx-LMEJ-ELOW-nB58-UNEoTl
root@dreams:~# lvdisplay
--- Logical volume ---
LV Name /dev/mythtv_store/mythtv
VG Name mythtv_store
LV UUID CbjYXs-gWnC-63X6-ED2D-x3BS-PbkC-td0OT4
LV Write Access read/write
LV Status available
# open 1
LV Size 186.27 GB
Current LE 47695
Segments 1
Allocation inherit
Read ahead sectors 0
Block device 254:0
The first line of the lvdisplay output is what we’re looking for. This is the device name that you’ll use to access the logical volume, in my case it is /dev/mythtv_store/mythtv
. In general it goes by the name of /dev/[VOLUME GROUP NAME]/[LOGICAL VOLUME NAME]
. From here we can see that we’ve got a 186.27 GB logical disk that we’ve just created. The next step is to format the thing and port our data over. I’ve been using JFS because it has speedy deletes for the large files that MythTV produces, however, you may want to consider using EXT3 or ReiserFS. The main reason is because you cannot shrink a JFS drive (or XFS for that matter). If you want a filesystem you can shrink, you must use EXT3 or ResierFS (at least at this time). Anyway, here’s how I formatted the drive, mounted it, and copied all my data from the old drive over (the old drive was mounted at /mnt/store
).
root@dreams:~# mkfs.jfs /dev/mythtv_store/mythtv
root@dreams:~# mkdir /mnt/tmp
root@dreams:~# mount /dev/mythtv_store/mythtv /mnt/tmp
root@dreams:~# cp -a /mnt/store /mnt/tmp
A quick look shows that all my files copied successfully. If you haven’t already, now would be a good time to shut down MythBackend, but lets hope you did that a long time ago. Now comes the part that you’ll feel queasy about, but it should work. We’re going to blow away the old disk, add it to the volume group, and then extend that logical volume and our JFS file system. The first thing that we need to do is blow away the partition table on /dev/hdc. This is necessary because LVM doesn’t like seeing a partition table there if it’s going to use the whole disk. Thanks to dd this is pretty straight forward.
root@dreams:~# dd if=/dev/zero of=/dev/hdc bs=1k count=1
root@dreams:~# pvcreate /dev/hdc
root@dreams:~# vgextend mythtv_store /dev/hdc
These steps have added /dev/hdc
to the volume group, but it hasn’t yet been added to the logical volume. To do that we’re going to need to know the total size of volume group. Once again, grep becomes our friend, and we use the following commands:
root@dreams:~# vgdisplay mythtv_store | grep "Total PE"
Total PE 96315
root@dreams:~# lvextend -l 96315 /dev/mythtv_store/mythtv
Now if we run lvdisplay we’ll see that the disk has been extened. However, looking at the output of df it’s clear that the disk space has not been increased. This is because we haven’t told JFS to extend the disk yet.
root@dreams:~# lvdisplay
--- Logical volume ---
LV Name /dev/mythtv_store/mythtv
VG Name mythtv_store
LV UUID CbjYXs-gWnC-63X6-ED2D-x3BS-PbkC-td0OT4
LV Write Access read/write
LV Status available
# open 1
LV Size 376.23 GB
Current LE 96315
Segments 2
Allocation inherit
Read ahead sectors 0
Block device 254:0
root@dreams:~# df
Filesystem Size Used Avail Use% Mounted on
/dev/hda6 33G 24G 6.9G 78% /
tmpfs 380M 0 380M 0% /dev/shm
/dev/hda1 90M 24M 62M 28% /boot
/dev/mapper/mythtv_store-mythtv
186G 185G 739M 99% /mnt/store
/dev/hda5 9.3G 8.7G 601M 94% /home
/dev 33G 24G 6.9G 78% /.dev
none 5.0M 2.8M 2.3M 56% /dev
The final step is to tell JFS to resize the mounted filesystem. In order to do this, JFS needs to execute a remount/resize command. This means that you need to have the filesystem mounted, then execute the following command:
root@dreams:~# mount -o remount,resize /mnt/store
If all goes well, it will take a few seconds to mount the disk, and then you’ll have a nice big disk to store all of your MythTV recordings on. Here’s the final output from the important commands on my system:
root@dreams:~# pvdisplay
--- Physical volume ---
PV Name /dev/hdb
VG Name mythtv_store
PV Size 186.31 GB / not usable 0
Allocatable yes (but full)
PE Size (KByte) 4096
Total PE 47695
Free PE 0
Allocated PE 47695
PV UUID e5obta-U4u1-gdWB-DwGP-MTBo-Lpw5-1O7rVK
--- Physical volume ---
PV Name /dev/hdc
VG Name mythtv_store
PV Size 189.92 GB / not usable 0
Allocatable yes (but full)
PE Size (KByte) 4096
Total PE 48620
Free PE 0
Allocated PE 48620
PV UUID 0poKpC-804L-kWvX-D97a-23Fc-L4UT-6HWObk
root@dreams:~# vgdisplay
--- Volume group ---
VG Name mythtv_store
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 5
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 2
Act PV 2
VG Size 376.23 GB
PE Size 4.00 MB
Total PE 96315
Alloc PE / Size 96315 / 376.23 GB
Free PE / Size 0 / 0
VG UUID 2uX3MD-1386-FqXx-LMEJ-ELOW-nB58-UNEoTl
root@dreams:~# lvdisplay
--- Logical volume ---
LV Name /dev/mythtv_store/mythtv
VG Name mythtv_store
LV UUID CbjYXs-gWnC-63X6-ED2D-x3BS-PbkC-td0OT4
LV Write Access read/write
LV Status available
# open 1
LV Size 376.23 GB
Current LE 96315
Segments 2
Allocation inherit
Read ahead sectors 0
Block device 254:0
root@dreams:~# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda6 33645952 24729060 7207756 78% /
tmpfs 388228 0 388228 0% /dev/shm
/dev/hda1 91599 24143 62569 28% /boot
/dev/mapper/mythtv_store-mythtv
394461228 179175688 215285540 46% /mnt/store
/dev/hda5 9732200 9116892 615308 94% /home
/dev 33645952 24729060 7207756 78% /.dev
none 5120 2856 2264 56% /dev