MythTV Update

I just updated my MythTV box from Karmic to Lucid. There were a few things that needed updating, and it became a little like pulling on a piece of thread - one thing lead to another until it became quite the saga. I thought I'd document things so that others don't have quite the same pain.

There were two big things that changed: I updated my data store filesystem from zfs to btrfs. I updated my lirc configuration to use the new devinput driver.

zfs to btrfs

My machine has one 64Gb SSD with the root filesystem (ext4), and two 1Tb HDDs. Under Karmic I was using zfs-fuse on the HDDs in a raid1 (mirrored) configuration. They were one big pool, but I then had a number of filesystems on that pool that I could mount in different places - e.g. /var/lib, /home, /srv, etc. I had to do this because zfs-fuse gets harder to use the earlier you try to load it. By just using it for sections of the directory structure that load relatively late it was possible to use it for large data stores, but still have it be relatively easy to use.

Under lucid, zfs-fuse is now in the ubuntu repository, rather than an extra ppa. This made me think that the setup was likely to keep working... unfortunately that wasn't the case. After the dist-upgrade I ended up with a problem whereby certain of my zfs filesystems didn't show up in a zfs list and didn't mount with a mount -a. Given that I knew the names of some of the filesystems, I could mount them, but I didn't remember the names of some of the snapshots, and I couldn't figure out how to list them... so I decided to move to btrfs.

I've been thinking about switching to btrfs for a while. Having something natively supported in the kernel is likely to be faster, and I suspect the support on linux will be better. The question is then how to move from a raid1 zfs setup to a raid1 btrfs setup. Given that they're both raid1, you'd think it would be easy. Unfortunately, btrfs cannot currently add a second disk in a raid1 configuration after the filesystem creation - you have to have two disks at creation time. So I used a loopback device backed by a sparse file as my second device...

btrfs raid1 array creation

The two drives we're talking about are /dev/sdb and /dev/sdc. I initially removed /dev/sdb from the zfs pool leaving the pool in degraded mode. Then I did the following to turn /dev/sdb into the start of the btrfs pool: (I was basing this on the btrfs information here: http://btrfs.wiki.kernel.org/index.php/Using_Btrfs_with_Multiple_Devices)

# get the size of the disk you want to move from (in 1k blocks)
cat /proc/partitions # look for /dev/sdb1
# create the large, sparse data file
dd if=/dev/zero of=large.img bs=1k count=1 seek=<size of disk in blocks>
# mount it on a loopback device
losetup /dev/loop0 large.img
# make the raid1 btrfs filesystem
mkfs.btrfs -m raid1 -d raid1 /dev/sdb1 /dev/loop0
# mount the filesystem once
mount -t btrfs /dev/sdb1 btrfs-mnt
# if that didn't work, try mounting it using /dev/loop0
# then unmount it again
umount btrfs-mnt
# undo the loopback setup
losetup -d /dev/loop0
# remove the sparse file
rm large.img
# mount the drive again in degraded mode
mount -t btrfs -odegraded /dev/sdb1 btrfs-mnt

# make btrfs subvolumes and copy stuff onto the drive
cp -rp stuff btrfs-mnt/

# unmount zfs
# use gparted to re-partition /dev/sdc into one big partition

then I tried the following, which didn't work:

btrfs-vol -a /dev/sdc1 btrfs-mnt
btrfs-vol -r missing btrfs-mnt
# remount btrfs volumes in the right places and not in degraded mode

This began a saga trying to make btrfs to work as a raid1 system. Luckily, all my data was there and accessible on /dev/sdb1 in degraded mode (although I had a few heart-stopping moments - this procedure is for the brave at the moment).

The solution ended up being to update to a newer version of btrfs :). Lucid runs kernel 2.6.32 which was just as btrfs became at all usable, and it still appears to have some issues. I wanted to update to at least 2.6.34 and preferably newer.

There are two parts to btrfs - the kernel and the tools. I updated the tools by downloading the latest source package (for Natty) for btrfs-tools from https://launchpad.net/ubuntu/+source/btrfs-tools and building it locally on Lucid. It built just fine.

