CVS commit: [netbsd-6] src/sys/arch/xen/xenbus
Module Name:src Committed By: msaitoh Date: Fri Nov 30 04:24:41 UTC 2012 Modified Files: src/sys/arch/xen/xenbus [netbsd-6]: xenbus_xs.c Log Message: Pull up following revision(s) (requested by royger in ticket #728): sys/arch/xen/xenbus/xenbus_xs.c: revision 1.23 xen: prevent adding duplicate xenwatches When a xenstore watch triggers, the event is processed on process_msg and if a valid handle it's found the handler is queued for execution on the pending xen watches queue (watch_events). This may present a problem if we trigger a xenwatch several times and then disconnect the device. If several xenwatch events are added to the watch_events queue and the device is disconnected afterwards, the first processed xenwatch event will disconnect the device, remove the watch and free all resources. This triggers a panic if there are pending xenwatch events for that device already queued in the local queue of the function xenwatch_thread, since when the next watch that has the same handler tries to execute we get a panic due to the fact that the device is already disconnected and all resources had been freed: xenbus_watch: 0xab7cd1d0 xbw_callback: 0x80755dd4 otherend_changed: backend/vif/1/0 backend/vif/1/0/state 6 backend/vif/1/0 -> Closed backend/vif/1/0 -> backend_device, b_detach: 0x8075a2bf xenbus_watch: 0xab7cd1d0 xbw_callback: 0xfc5ec02183e547a8 fatal protection fault in supervisor mode trap type 4 code 0 rip 80756596 cs e030 rflags 10246 cr2 7f7ff7b4c020 ilevel 0 rsp a000e6d82c50 curlwp 0xaa72d580 pid 0 lid 36 lowest kstack 0xa000e6d7f000 kernel: protection fault trap, code=0 Stopped in pid 0.36 (system) at netbsd:xenwatch_thread+0xc7:call *10(%rax ) xenwatch_thread() at netbsd:xenwatch_thread+0xc7 ds f es 5987 fs 2c40 gs 1460 rdi ab7cd1d0 rsi aa5477f0 rbp a000e6d82c70 rbx ab7c14c0 rdx 2 rcx f rax ab7cd1d0 r8 78 r9 ffef r10 deadbeef r11 1 r12 a000e6d82c50 r13 aa72d580 r14 aa72d580 r15 0 rip 80756596xenwatch_thread+0xc7 cs e030 rflags 10246 rsp a000e6d82c50 ss e02b netbsd:xenwatch_thread+0xc7:call*10(%rax) To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.22.8.1 src/sys/arch/xen/xenbus/xenbus_xs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/xen/xenbus/xenbus_xs.c diff -u src/sys/arch/xen/xenbus/xenbus_xs.c:1.22 src/sys/arch/xen/xenbus/xenbus_xs.c:1.22.8.1 --- src/sys/arch/xen/xenbus/xenbus_xs.c:1.22 Wed Jul 27 23:11:23 2011 +++ src/sys/arch/xen/xenbus/xenbus_xs.c Fri Nov 30 04:24:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: xenbus_xs.c,v 1.22 2011/07/27 23:11:23 matt Exp $ */ +/* $NetBSD: xenbus_xs.c,v 1.22.8.1 2012/11/30 04:24:41 msaitoh Exp $ */ /** * xenbus_xs.c * @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.22 2011/07/27 23:11:23 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.22.8.1 2012/11/30 04:24:41 msaitoh Exp $"); #if 0 #define DPRINTK(fmt, args...) \ @@ -751,7 +751,7 @@ xenwatch_thread(void *unused) static int process_msg(void) { - struct xs_stored_msg *msg; + struct xs_stored_msg *msg, *s_msg; char *body; int err; @@ -782,7 +782,7 @@ process_msg(void) body[msg->hdr.len] = '\0'; if (msg->hdr.type == XS_WATCH_EVENT) { - bool found; + bool found, repeated; DPRINTK("process_msg: XS_WATCH_EVENT"); msg->u.watch.vec = split(body, msg->hdr.len, @@ -796,14 +796,24 @@ process_msg(void) msg->u.watch.handle = find_watch( msg->u.watch.vec[XS_WATCH_TOKEN]); found = (msg->u.watch.handle != NULL); + repeated = false; if (found) { mutex_enter(&watch_events_lock); - SIMPLEQ_INSERT_TAIL(&watch_events, msg, msg_next); - cv_broadcast(&watch_cv); + /* Don't add duplicate events to the queue of pending watches */ + SIMPLEQ_FOREACH(s_msg, &watch_events, msg_next) { +if (s_msg->u.watch.handle == msg->u.watch.handle) { + repeated = true; + break; +} + } + if (!repeated) { +SIMPLEQ_INSERT_TAIL(&watch_events, msg, msg_next); +cv_broadcast(&watch_cv); + } mutex_exit(&watch_events_lock); } mutex_exit(&watches_lock); - if (!found) { + if (!found || repeated) { free(msg->u.watch.vec, M_DEVBUF); free(msg, M_DEVBUF); }
CVS commit: [netbsd-6] src/sys/arch/xen/xenbus
Module Name:src Committed By: riz Date: Tue Jun 12 18:30:50 UTC 2012 Modified Files: src/sys/arch/xen/xenbus [netbsd-6]: xenbus_probe.c Log Message: Pull up following revision(s) (requested by sborrill in ticket #313): sys/arch/xen/xenbus/xenbus_probe.c: revision 1.36 sys/arch/xen/xenbus/xenbus_probe.c: revision 1.37 Sort vif and vbd device IDs numerically so that attach order does not depend on the order they are passed in through xenstore. While this works for hand-crafted Xen configuration files, it does not work for XenServer, XCP or EC2 instances. This means that adding an extra virtual disk can make the domU unbootable. ID is actually based on the Linux device major/minor so this approach isn't entirely correct (for instance, you can specify devices to be non-contiguous which doesn't fit too well with our autoconf approach), but it works as a first approximation. Tested by me on XenServer and riz@ on EC2. OK bouyer@ Fix problem where devices with ID 0 were skipped as invalid as it didn't distinguish between numerical zero and invalid numeric string. To generate a diff of this commit: cvs rdiff -u -r1.35 -r1.35.8.1 src/sys/arch/xen/xenbus/xenbus_probe.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/xen/xenbus/xenbus_probe.c diff -u src/sys/arch/xen/xenbus/xenbus_probe.c:1.35 src/sys/arch/xen/xenbus/xenbus_probe.c:1.35.8.1 --- src/sys/arch/xen/xenbus/xenbus_probe.c:1.35 Thu Sep 22 23:02:35 2011 +++ src/sys/arch/xen/xenbus/xenbus_probe.c Tue Jun 12 18:30:50 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: xenbus_probe.c,v 1.35 2011/09/22 23:02:35 jym Exp $ */ +/* $NetBSD: xenbus_probe.c,v 1.35.8.1 2012/06/12 18:30:50 riz Exp $ */ /** * Talks to Xen Store to figure out what devices we have. * @@ -29,7 +29,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.35 2011/09/22 23:02:35 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.35.8.1 2012/06/12 18:30:50 riz Exp $"); #if 0 #define DPRINTK(fmt, args...) \ @@ -321,7 +321,8 @@ static int xenbus_probe_device_type(const char *path, const char *type, int (*create)(struct xenbus_device *)) { - int err, i, msize; + int err, i, pos, msize; + int *lookup = NULL; unsigned long state; char **dir; unsigned int dir_n = 0; @@ -335,8 +336,62 @@ xenbus_probe_device_type(const char *pat if (err) return err; - for (i = 0; i < dir_n; i++) { + /* Only sort frontend devices i.e. create == NULL*/ + if (dir_n > 1 && create == NULL) { + int minp; + unsigned long minv; + unsigned long *id; + + lookup = malloc(sizeof(int) * dir_n, M_DEVBUF, + M_WAITOK | M_ZERO); + if (lookup == NULL) + panic("can't malloc lookup"); + + id = malloc(sizeof(unsigned long) * dir_n, M_DEVBUF, + M_WAITOK | M_ZERO); + if (id == NULL) + panic("can't malloc id"); + + /* Convert string values to numeric; skip invalid */ + for (i = 0; i < dir_n; i++) { + /* + * Add one to differentiate numerical zero from invalid + * string. Has no effect on sort order. + */ + id[i] = strtoul(dir[i], &ep, 10) + 1; + if (dir[i][0] == '\0' || *ep != '\0') +id[i] = 0; + } + + /* Build lookup table in ascending order */ + for (pos = 0; pos < dir_n; ) { + minv = UINT32_MAX; + minp = -1; + for (i = 0; i < dir_n; i++) { +if (id[i] < minv && id[i] > 0) { + minv = id[i]; + minp = i; +} + } + if (minp >= 0) { +lookup[pos++] = minp; +id[minp] = 0; + } + else +break; + } + + free(id, M_DEVBUF); + /* Adjust in case we had to skip non-numeric entries */ + dir_n = pos; + } + + for (pos = 0; pos < dir_n; pos++) { err = 0; + if (lookup) + i = lookup[pos]; + else + i = pos; /* * add size of path to size of xenbus_device. xenbus_device * already has room for one char in xbusd_path. @@ -413,6 +468,9 @@ xenbus_probe_device_type(const char *pat watch_otherend(xbusd); } free(dir, M_DEVBUF); + if (lookup) + free(lookup, M_DEVBUF); + return err; }