[PATCH] compat_ioctl: introduce generic_compat_ioctl helper

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Arnd Bergmann
Date: Saturday, October 20, 2007 - 8:50 am

Many drivers use only compatible ioctl numbers. In order to
avoid having to write a special compat_ioctl handler for each
of them or listing every ioctl number in fs/compat_ioctl.c,
let's introduce a generic handler that simply calls the
driver specific f_op->unlocked_ioctl() or f_op->ioctl() handler.

Signed-off-by: Arnd Bergman <arnd@arndb.de>
---
On Saturday 13 October 2007, Al Viro wrote:

Is this what you had in mind? I've been meaning to do something like
it for some time, but had forgotten about it.

I guess we can kill a significant amount of COMPATIBLE_IOCTL
lines in fs/compat_ioctl.c with this.

Index: linux-2.6/fs/compat_ioctl.c
===================================================================
--- linux-2.6.orig/fs/compat_ioctl.c
+++ linux-2.6/fs/compat_ioctl.c
@@ -1877,6 +1877,30 @@ lp_timeout_trans(unsigned int fd, unsign
 	return sys_ioctl(fd, cmd, (unsigned long)tn);
 }
 
+/*
+ * Helper function for device drivers that only have COMPATIBLE_IOCTL
+ * numbers. This can be used as f_op->compat_ioctl without any #ifdef
+ * and will simply call the native ioctl handler with the argument
+ * pointer.
+ * Don't use for drivers that interpret arg as an unsigned long instead
+ * of a pointer.
+ */
+long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOTTY;
+	arg = (unsigned long)compat_ptr(arg);
+
+	if (file->f_op->unlocked_ioctl)
+		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+	else if (file->f_op->ioctl) {
+		lock_kernel();
+		ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(generic_compat_ioctl);
 
 typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
 					unsigned long, struct file *);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1807,6 +1807,12 @@ extern void do_generic_mapping_read(stru
 extern int generic_segment_checks(const struct iovec *iov,
 		unsigned long *nr_segs, size_t *count, int access_flags);
 
+#ifdef CONFIG_COMPAT
+extern long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+#define generic_compat_ioctl (long (*)(struct file *, unsigned int, unsigned long))NULL
+#endif
+
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
 		struct pipe_inode_info *, size_t, unsigned int);
-
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH] hiddev: Add 32bit ioctl compatibilty, Philip Langdale, (Fri Oct 12, 4:51 pm)
Re: [PATCH] hiddev: Add 32bit ioctl compatibilty, Al Viro, (Fri Oct 12, 5:02 pm)
Re: [PATCH] hiddev: Add 32bit ioctl compatibilty, Philip Langdale, (Sat Oct 13, 10:42 am)
[PATCH] compat_ioctl: introduce generic_compat_ioctl helper, Arnd Bergmann, (Sat Oct 20, 8:50 am)
[PATCH] hiddev: simplify 32bit ioctl compatibilty, Arnd Bergmann, (Sat Oct 20, 9:03 am)
Re: [PATCH] compat_ioctl: introduce generic_compat_ioctl h ..., Christoph Hellwig, (Sat Oct 20, 9:11 am)