4efc0c7
Making an hfsplus partition bootable requires the ability to "bless" a
4efc0c7
file by putting its inode number in the volume header. Doing this from
4efc0c7
userspace on a mounted filesystem is impractical since the kernel will
4efc0c7
write back the original values on unmount. Add an ioctl to allow userspace
4efc0c7
to update the volume header information based on the target file.
4efc0c7
4efc0c7
Signed-off-by: Matthew Garrett <mjg@redhat.com>
4efc0c7
---
4efc0c7
Kept the ioctl in the hfs code, but moved it to a different range to reduce
4efc0c7
reduce the chances of someone stepping on it with another filesystem.
4efc0c7
 Documentation/ioctl/ioctl-number.txt |    1 +
4efc0c7
 fs/hfsplus/hfsplus_fs.h              |    5 +++++
4efc0c7
 fs/hfsplus/ioctl.c                   |   34 ++++++++++++++++++++++++++++++++++
4efc0c7
 3 files changed, 40 insertions(+), 0 deletions(-)
4efc0c7
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
4efc0c7
index 4840334..37a4248 100644
4efc0c7
--- a/Documentation/ioctl/ioctl-number.txt
4efc0c7
+++ b/Documentation/ioctl/ioctl-number.txt
4efc0c7
@@ -218,6 +218,7 @@ Code  Seq#(hex)	Include File		Comments
4efc0c7
 'h'	00-7F				conflict! Charon filesystem
4efc0c7
 					<mailto:zapman@interlan.net>
4efc0c7
 'h'	00-1F	linux/hpet.h		conflict!
4efc0c7
+'h'	80-8F	fs/hfsplus/ioctl.c
4efc0c7
 'i'	00-3F	linux/i2o-dev.h		conflict!
4efc0c7
 'i'	0B-1F	linux/ipmi.h		conflict!
4efc0c7
 'i'	80-8F	linux/i8k.h
4efc0c7
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
4efc0c7
index 21a5b7f..4e75ac6 100644
4efc0c7
--- a/fs/hfsplus/hfsplus_fs.h
4efc0c7
+++ b/fs/hfsplus/hfsplus_fs.h
4efc0c7
@@ -317,6 +317,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
4efc0c7
 
4efc0c7
 
4efc0c7
 /*
4efc0c7
+ * hfs+-specific ioctl for making the filesystem bootable
4efc0c7
+ */
4efc0c7
+#define HFSPLUS_IOC_BLESS _IO('h', 0x80)
4efc0c7
+
4efc0c7
+/*
4efc0c7
  * Functions in any *.c used in other files
4efc0c7
  */
4efc0c7
 
4efc0c7
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
4efc0c7
index f66c765..c640ba5 100644
4efc0c7
--- a/fs/hfsplus/ioctl.c
4efc0c7
+++ b/fs/hfsplus/ioctl.c
4efc0c7
@@ -20,6 +20,38 @@
4efc0c7
 #include <asm/uaccess.h>
4efc0c7
 #include "hfsplus_fs.h"
4efc0c7
 
4efc0c7
+/*
4efc0c7
+ * "Blessing" an HFS+ filesystem writes metadata to the superblock informing
4efc0c7
+ * the platform firmware which file to boot from
4efc0c7
+ */
4efc0c7
+static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
4efc0c7
+{
4efc0c7
+	struct dentry *dentry = file->f_path.dentry;
4efc0c7
+	struct inode *inode = dentry->d_inode;
4efc0c7
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
4efc0c7
+	struct hfsplus_vh *vh = sbi->s_vhdr;
4efc0c7
+	struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
4efc0c7
+
4efc0c7
+	if (!capable(CAP_SYS_ADMIN))
4efc0c7
+		return -EPERM;
4efc0c7
+
4efc0c7
+	mutex_lock(&sbi->vh_mutex);
4efc0c7
+
4efc0c7
+	/* Directory containing the bootable system */
4efc0c7
+	vh->finder_info[0] = bvh->finder_info[0] =
4efc0c7
+		cpu_to_be32(parent_ino(dentry));
4efc0c7
+
4efc0c7
+	/* Bootloader */
4efc0c7
+	vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino);
4efc0c7
+
4efc0c7
+	/* Per spec, the OS X system folder - same as finder_info[0] here */
4efc0c7
+	vh->finder_info[5] = bvh->finder_info[5] =
4efc0c7
+		cpu_to_be32(parent_ino(dentry));
4efc0c7
+
4efc0c7
+	mutex_unlock(&sbi->vh_mutex);
4efc0c7
+	return 0;
4efc0c7
+}
4efc0c7
+
4efc0c7
 static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
4efc0c7
 {
4efc0c7
 	struct inode *inode = file->f_path.dentry->d_inode;
4efc0c7
@@ -108,6 +140,8 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
4efc0c7
 		return hfsplus_ioctl_getflags(file, argp);
4efc0c7
 	case HFSPLUS_IOC_EXT2_SETFLAGS:
4efc0c7
 		return hfsplus_ioctl_setflags(file, argp);
4efc0c7
+	case HFSPLUS_IOC_BLESS:
4efc0c7
+		return hfsplus_ioctl_bless(file, argp);
4efc0c7
 	default:
4efc0c7
 		return -ENOTTY;
4efc0c7
 	}
4efc0c7
-- 
4efc0c7
1.7.7.6
4efc0c7
4efc0c7