Module Name: src Committed By: jym Date: Mon Dec 26 20:26:38 UTC 2011
Modified Files: src/sys/arch/xen/xen: balloon.c Log Message: Properly protect the min/target variables from balloon_sc, not just target. Use their reference directly instead of going through their opaque sysctl_data storage. It makes the locking a bit more obvious. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/arch/xen/xen/balloon.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/xen/balloon.c diff -u src/sys/arch/xen/xen/balloon.c:1.11 src/sys/arch/xen/xen/balloon.c:1.12 --- src/sys/arch/xen/xen/balloon.c:1.11 Tue Sep 20 00:12:24 2011 +++ src/sys/arch/xen/xen/balloon.c Mon Dec 26 20:26:38 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: balloon.c,v 1.11 2011/09/20 00:12:24 jym Exp $ */ +/* $NetBSD: balloon.c,v 1.12 2011/12/26 20:26:38 jym Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ #define BALLOONDEBUG 0 #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: balloon.c,v 1.11 2011/09/20 00:12:24 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: balloon.c,v 1.12 2011/12/26 20:26:38 jym Exp $"); #include <sys/inttypes.h> #include <sys/device.h> @@ -129,18 +129,17 @@ struct balloon_xenbus_softc { device_t sc_dev; struct sysctllog *sc_log; - kmutex_t balloon_mtx; /* Protects condvar and target (below) */ + kmutex_t balloon_mtx; /* Protects condvar, target and res_min (below) */ kcondvar_t balloon_cv; /* Condvar variable for target (below) */ size_t balloon_target; /* Target domain reservation size in pages. */ - xen_pfn_t *sc_mfn_list; /* List of MFNs passed from/to balloon */ + /* Minimum amount of memory reserved by domain, in KiB */ + uint64_t balloon_res_min; + xen_pfn_t *sc_mfn_list; /* List of MFNs passed from/to balloon */ pool_cache_t bpge_pool; /* pool cache for balloon page entries */ /* linked list for tracking pages used by balloon */ SLIST_HEAD(, balloon_page_entry) balloon_page_entries; size_t balloon_num_page_entries; - - /* Minimum amount of memory reserved by domain, in KiB */ - uint64_t balloon_res_min; }; static size_t xenmem_get_currentreservation(void); @@ -607,21 +606,25 @@ balloon_xenbus_watcher(struct xenbus_wat unsigned int len) { size_t new_target; - uint64_t target_kb = balloon_xenbus_read_target(); - uint64_t target_min = balloon_sc->balloon_res_min; - uint64_t target_max = BALLOON_PAGES_TO_KB(xenmem_get_maxreservation()); + uint64_t target_kb, target_max, target_min; + target_kb = balloon_xenbus_read_target(); if (target_kb == 0) { /* bogus -- just return */ return; } + mutex_enter(&balloon_sc->balloon_mtx); + target_min = balloon_sc->balloon_res_min; + mutex_exit(&balloon_sc->balloon_mtx); if (target_kb < target_min) { device_printf(balloon_sc->sc_dev, "new target %"PRIu64" is below min %"PRIu64"\n", target_kb, target_min); return; } + + target_max = BALLOON_PAGES_TO_KB(xenmem_get_maxreservation()); if (target_kb > target_max) { /* * Should not happen. Hypervisor should block balloon @@ -664,7 +667,10 @@ sysctl_kern_xen_balloon_min(SYSCTLFN_ARG node = *rnode; node.sysctl_data = &newval; - newval = *(u_quad_t *)rnode->sysctl_data; + + mutex_enter(&balloon_sc->balloon_mtx); + newval = balloon_sc->balloon_res_min; + mutex_exit(&balloon_sc->balloon_mtx); error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) @@ -678,8 +684,10 @@ sysctl_kern_xen_balloon_min(SYSCTLFN_ARG return EPERM; } - if (*(u_quad_t *)rnode->sysctl_data != newval) - atomic_swap_64((u_quad_t *)rnode->sysctl_data, newval); + mutex_enter(&balloon_sc->balloon_mtx); + if (balloon_sc->balloon_res_min != newval) + balloon_sc->balloon_res_min = newval; + mutex_exit(&balloon_sc->balloon_mtx); return 0; } @@ -729,8 +737,11 @@ sysctl_kern_xen_balloon_target(SYSCTLFN_ node = *rnode; node.sysctl_data = &newval; - /* we are just reading the value of target, no lock needed */ - newval = BALLOON_PAGES_TO_KB(*(u_quad_t*)rnode->sysctl_data); + + mutex_enter(&balloon_sc->balloon_mtx); + newval = BALLOON_PAGES_TO_KB(balloon_sc->balloon_target); + res_min = balloon_sc->balloon_res_min; + mutex_exit(&balloon_sc->balloon_mtx); error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (newp == NULL || error != 0) { @@ -747,7 +758,6 @@ sysctl_kern_xen_balloon_target(SYSCTLFN_ * sorry. */ res_max = BALLOON_PAGES_TO_KB(xenmem_get_maxreservation()); - res_min = balloon_sc->balloon_res_min; if (newval < res_min || newval > res_max) { #if BALLOONDEBUG device_printf(balloon_sc->sc_dev, @@ -799,16 +809,14 @@ sysctl_kern_xen_balloon_setup(struct bal CTLTYPE_QUAD, "current", SYSCTL_DESCR("Domain's current memory reservation from " "hypervisor, in KiB."), - sysctl_kern_xen_balloon_current, 0, - NULL, 0, + sysctl_kern_xen_balloon_current, 0, NULL, 0, CTL_CREATE, CTL_EOL); sysctl_createv(clog, 0, &node, NULL, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_QUAD, "target", SYSCTL_DESCR("Target memory reservation for domain, in KiB."), - sysctl_kern_xen_balloon_target, 0, - &sc->balloon_target, 0, + sysctl_kern_xen_balloon_target, 0, NULL, 0, CTL_CREATE, CTL_EOL); sysctl_createv(clog, 0, &node, NULL, @@ -816,8 +824,7 @@ sysctl_kern_xen_balloon_setup(struct bal CTLTYPE_QUAD, "min", SYSCTL_DESCR("Minimum amount of memory the domain " "reserves, in KiB."), - sysctl_kern_xen_balloon_min, 0, - &sc->balloon_res_min, 0, + sysctl_kern_xen_balloon_min, 0, NULL, 0, CTL_CREATE, CTL_EOL); sysctl_createv(clog, 0, &node, NULL, @@ -825,7 +832,6 @@ sysctl_kern_xen_balloon_setup(struct bal CTLTYPE_QUAD, "max", SYSCTL_DESCR("Maximum amount of memory the domain " "can use, in KiB."), - sysctl_kern_xen_balloon_max, 0, - NULL, 0, + sysctl_kern_xen_balloon_max, 0, NULL, 0, CTL_CREATE, CTL_EOL); }