aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2011-02-17 06:04:20 -0500
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-02-25 11:43:09 -0500
commit552717231e50b478dfd19d63fd97879476ae051d (patch)
tree6ed6a314b8b4e2ee266e33fdf450c48704df5cbc /drivers
parente057a4b6e0eb6701f6ec923be2075d4984cef51a (diff)
xen: do not respond to unknown xenstore control requests
The PV xenbus control/shutdown node is written by the toolstack as a request to the guest to perform a particular action (shutdown, reboot, suspend etc). The guest is expected to acknowledge that it will complete a request by clearing the control node. Previously it would acknowledge any request, even if it did not know what to do with it. Specifically in the case where CONFIG_PM_SLEEP is not enabled the kernel would acknowledge a suspend request even though it was not actually going to do anything. Instead make the kernel only acknowledge requests if it is actually going to do something with it. This will improve the toolstack's ability to diagnose and deal with failures. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/xen/manage.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index b2a8d7856ce3..972bf783a182 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -172,12 +172,39 @@ out:
172} 172}
173#endif /* CONFIG_PM_SLEEP */ 173#endif /* CONFIG_PM_SLEEP */
174 174
175struct shutdown_handler {
176 const char *command;
177 void (*cb)(void);
178};
179
180static void do_poweroff(void)
181{
182 shutting_down = SHUTDOWN_POWEROFF;
183 orderly_poweroff(false);
184}
185
186static void do_reboot(void)
187{
188 shutting_down = SHUTDOWN_POWEROFF; /* ? */
189 ctrl_alt_del();
190}
191
175static void shutdown_handler(struct xenbus_watch *watch, 192static void shutdown_handler(struct xenbus_watch *watch,
176 const char **vec, unsigned int len) 193 const char **vec, unsigned int len)
177{ 194{
178 char *str; 195 char *str;
179 struct xenbus_transaction xbt; 196 struct xenbus_transaction xbt;
180 int err; 197 int err;
198 static struct shutdown_handler handlers[] = {
199 { "poweroff", do_poweroff },
200 { "halt", do_poweroff },
201 { "reboot", do_reboot },
202#ifdef CONFIG_PM_SLEEP
203 { "suspend", do_suspend },
204#endif
205 {NULL, NULL},
206 };
207 static struct shutdown_handler *handler;
181 208
182 if (shutting_down != SHUTDOWN_INVALID) 209 if (shutting_down != SHUTDOWN_INVALID)
183 return; 210 return;
@@ -194,7 +221,14 @@ static void shutdown_handler(struct xenbus_watch *watch,
194 return; 221 return;
195 } 222 }
196 223
197 xenbus_write(xbt, "control", "shutdown", ""); 224 for (handler = &handlers[0]; handler->command; handler++) {
225 if (strcmp(str, handler->command) == 0)
226 break;
227 }
228
229 /* Only acknowledge commands which we are prepared to handle. */
230 if (handler->cb)
231 xenbus_write(xbt, "control", "shutdown", "");
198 232
199 err = xenbus_transaction_end(xbt, 0); 233 err = xenbus_transaction_end(xbt, 0);
200 if (err == -EAGAIN) { 234 if (err == -EAGAIN) {
@@ -202,17 +236,8 @@ static void shutdown_handler(struct xenbus_watch *watch,
202 goto again; 236 goto again;
203 } 237 }
204 238
205 if (strcmp(str, "poweroff") == 0 || 239 if (handler->cb) {
206 strcmp(str, "halt") == 0) { 240 handler->cb();
207 shutting_down = SHUTDOWN_POWEROFF;
208 orderly_poweroff(false);
209 } else if (strcmp(str, "reboot") == 0) {
210 shutting_down = SHUTDOWN_POWEROFF; /* ? */
211 ctrl_alt_del();
212#ifdef CONFIG_PM_SLEEP
213 } else if (strcmp(str, "suspend") == 0) {
214 do_suspend();
215#endif
216 } else { 241 } else {
217 printk(KERN_INFO "Ignoring shutdown request: %s\n", str); 242 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
218 shutting_down = SHUTDOWN_INVALID; 243 shutting_down = SHUTDOWN_INVALID;