From: David van Moolenbroek Date: Thu, 4 Aug 2016 16:12:54 +0000 (+0000) Subject: VFS: add debug dump for select X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=refs%2Fchanges%2F43%2F3343%2F1;p=minix.git VFS: add debug dump for select By now it has become clear that the VFS select code has an unusually high concentration of bugs, and there is no indication that any form of convergence to a bug-free state is in sight. Thus, for now, it may be helpful to be able to dump the contents of the select tables in order to track down any bugs in the future. Hopefully that will allow the next bugs to be resolved slightly after than before. The debug dump can be triggered with "svrctl vfs get print_select". Change-Id: Ia826746dce0f065d7f3b46aa9047945067b8263d --- diff --git a/minix/servers/vfs/misc.c b/minix/servers/vfs/misc.c index b47bbd0d7..d02b99534 100644 --- a/minix/servers/vfs/misc.c +++ b/minix/servers/vfs/misc.c @@ -862,6 +862,11 @@ int do_svrctl(void) sysgetenv.val = 0; sysgetenv.vallen = 0; r = OK; + } else if (!strcmp(search_key, "print_select")) { + select_dump(); + sysgetenv.val = 0; + sysgetenv.vallen = 0; + r = OK; } else if (!strcmp(search_key, "active_threads")) { int active = NR_WTHREADS - worker_available(); snprintf(small_buf, sizeof(small_buf) - 1, diff --git a/minix/servers/vfs/proto.h b/minix/servers/vfs/proto.h index 37763a655..d031282d4 100644 --- a/minix/servers/vfs/proto.h +++ b/minix/servers/vfs/proto.h @@ -352,6 +352,7 @@ void select_forget(void); void select_reply1(endpoint_t driver_e, devminor_t minor, int status); void select_reply2(endpoint_t driver_e, devminor_t minor, int status); void select_unsuspend_by_endpt(endpoint_t proc); +void select_dump(void); /* worker.c */ void worker_init(void); diff --git a/minix/servers/vfs/select.c b/minix/servers/vfs/select.c index ac6e34044..92b852b54 100644 --- a/minix/servers/vfs/select.c +++ b/minix/servers/vfs/select.c @@ -1113,3 +1113,54 @@ static void select_lock_filp(struct filp *f, int ops) lock_filp(f, locktype); } + +/* + * Dump the state of the entire select table, for debugging purposes. + */ +void +select_dump(void) +{ + struct selectentry *se; + struct filp *f; + struct dmap *dp; + dev_t dev; + int s, fd; + + for (s = 0; s < MAXSELECTS; s++) { + se = &selecttab[s]; + if (se->requestor == NULL) + continue; + + printf("select %d: endpt %d nfds %d nreadyfds %d error %d " + "block %d starting %d expiry %u is_deferred %d\n", + s, se->req_endpt, se->nfds, se->nreadyfds, se->error, + se->block, se->starting, se->expiry, is_deferred(se)); + + for (fd = 0; !se->starting && fd < se->nfds; fd++) { + /* Save on output: do not print NULL filps at all. */ + if ((f = se->filps[fd]) == NULL) + continue; + + printf("- [%d] filp %p flags %x type ", fd, f, + f->filp_select_flags); + if (is_regular_file(f)) + printf("regular\n"); + else if (is_pipe(f)) + printf("pipe\n"); + else if (is_char_device(f)) { + dev = cdev_map(f->filp_vno->v_sdev, + se->requestor); + printf("char (dev <%d,%d>, dmap ", + major(dev), minor(dev)); + if (dev != NO_DEV) { + dp = &dmap[major(dev)]; + printf("busy %d filp %p)\n", + dp->dmap_sel_busy, + dp->dmap_sel_filp); + } else + printf("unknown)\n"); + } else + printf("unknown\n"); + } + } +}