From ec2359d566932f8c650e39b55583fde77eff273d Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Fri, 27 Sep 2013 11:56:29 +0000 Subject: [PATCH] TTY: allow selecting on translated minors Due to the existence of /dev/console and /dev/log, and the new "console=" setting, it is now possible that a single non-PTY object (e.g. serial) is accessible through two different minor numbers. This poses a problem when sending late select replies (CDEV_SEL2_REPLY), because the object's minor number can not be used to identify the device. Since selecting on such objects through translated minor numbers is actually required, we now save the minor number used to initiate the select query in order to send a late reply. The solution is suboptimal, as it is not possible to use two different minors to select on the same object at once. In the future, there should be at least one select record for each minor that can be used with each object. Change-Id: I4d39681d2ffd68b4047daf933d45b7bafe3c885e --- drivers/tty/tty.c | 20 +++++++++++++------- drivers/tty/tty.h | 3 ++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c index bdfdd142e..655becf06 100644 --- a/drivers/tty/tty.c +++ b/drivers/tty/tty.c @@ -873,8 +873,8 @@ int select_retry(struct tty *tp) int ops; if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) { - chardriver_reply_select(tp->tty_select_proc, tp->tty_minor, - ops); + chardriver_reply_select(tp->tty_select_proc, + tp->tty_select_minor, ops); tp->tty_select_ops &= ~ops; } return OK; @@ -891,10 +891,6 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt) if ((tp = line2tty(minor)) == NULL) return ENXIO; - /* Translated minor numbers are a problem when sending late replies. */ - if (tp->tty_minor != minor) - return EBADF; - watch = (ops & CDEV_NOTIFY); ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR); @@ -902,11 +898,21 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt) ops &= ~ready_ops; if (ops && watch) { + /* Translated minor numbers are a problem with late select replies. We + * have to save the minor number used to do the select, since otherwise + * VFS won't be able to make sense of those late replies. We do not + * support selecting on two different minors for the same object. + */ + if (tp->tty_select_ops != 0 && tp->tty_select_minor != minor) { + printf("TTY: select on one object with two minors (%d, %d)\n", + tp->tty_select_minor, minor); + return EBADF; + } tp->tty_select_ops |= ops; tp->tty_select_proc = endpt; + tp->tty_select_minor = minor; } - assert(tp->tty_minor == minor); return ready_ops; } diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h index bc6826295..de5605b79 100644 --- a/drivers/tty/tty.h +++ b/drivers/tty/tty.h @@ -75,8 +75,9 @@ typedef struct tty { cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */ /* select() data */ - int tty_select_ops; /* which operations are interesting */ + unsigned int tty_select_ops; /* which operations are interesting */ endpoint_t tty_select_proc; /* which process wants notification */ + devminor_t tty_select_minor; /* minor used to start select query */ /* Miscellaneous. */ devfun_t tty_ioctl; /* set line speed, etc. at the device level */