lkundrak / rpms / kernel

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