HFS+ Partitions

Apples HFS+ formatted partitions are handled badly by nearly all Linux distros and OpenELEC is no exception. The issue is the filesystem journal that is created/enabled by default on HFS+ partitions when Mac OS X creates the partition. Apple has never officially released the specifications for the journal so although it has been subject to extensive reverse engineering there is always an element of the unknown about Linux writing to it. To avoid issues the Linux kernel plays safe by automatically mounting HFS+ partitions read-only. It *can* mount a HFS+ journaled drive read-write, but you need to run "fsck.hfsplus -f /dev/device" before the partition is mounted, and in most distro's you need to specify 'mount -o force,rw' options to force the partition to mount read-write.

If you want to use HFS+ partitions with OpenELEC *easily* you need to remove the journal so the kernel can automatically mount the partition in read-write mode. Removing the journal can be done using Mac OS X's 'Disk Utility' application, or from within OpenELEC using a small "disable_journal" utility. The utility (originally found HERE) examines the partition you specify and disables the journal on it. The utility has been pre-compiled so you can simply download and use it against a drive attached to your OpenELEC equipped HTPC.

First download the "disable_journal" utility from the OpenELEC website

curl -O http://chewitt.openelec.tv/disable_journal

Now make the application executable

chmod +x disable_journal

Next we check which device we want to remove the journal from using the "mount" command. This gives output like below

root ~ # mount rootfs on / type rootfs (rw) none on /dev type devtmpfs (rw,relatime,size=1021820k,nr_inodes=255455,mode=755) none on /proc type proc (rw,relatime) none on /sys type sysfs (rw,relatime) /dev/sda1 on /flash type ext4 (ro,noatime,barrier=1,data=ordered) /dev/sda2 on /storage type ext4 (rw,noatime,barrier=1,data=ordered) /dev/loop0 on / type squashfs (ro,relatime) none on /dev/pts type devpts (rw,relatime,gid=5,mode=620) none on /dev/shm type tmpfs (rw,relatime) none on /var type ramfs (rw,relatime) fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime) /dev/sdb1 on /var/media/EFI type vfat (rw,nosuid,nodev,relatime,fmask=0022,dmask=0077,codepage=cp437,iocharset=ascii,shortname=mixed,showexec,utf8,errors=remount-ro) /dev/sdb2 on /var/media/HFSPLUS type hfsplus (ro,nosuid,nodev,relatime,umask=22,uid=0,gid=0,nls=utf8)

I can see above that the USB drive has two partitions; /dev/sdb1 is an EFI partition (created automatically by Disk Utility on any GPT partitioned volume over 2GB in size) and /dev/sdb2 is an "hfsplus" format partition. The latter is the one we need to remove the journal from.

Now I can run the disable_journal utility against /dev/sdb2 to remove the journal

./disable_journal /dev/sdb2

Removing the journal takes less than a second, then you can reboot. Once XBMC has restarted you can SSH in to OpenELEC and run the 'mount' command again. This time it should show the /dev/sdb2 partition as 'rw' meaning is has mounted read-write.

root ~ # mount rootfs on / type rootfs (rw) none on /dev type devtmpfs (rw,relatime,size=1021820k,nr_inodes=255455,mode=755) none on /proc type proc (rw,relatime) none on /sys type sysfs (rw,relatime) /dev/sda1 on /flash type ext4 (ro,noatime,barrier=1,data=ordered) /dev/sda2 on /storage type ext4 (rw,noatime,barrier=1,data=ordered) /dev/loop0 on / type squashfs (ro,relatime) none on /dev/pts type devpts (rw,relatime,gid=5,mode=620) none on /dev/shm type tmpfs (rw,relatime) none on /var type ramfs (rw,relatime) fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime) /dev/sdb1 on /var/media/EFI type vfat (rw,nosuid,nodev,relatime,fmask=0022,dmask=0077,codepage=cp437,iocharset=ascii,shortname=mixed,showexec,utf8,errors=remount-ro) /dev/sdb2 on /var/media/HFSPLUS type hfsplus (rw,nosuid,nodev,relatime,umask=22,uid=0,gid=0,nls=utf8)

Another approach to HFS+ partitions is to create a udev rule that forces an "fsck.hfsplus" on any HFS+ partition before it is mounted, allowing the Kernel to mount it read-write. You can add custom udev rules by renaming a folder in the writeable .config directory (accessible over SAMBA as \\OPENELEC\Configfiles, or via SSH) and then creating the rule file, e.g.

mv /storage/.config/udev.rules.d.sample /storage/.config/udev.rules.d

Then create a new file called 62-fsck-hfsplus.rules

touch /storage/.config/udev.rules.d/62-fsck-hfsplus.rules

Then edit the file using vi or nano

nano /storage/.config/udev.rules.d/62-fsck-hfsplus.rules

Then cut/paste the following content into the empty file


 * 1)      This file is part of OpenELEC - http://www.openelec.tv
 * 2)      Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv)
 * 3)  This Program is free software; you can redistribute it and/or modify
 * 4)  it under the terms of the GNU General Public License as published by
 * 5)  the Free Software Foundation; either version 2, or (at your option)
 * 6)  any later version.
 * 7)  This Program is distributed in the hope that it will be useful,
 * 8)  but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 9)  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * 10)  GNU General Public License for more details.
 * 11)  You should have received a copy of the GNU General Public License
 * 12)  along with OpenELEC; see the file COPYING.  If not, write to
 * 13)  the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA.
 * 14)  http://www.gnu.org/copyleft/gpl.html
 * 1)  You should have received a copy of the GNU General Public License
 * 2)  along with OpenELEC; see the file COPYING.  If not, write to
 * 3)  the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA.
 * 4)  http://www.gnu.org/copyleft/gpl.html

SUBSYSTEM!="block", GOTO="end" ACTION!="add", GOTO="end"

ACTION=="add", IMPORT{program}="/usr/bin/blkid -o udev -p %N" ACTION=="add", ENV{ID_FS_TYPE}=="hfsplus", ENV{mount_options}="rw,nosuid,nodev,uhelper=udisks", RUN+="/bin/fsck.hfsplus -r -y /dev/%k"

LABEL="end"
 * 1) exit

Save the file then reboot to have it take effect.