cons: Support epolling /dev/null Some apps want to epoll on their output streams. If that's redirected to /dev/null (#cons/null), then they will try to epoll/select/poll on it. We don't have actual edges, but we can fake it. And we'll also need to support stat reporting writable. Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/drivers/dev/cons.c b/kern/drivers/dev/cons.c index 572caf5..b2639da 100644 --- a/kern/drivers/dev/cons.c +++ b/kern/drivers/dev/cons.c
@@ -729,6 +729,11 @@ perm |= qreadable(cons_q) ? DMREADABLE : 0; devdir(c, tab->qid, tab->name, qlen(cons_q), eve.name, perm, &dir); return dev_make_stat(c, &dir, dp, n); + case Qnull: + tab = &consdir[Qnull]; + perm = tab->perm | DMWRITABLE; + devdir(c, tab->qid, tab->name, 0, eve.name, perm, &dir); + return dev_make_stat(c, &dir, dp, n); default: return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen); } @@ -1312,11 +1317,33 @@ return ret; } +/* Null isn't really tapable, since there are no edge events - it is always + * writable. However, users might want to tap their output files, regardless of + * whether or not it will generate an event. We'll pretend that we tapped it + * (or untapped, based on the command). + * + * Note that epoll will generate an event, since it will stat null and see its + * writable, so epoll will appear to have an event. */ +static int tap_null(struct chan *c, struct fd_tap *tap, int cmd) +{ + /* We don't actually support HANGUP, but epoll implies it. */ + #define CONS_NULL_TAPS (FDTAP_FILT_WRITABLE | FDTAP_FILT_HANGUP) + + if (tap->filter & ~CONS_NULL_TAPS) { + set_error(ENOSYS, "Unsupported #%s tap, must be %p", devname(), + CONS_NULL_TAPS); + return -1; + } + return 0; +} + static int cons_tapfd(struct chan *c, struct fd_tap *tap, int cmd) { switch ((uint32_t)c->qid.path) { case Qstdin: return tap_stdin(c, tap, cmd); + case Qnull: + return tap_null(c, tap, cmd); default: set_error(ENOSYS, "Can't tap #%s file type %d", devname(), c->qid.path);