Skip to contentSkip to conversation

->compat_ioctl for 390 tape_char

PATCH In review Christoph Hellwig 2 participants 5 messages Nov 4, 2005 – Nov 7, 2005 s390

lore
Share & tools
lore
#0 lore raw

PATCH 4/4 ->compat_ioctl for 390 tape_char

The only own ioctl, TAPE390_DISPLAY, is compat_clean, everything else is routed through common translation code.

drivers/s390/char/tape_char.c +18 -0
Index: linux-2.6/drivers/s390/char/tape_char.c
===================================================================
@@ -37,6 +37,8 @@
 static int tapechar_release(struct inode *,struct file *);
 static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
 			  unsigned long);
+static long tapechar_compat_ioctl(struct file *, unsigned int,
+			  unsigned long);
 
 static struct file_operations tape_fops =
 {
@@ -44,6 +46,7 @@
 	.read = tapechar_read,
 	.write = tapechar_write,
 	.ioctl = tapechar_ioctl,
+	.compat_ioctl = tapechar_compat_ioctl,
 	.open = tapechar_open,
 	.release = tapechar_release,
 };
@@ -463,6 +466,21 @@
 	return device->discipline->ioctl_fn(device, no, data);
 }
 
+static long
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+	struct tape_device *device = filp->private_data;
+	int rval = -ENOIOCTLCMD;
+
+	if (device->discipline->ioctl_fn) {
+		lock_kernel();
+		rval = device->discipline->ioctl_fn(device, no, data);
+		unlock_kernel();
+	}
+
+	return rval;
+}
+
 /*
  * Initialize character device frontend.
  */
arch/s390/kernel/compat_ioctl.c +0 -3
Index: linux-2.6/arch/s390/kernel/compat_ioctl.c
===================================================================
@@ -42,9 +42,6 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "../../../fs/compat_ioctl.c"
-
-/* s390 only ioctls */
-COMPATIBLE_IOCTL(TAPE390_DISPLAY)
 };
 
 int ioctl_table_size = ARRAY_SIZE(ioctl_start);
#1 lore raw
Quoted 8 lines · Christoph Hellwig

The only own ioctl, TAPE390_DISPLAY, is compat_clean, everything else is routed through common translation code.

drivers/s390/char/tape_char.c +3 -0
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+       struct tape_device *device = filp->private_data;

drivers/s390/char/tape_char.c line 482

Quoted 10 lines
drivers/s390/char/tape_char.c +10 -0
+       int rval = -ENOIOCTLCMD;
+
+       if (device->discipline->ioctl_fn) {
+               lock_kernel();
+               rval = device->discipline->ioctl_fn(device, no, data);
+               unlock_kernel();
+       }
+
+       return rval;
+}

Hmm, isn't ->compat_ioctl called before the translation lookup? If so, this code would return -EINVAL from tape_34xx_ioctl and result in never entering the conversion for MTIO* at all.

The same problem seems to be in the other patches of this series, but I could also be mistaken.

BTW, I now have a set of 25 patches that moves all handlers from fs/compat_ioctl.c over to the respective drivers and subsystems, but I'm not sure how to best test that.
I intend to at least give it a test run on my Opteron for the whatever ioctls I normally use, but the rest is just guesswork. Christoph, can you review those patches?

	Arnd <><
#2 lore raw
Quoted 1 line · Arnd Bergmann

Hmm, isn't ->compat_ioctl called before the translation lookup?

Yes.

Quoted 3 lines

If so,
this code would return -EINVAL from tape_34xx_ioctl and result in never entering the conversion for MTIO* at all.

we return -ENOIOCTLCMD if we didn't have a valid compat ioctl, and in that case the vfs code will try to find it in the core translation table.

Quoted 6 lines