I also updated to a backported natty kernel. I added the ubuntu kernel ppa from https://launchpad.net/~kernel-ppa/+archive/ppa and then installed the linux-image-generic-lts-backport-natty package and associated headers.

Once these updates were done I was able, with only a little bit of playing, to get /dev/sdc1 added to the btrfs pool using the new style btrfs commands.

Remember to re-balance after adding the new drive to copy all the data across both.

There is still a weird issue removing the 'missing' devices - I don't get an error, but the 'missing' devices are still flagged as 'missing':

root@willvo:~# btrfs filesystem show
failed to read /dev/sr0
Label: none  uuid: f929c413-01c8-443f-b4f2-86f36702f519
    Total devices 3 FS bytes used 578.39GB
    devid    1 size 931.51GB used 604.00GB path /dev/sdb1
    devid    2 size 931.51GB used 604.00GB path /dev/sdc1
    *** Some devices missing

Btrfs Btrfs v0.19
root@willvo:~# btrfs device delete missing /data
root@willvo:~# btrfs filesystem show
failed to read /dev/sr0
Label: none  uuid: f929c413-01c8-443f-b4f2-86f36702f519
    Total devices 3 FS bytes used 578.39GB
    devid    1 size 931.51GB used 604.00GB path /dev/sdb1
    devid    2 size 931.51GB used 604.00GB path /dev/sdc1
    *** Some devices missing

Btrfs Btrfs v0.19

But it seems to be working anyway, so we'll leave that for the moment and move to the other issue. The new kernel doesn't just change the way btrfs works - it also changes the IR drivers. That means an update to the lirc configuration.

Updating lirc

The backstory for this update is covered here, http://wilsonet.com/?page_id=95, but the short story is that the drivers have changed and you need to switch to using devinput.

I have an Antec Veris system with a imon IR receiver and an Antec_Veris_RM200 remote. I don't actually use that remote though - it has too many keys and that just invites people to either a) complain it is too complex, b) press the keys and complain they don't do anything or c) both of the previous. Rather I use a LogiTech Harmony 525 programmable remote.

When I first set up my system, Logitech's auto-setup system didn't know about the RM200 remote - I had to use their learning system to program the Harmony. This worked ok, but I was never quite satisfied with it. When I set things up this time I figured out that with the new drivers I can switch the receiver into 'rc-6' mode which allows it to understand Microsoft Media Centre remotes. This is great as Logitech certainly does know about them. I followed this guide to set up my remote to act as a media-centre remote. I found there were a few buttons that my system couldn't interpret, so I had to switch some around - that wasn't a problem as there are plenty of options to choose from and most work just fine (but see below). One other caveat is that I couldn't get any of the 'Microsoft Keyboard' buttons to work reliably, just the remote buttons.

The setup on the linux side is a little more tricky. I found this thread useful, but did not follow it exactly.

Firstly, you need the ir-keytable tool, which I had to build from source.

git clone http://linuxtv.org/git/v4l-utils.git
cd v4l-utils
make
cd utils/keytable
cp ir-keytable /usr/local/bin/
cp rc_keymaps /etc/

Then when you run it, it will tell you the device to use for your remote:

# ir-keytable
Found /sys/class/rc/rc0/ (/dev/input/event4) with:
    Driver imon, table rc-imon-pad
    Supported protocols: RC-6   Enabled protocols: 

But we don't want to use /dev/input/event4 directly as that may change when you connect or disconnect another input device. Rather, use ls -l /dev/input/by-id/ to see which device there points to the right device. In my case I want to use /dev/input/by-id/usb-15c2_0038-event-mouse because that points to /dev/input/event4, but will keep pointing to the right device even if it changes.

Now, switch your lirc configuration to using devinput:

sudo dpkg-reconfigure lirc

and then select

Linux input layer (/dev/input/eventX)

I selected None for the IR Transmitter, and then /dev/input/by-id/usb-15c2_0038-event-mouse for the device.

