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
This commit is contained in:
David van Moolenbroek 2013-09-27 11:56:29 +00:00 committed by Lionel Sambuc
parent 913340b559
commit ec2359d566
2 changed files with 15 additions and 8 deletions

View file

@ -873,8 +873,8 @@ int select_retry(struct tty *tp)
int ops; int ops;
if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) { if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) {
chardriver_reply_select(tp->tty_select_proc, tp->tty_minor, chardriver_reply_select(tp->tty_select_proc,
ops); tp->tty_select_minor, ops);
tp->tty_select_ops &= ~ops; tp->tty_select_ops &= ~ops;
} }
return OK; return OK;
@ -891,10 +891,6 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
if ((tp = line2tty(minor)) == NULL) if ((tp = line2tty(minor)) == NULL)
return ENXIO; return ENXIO;
/* Translated minor numbers are a problem when sending late replies. */
if (tp->tty_minor != minor)
return EBADF;
watch = (ops & CDEV_NOTIFY); watch = (ops & CDEV_NOTIFY);
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR); 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; ops &= ~ready_ops;
if (ops && watch) { 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_ops |= ops;
tp->tty_select_proc = endpt; tp->tty_select_proc = endpt;
tp->tty_select_minor = minor;
} }
assert(tp->tty_minor == minor);
return ready_ops; return ready_ops;
} }

View file

@ -75,8 +75,9 @@ typedef struct tty {
cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */ cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */
/* select() data */ /* 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 */ endpoint_t tty_select_proc; /* which process wants notification */
devminor_t tty_select_minor; /* minor used to start select query */
/* Miscellaneous. */ /* Miscellaneous. */
devfun_t tty_ioctl; /* set line speed, etc. at the device level */ devfun_t tty_ioctl; /* set line speed, etc. at the device level */