CVS commit: [netbsd-6] src/sys/arch/xen/xenbus

2012-11-29 Thread SAITOH Masanobu
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

2012-06-12 Thread Jeff Rizzo
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;
 }