Next, we need to tell HAL not to grab the device. Following the advice here I looked in /usr/share/hal/fdi/preprobe/20thirdparty/ and noticed there was already a lirc.fdi file. I edited it to add the following:

 <match key="info.product" contains_ncase="iMON Remote">
    <merge key="info.ignore" type="bool">true</merge>
 </match>

Next, we need to switch the remote into rc-6 mode and update its keymap. This can be done using the ir-keytable command we built earlier. For example:

ir-keytable -c -w /etc/rc_keymaps/imon_mce

should do both. I had some problems with that however and played around with a few things. I'm not exactly sure which of these fixed the problems.

And even that isn't enough to make the whole system work. I still found that lirc wasn't getting some keys. So I copied /usr/share/lirc/remotes/devinput/lircd.conf.devinput to /etc/lirc/lircd.conf.devinput and edited it as follows (basically adding 0x200 to some of the event codes - not sure why they need this):

--- /usr/share/lirc/remotes/devinput/lircd.conf.devinput    2009-02-08 05:00:41.000000000 +1100
+++ /etc/lirc/lircd.conf.devinput   2010-10-30 00:45:19.529971238 +1100
@@ -11,20 +11,21 @@
   pre_data_bits   16
   pre_data       0x8001
   gap          132799
+#  gap          39995
   toggle_bit_mask 0x0

       begin codes
-          KEY_0                    0x000B
           KEY_102ND                0x0056
-          KEY_1                    0x0002
-          KEY_2                    0x0003
-          KEY_3                    0x0004
-          KEY_4                    0x0005
-          KEY_5                    0x0006
-          KEY_6                    0x0007
-          KEY_7                    0x0008
-          KEY_8                    0x0009
-          KEY_9                    0x000A
+          KEY_0                    0x0200
+          KEY_1                    0x0201
+          KEY_2                    0x0202
+          KEY_3                    0x0203
+          KEY_4                    0x0204
+          KEY_5                    0x0205
+          KEY_6                    0x0206
+          KEY_7                    0x0207
+          KEY_8                    0x0208
+          KEY_9                    0x0209
           KEY_A                    0x001E
           KEY_AB                   0x0196
           KEY_AGAIN                0x0081
@@ -191,7 +192,8 @@
           KEY_KP7                  0x0047
           KEY_KP8                  0x0048
           KEY_KP9                  0x0049
-          KEY_KPASTERISK           0x0037
+#          KEY_KPASTERISK           0x0037
+          KEY_KPASTERISK           0x020A
           KEY_KPCOMMA              0x0079
           KEY_KPDOT                0x0053
           KEY_KPENTER              0x0060
@@ -200,7 +202,8 @@
           KEY_KPLEFTPAREN          0x00B3
           KEY_KPMINUS              0x004A
           KEY_KPPLUS               0x004E
-          KEY_KPPLUSMINUS          0x0076
+#          KEY_KPPLUSMINUS          0x0076
+          KEY_KPPLUSMINUS          0x020B
           KEY_KPRIGHTPAREN         0x00B4
           KEY_KPSLASH              0x0062
           KEY_L                    0x0026

Having made those changes you still need to tell lirc to use them, so edit /etc/lirc/lircd.conf to include /etc/lirc/lircd.conf.devinput instead of the default (for devinput) /usr/share/lirc/remotes/devinput/lircd.conf.devinput.

At this point your remote should work.

Lirc and gdm

There is one other tweak I made. I still use gdm on my system rather than booting directly into mythtv. I have the mythtv user set up to auto-login after 10 seconds. Before Karmic, this used to wait 10 seconds and then start mythtv every time. On Karmic and now Lucid, this only auto-login only works on the initial boot. If you exit myth then it will not re-auto-login. As I have no easily accessible keyboard, this is somewhat annoying.

I just added some extra irexec commands that run on KEY_UP, KEY_DOWN and KEY_OK events. These check if the 'mythtv' user is logged in, and if not then they use xdotool to generate approprate keyboard events. This allows you to use the remote to select the myth user. On Lucid you can then add that user to the nopasswdlogin group so that they don't need a password to login on the console (you want to make sure your remote access is still secure!), and people can now restart the myth frontend effectively with just the remote.

blog comments powered by Disqus