change semantics of ldisc ->compat_ioctl()
First of all, make it return int. Returning long when native method had never allowed that is ridiculous and inconvenient. More importantly, change the caller; if ldisc ->compat_ioctl() is NULL or returns -ENOIOCTLCMD, tty_compat_ioctl() will try to feed cmd and compat_ptr(arg) to ldisc's native ->ioctl(). That simplifies ->compat_ioctl() instances quite a bit - they only need to deal with ioctls that are neither generic tty ones (those would get shunted off to tty_ioctl()) nor simple compat pointer ones. Note that something like TCFLSH won't reach ->compat_ioctl(), even if ldisc ->ioctl() does handle it - it will be recognized earlier and passed to tty_ioctl() (and ultimately - ldisc ->ioctl()). For many ldiscs it means that NULL ->compat_ioctl() does the right thing. Those where it won't serve (see e.g. n_r3964.c) are also easily dealt with - we need to handle the numeric-argument ioctls (calling the native instance) and, if such would exist, the ioctls that need layout conversion, etc. All in-tree ldiscs dealt with. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -134,6 +134,10 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
||||
const unsigned char *buf, size_t nr);
|
||||
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#endif
|
||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
|
||||
static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
|
||||
struct poll_table_struct *wait);
|
||||
@@ -149,6 +153,9 @@ static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
|
||||
.read = r3964_read,
|
||||
.write = r3964_write,
|
||||
.ioctl = r3964_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = r3964_compat_ioctl,
|
||||
#endif
|
||||
.set_termios = r3964_set_termios,
|
||||
.poll = r3964_poll,
|
||||
.receive_buf = r3964_receive_buf,
|
||||
@@ -1210,6 +1217,21 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case R3964_ENABLE_SIGNALS:
|
||||
case R3964_SETPRIORITY:
|
||||
case R3964_USE_BCC:
|
||||
return r3964_ioctl(tty, file, cmd, arg);
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
{
|
||||
TRACE_L("set_termios");
|
||||
|
Reference in New Issue
Block a user