BTW, I now have a set of 25 patches that moves all handlers from fs/compat_ioctl.c over to the respective drivers and subsystems, but I'm not sure how to best test that.
I intend to at least give it a test run on my Opteron for the whatever ioctls I normally use, but the rest is just guesswork. Christoph, can you review those patches?

I'm not sure moving everything from fs/compat_ioctl.c is a good idea. Everything that is just in a single driver or subsystem that has common ioctl code - sure. else it doesn't make a lot of sense.

#3 lore raw
Quoted 3 lines · Christoph Hellwig

we return -ENOIOCTLCMD if we didn't have a valid compat ioctl, and in that case the vfs code will try to find it in the core translation table.

No, the function you wrote returns -ENOIOCTLCMD only if device->discipline->ioctl_fn is NULL, otherwise it returns the code it gets from that function, which is -EINVAL.

Quoted 3 lines

I'm not sure moving everything from fs/compat_ioctl.c is a good idea. Everything that is just in a single driver or subsystem that has common ioctl code - sure.  else it doesn't make a lot of sense.

It turns out that almost everything is a single driver, the exceptions are:

- tty ioctls: I move the conversion into drivers/char/tty_io.c with a relatively big switch() statement. All drivers implementing these use tty_operations.
- block ioctl: similar for drivers/block/ioctl.c
- net ioctl: similar for net/compat.c. I also add compat_ioctl methods for proto_ops.
- cdrom, tape, v4l: I create a new file that contains a compat_ioctl file operation that can be used in each driver, either by pointing directly to it or by calling it from their own compat_ioctl handler. The handlers end up calling f_op->ioctl() internally.
- file systems: many file systems implement EXT2_IOC_GETFLAGS etc. those are trivial to handle, so I duplicate the code for each of those file systems.

	Arnd <><
#4 lore raw
Quoted 8 lines · Arnd Bergmann
Quoted 3 lines · Christoph Hellwig

we return -ENOIOCTLCMD if we didn't have a valid compat ioctl, and in that case the vfs code will try to find it in the core translation table.

No, the function you wrote returns -ENOIOCTLCMD only if device->discipline->ioctl_fn is NULL, otherwise it returns the code it gets from that function, which is -EINVAL.

indeed. updated patch below that handles that case. I couldn't find a problem like that in the other patches.

drivers/s390/char/tape_char.c +20 -0
Index: linux-2.6/drivers/s390/char/tape_char.c
===================================================================
@@ -37,6 +37,8 @@
 static int tapechar_release(struct inode *,struct file *);
 static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
 			  unsigned long);
+static long tapechar_compat_ioctl(struct file *, unsigned int,
+			  unsigned long);
 
 static struct file_operations tape_fops =
 {
@@ -44,6 +46,7 @@
 	.read = tapechar_read,
 	.write = tapechar_write,
 	.ioctl = tapechar_ioctl,
+	.compat_ioctl = tapechar_compat_ioctl,
 	.open = tapechar_open,
 	.release = tapechar_release,
 };
@@ -463,6 +466,23 @@
 	return device->discipline->ioctl_fn(device, no, data);
 }
 
+static long
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+	struct tape_device *device = filp->private_data;
+	int rval = -ENOIOCTLCMD;
+
+	if (device->discipline->ioctl_fn) {
+		lock_kernel();
+		rval = device->discipline->ioctl_fn(device, no, data);
+		unlock_kernel();
+		if (rval == -EINVAL)
+			rval = -ENOIOCTLCMD;
+	}
+
+	return rval;
+}
+
 /*
  * Initialize character device frontend.
  */
arch/s390/kernel/compat_ioctl.c +0 -3
Index: linux-2.6/arch/s390/kernel/compat_ioctl.c
===================================================================
@@ -42,9 +42,6 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "../../../fs/compat_ioctl.c"
-
-/* s390 only ioctls */
-COMPATIBLE_IOCTL(TAPE390_DISPLAY)
 };
 
 int ioctl_table_size = ARRAY_SIZE(ioctl_start);