hfsplus: add an ioctl to bless files
authorMatthew Garrett <mjg@redhat.com>
Mon, 6 Feb 2012 20:14:40 +0000 (15:14 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 21 Mar 2012 01:29:53 +0000 (21:29 -0400)
Making an hfsplus partition bootable requires the ability to "bless" a
file by putting its inode number in the volume header. Doing this from
userspace on a mounted filesystem is impractical since the kernel will
write back the original values on unmount. Add an ioctl to allow userspace
to update the volume header information based on the target file.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Documentation/ioctl/ioctl-number.txt
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/ioctl.c

index 4840334ea97b30705df13a2c642e976a83621800..37a424868eea7c38d4d071c23baa9ae35575f716 100644 (file)
@@ -218,6 +218,7 @@ Code  Seq#(hex)     Include File            Comments
 'h'    00-7F                           conflict! Charon filesystem
                                        <mailto:zapman@interlan.net>
 'h'    00-1F   linux/hpet.h            conflict!
+'h'    80-8F   fs/hfsplus/ioctl.c
 'i'    00-3F   linux/i2o-dev.h         conflict!
 'i'    0B-1F   linux/ipmi.h            conflict!
 'i'    80-8F   linux/i8k.h
index 21a5b7fc6db42310576ee3cb00bbff46f6d5a534..4e75ac646fea3ac10643a657ae5276c7ee9d19c8 100644 (file)
@@ -316,6 +316,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
 #define HFSPLUS_IOC_EXT2_SETFLAGS      FS_IOC_SETFLAGS
 
 
+/*
+ * hfs+-specific ioctl for making the filesystem bootable
+ */
+#define HFSPLUS_IOC_BLESS _IO('h', 0x80)
+
 /*
  * Functions in any *.c used in other files
  */
index f66c7655b3f7f0d74234f2f70ab7cb4302bb078c..c640ba57074b8ba58c46c148815c714f20b48939 100644 (file)
 #include <asm/uaccess.h>
 #include "hfsplus_fs.h"
 
+/*
+ * "Blessing" an HFS+ filesystem writes metadata to the superblock informing
+ * the platform firmware which file to boot from
+ */
+static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
+{
+       struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = dentry->d_inode;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+       struct hfsplus_vh *vh = sbi->s_vhdr;
+       struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       mutex_lock(&sbi->vh_mutex);
+
+       /* Directory containing the bootable system */
+       vh->finder_info[0] = bvh->finder_info[0] =
+               cpu_to_be32(parent_ino(dentry));
+
+       /* Bootloader */
+       vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino);
+
+       /* Per spec, the OS X system folder - same as finder_info[0] here */
+       vh->finder_info[5] = bvh->finder_info[5] =
+               cpu_to_be32(parent_ino(dentry));
+
+       mutex_unlock(&sbi->vh_mutex);
+       return 0;
+}
+
 static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
@@ -108,6 +140,8 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return hfsplus_ioctl_getflags(file, argp);
        case HFSPLUS_IOC_EXT2_SETFLAGS:
                return hfsplus_ioctl_setflags(file, argp);
+       case HFSPLUS_IOC_BLESS:
+               return hfsplus_ioctl_bless(file, argp);
        default:
                return -ENOTTY;
        }