When running on ppc64, sparc64, or x86-64, register ioctls with the ioctl32
translation layer. [Don Mulvey]
--- diff/drivers/md/dm-ioctl.c	2003-02-13 10:42:45.000000000 +0000
+++ source/drivers/md/dm-ioctl.c	2003-02-13 10:42:50.000000000 +0000
@@ -922,30 +922,30 @@
 	return dm_hash_rename(param->name, new_name);
 }
 
-
 /*-----------------------------------------------------------------
  * Implementation of open/close/ioctl on the special char
  * device.
  *---------------------------------------------------------------*/
-static ioctl_fn lookup_ioctl(unsigned int cmd)
-{
-	static struct {
-		int cmd;
-		ioctl_fn fn;
-	} _ioctls[] = {
-		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
-		{DM_REMOVE_ALL_CMD, remove_all},
-		{DM_DEV_CREATE_CMD, create},
-		{DM_DEV_REMOVE_CMD, remove},
-		{DM_DEV_RELOAD_CMD, reload},
-		{DM_DEV_RENAME_CMD, rename},
-		{DM_DEV_SUSPEND_CMD, suspend},
-		{DM_DEV_DEPS_CMD, dep},
-		{DM_DEV_STATUS_CMD, info},
-		{DM_TARGET_STATUS_CMD, get_status},
-		{DM_TARGET_WAIT_CMD, wait_device_event},
-	};
+static struct {
+	int cmd;
+	ioctl_fn fn;
 
+} _ioctls[] = {
+	{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
+	{DM_REMOVE_ALL_CMD, remove_all},
+	{DM_DEV_CREATE_CMD, create},
+	{DM_DEV_REMOVE_CMD, remove},
+	{DM_DEV_RELOAD_CMD, reload},
+	{DM_DEV_RENAME_CMD, rename},
+	{DM_DEV_SUSPEND_CMD, suspend},
+	{DM_DEV_DEPS_CMD, dep},
+	{DM_DEV_STATUS_CMD, info},
+	{DM_TARGET_STATUS_CMD, get_status},
+	{DM_TARGET_WAIT_CMD, wait_device_event},
+};
+
+static inline ioctl_fn lookup_ioctl(unsigned int cmd)
+{
 	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
 }
 
@@ -1102,6 +1102,41 @@
 };
 
 /*
+ * Register 32 bit ioctls on 64bit systems.
+ */
+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64)
+#include <linux/smp_lock.h>
+#include <asm/ioctl32.h>
+
+static inline void register_ioctl32_cmds(void)
+{
+	int i;
+
+	lock_kernel();
+	for (i = 0; i < ARRAY_SIZE(_ioctls); i++) {
+		register_ioctl32_conversion(_IOWR(DM_IOCTL, _ioctls[i].cmd,
+						  struct dm_ioctl), NULL);
+	}
+	unlock_kernel();
+}
+
+static inline void unregister_ioctl32_cmds(void)
+{
+	int i;
+
+	lock_kernel();
+	for (i = 0; i < ARRAY_SIZE(_ioctls); i++) {
+		unregister_ioctl32_conversion(_IOWR(DM_IOCTL, _ioctls[i].cmd,
+					            struct dm_ioctl));
+	}
+	unlock_kernel();
+}
+#else
+static inline void register_ioctl32_cmds(void) {}
+static inline void unregister_ioctl32_cmds(void) {}
+#endif
+
+/*
  * Create misc character device and link to DM_DIR/control.
  */
 int __init dm_interface_init(void)
@@ -1120,6 +1155,8 @@
 		return r;
 	}
 
+	register_ioctl32_cmds();
+
 	r = devfs_generate_path(_dm_misc.devfs_handle, rname + 3,
 				sizeof rname - 3);
 	if (r == -ENOSYS)
@@ -1146,6 +1183,7 @@
 	return 0;
 
       failed:
+	unregister_ioctl32_cmds();
 	misc_deregister(&_dm_misc);
 	dm_hash_exit();
 	return r;
@@ -1153,6 +1191,8 @@
 
 void dm_interface_exit(void)
 {
+	unregister_ioctl32_cmds();
+
 	if (misc_deregister(&_dm_misc) < 0)
 		DMERR("misc_deregister failed for control device");
 
