blob: 9b6ef172607ce649d631b448eb793969be1fcb2a [file] [log] [blame]
Michael Rothe3d4d252011-07-19 15:41:55 -05001/*
Michael Roth42074a92012-01-19 22:19:27 -06002 * QEMU Guest Agent POSIX-specific command implementations
Michael Rothe3d4d252011-07-19 15:41:55 -05003 *
4 * Copyright IBM Corp. 2011
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
Michal Privoznik3424fc92012-02-29 17:02:23 +01008 * Michal Privoznik <mprivozn@redhat.com>
Michael Rothe3d4d252011-07-19 15:41:55 -05009 *
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
12 */
13
14#include <glib.h>
Michael Rothe3d4d252011-07-19 15:41:55 -050015#include <sys/types.h>
16#include <sys/ioctl.h>
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030017#include <sys/wait.h>
Michael Rothe3d4d252011-07-19 15:41:55 -050018#include "qga/guest-agent-core.h"
19#include "qga-qmp-commands.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010020#include "qapi/qmp/qerror.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010021#include "qemu/queue.h"
22#include "qemu/host-utils.h"
Michael Rothe3d4d252011-07-19 15:41:55 -050023
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030024#ifndef CONFIG_HAS_ENVIRON
Andreas Färbereecae142012-05-27 17:02:20 +020025#ifdef __APPLE__
26#include <crt_externs.h>
27#define environ (*_NSGetEnviron())
28#else
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030029extern char **environ;
30#endif
Andreas Färbereecae142012-05-27 17:02:20 +020031#endif
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030032
Michael Rothe72c3f22012-03-25 13:59:41 -050033#if defined(__linux__)
34#include <mntent.h>
35#include <linux/fs.h>
36#include <ifaddrs.h>
37#include <arpa/inet.h>
38#include <sys/socket.h>
39#include <net/if.h>
Michael Rothe72c3f22012-03-25 13:59:41 -050040
Paolo Bonzinieab5fd52012-06-13 07:41:28 +020041#ifdef FIFREEZE
Michael Rothe72c3f22012-03-25 13:59:41 -050042#define CONFIG_FSFREEZE
43#endif
Paolo Bonzinieab5fd52012-06-13 07:41:28 +020044#ifdef FITRIM
45#define CONFIG_FSTRIM
46#endif
Michael Rothe72c3f22012-03-25 13:59:41 -050047#endif
48
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020049static void ga_wait_child(pid_t pid, int *status, Error **err)
50{
51 pid_t rpid;
52
53 *status = 0;
54
55 do {
56 rpid = waitpid(pid, status, 0);
57 } while (rpid == -1 && errno == EINTR);
58
59 if (rpid == -1) {
60 error_setg_errno(err, errno, "failed to wait for child (pid: %d)", pid);
61 return;
62 }
63
64 g_assert(rpid == pid);
65}
66
Michael Rothe3d4d252011-07-19 15:41:55 -050067void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
68{
Michael Rothe3d4d252011-07-19 15:41:55 -050069 const char *shutdown_flag;
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020070 Error *local_err = NULL;
71 pid_t pid;
Luiz Capitulino36748382012-05-14 15:25:20 -030072 int status;
Michael Rothe3d4d252011-07-19 15:41:55 -050073
74 slog("guest-shutdown called, mode: %s", mode);
75 if (!has_mode || strcmp(mode, "powerdown") == 0) {
76 shutdown_flag = "-P";
77 } else if (strcmp(mode, "halt") == 0) {
78 shutdown_flag = "-H";
79 } else if (strcmp(mode, "reboot") == 0) {
80 shutdown_flag = "-r";
81 } else {
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020082 error_setg(err,
83 "mode is invalid (valid values are: halt|powerdown|reboot");
Michael Rothe3d4d252011-07-19 15:41:55 -050084 return;
85 }
86
Luiz Capitulinod5dd3492012-05-11 16:19:47 -030087 pid = fork();
88 if (pid == 0) {
Michael Rothe3d4d252011-07-19 15:41:55 -050089 /* child, start the shutdown */
90 setsid();
Luiz Capitulino36748382012-05-14 15:25:20 -030091 reopen_fd_to_null(0);
92 reopen_fd_to_null(1);
93 reopen_fd_to_null(2);
Michael Rothe3d4d252011-07-19 15:41:55 -050094
Luiz Capitulino36748382012-05-14 15:25:20 -030095 execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
96 "hypervisor initiated shutdown", (char*)NULL, environ);
97 _exit(EXIT_FAILURE);
Luiz Capitulinod5dd3492012-05-11 16:19:47 -030098 } else if (pid < 0) {
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020099 error_setg_errno(err, errno, "failed to create child process");
Luiz Capitulinod5dd3492012-05-11 16:19:47 -0300100 return;
101 }
102
Luiz Capitulinod220a6d2012-11-27 11:01:58 -0200103 ga_wait_child(pid, &status, &local_err);
104 if (error_is_set(&local_err)) {
105 error_propagate(err, local_err);
106 return;
107 }
108
109 if (!WIFEXITED(status)) {
110 error_setg(err, "child process has terminated abnormally");
111 return;
112 }
113
114 if (WEXITSTATUS(status)) {
115 error_setg(err, "child process has failed to shutdown");
116 return;
117 }
118
119 /* succeded */
Michael Rothe3d4d252011-07-19 15:41:55 -0500120}
121
122typedef struct GuestFileHandle {
123 uint64_t id;
124 FILE *fh;
125 QTAILQ_ENTRY(GuestFileHandle) next;
126} GuestFileHandle;
127
128static struct {
129 QTAILQ_HEAD(, GuestFileHandle) filehandles;
130} guest_file_state;
131
132static void guest_file_handle_add(FILE *fh)
133{
134 GuestFileHandle *gfh;
135
Anthony Liguori7267c092011-08-20 22:09:37 -0500136 gfh = g_malloc0(sizeof(GuestFileHandle));
Michael Rothe3d4d252011-07-19 15:41:55 -0500137 gfh->id = fileno(fh);
138 gfh->fh = fh;
139 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
140}
141
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200142static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500143{
144 GuestFileHandle *gfh;
145
146 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
147 {
148 if (gfh->id == id) {
149 return gfh;
150 }
151 }
152
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200153 error_setg(err, "handle '%" PRId64 "' has not been found", id);
Michael Rothe3d4d252011-07-19 15:41:55 -0500154 return NULL;
155}
156
157int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
158{
159 FILE *fh;
160 int fd;
161 int64_t ret = -1;
162
163 if (!has_mode) {
164 mode = "r";
165 }
166 slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
167 fh = fopen(path, mode);
168 if (!fh) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200169 error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')",
170 path, mode);
Michael Rothe3d4d252011-07-19 15:41:55 -0500171 return -1;
172 }
173
174 /* set fd non-blocking to avoid common use cases (like reading from a
175 * named pipe) from hanging the agent
176 */
177 fd = fileno(fh);
178 ret = fcntl(fd, F_GETFL);
179 ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
180 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200181 error_setg_errno(err, errno, "failed to make file '%s' non-blocking",
182 path);
Michael Rothe3d4d252011-07-19 15:41:55 -0500183 fclose(fh);
184 return -1;
185 }
186
187 guest_file_handle_add(fh);
188 slog("guest-file-open, handle: %d", fd);
189 return fd;
190}
191
192void qmp_guest_file_close(int64_t handle, Error **err)
193{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200194 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500195 int ret;
196
197 slog("guest-file-close called, handle: %ld", handle);
198 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500199 return;
200 }
201
202 ret = fclose(gfh->fh);
Luiz Capitulino3ac4b7c2012-11-27 11:01:56 -0200203 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200204 error_setg_errno(err, errno, "failed to close handle");
Michael Rothe3d4d252011-07-19 15:41:55 -0500205 return;
206 }
207
208 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
Anthony Liguori7267c092011-08-20 22:09:37 -0500209 g_free(gfh);
Michael Rothe3d4d252011-07-19 15:41:55 -0500210}
211
212struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
213 int64_t count, Error **err)
214{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200215 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500216 GuestFileRead *read_data = NULL;
217 guchar *buf;
218 FILE *fh;
219 size_t read_count;
220
221 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500222 return NULL;
223 }
224
225 if (!has_count) {
226 count = QGA_READ_COUNT_DEFAULT;
227 } else if (count < 0) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200228 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
229 count);
Michael Rothe3d4d252011-07-19 15:41:55 -0500230 return NULL;
231 }
232
233 fh = gfh->fh;
Anthony Liguori7267c092011-08-20 22:09:37 -0500234 buf = g_malloc0(count+1);
Michael Rothe3d4d252011-07-19 15:41:55 -0500235 read_count = fread(buf, 1, count, fh);
236 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200237 error_setg_errno(err, errno, "failed to read file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500238 slog("guest-file-read failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500239 } else {
240 buf[read_count] = 0;
Anthony Liguori7267c092011-08-20 22:09:37 -0500241 read_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500242 read_data->count = read_count;
243 read_data->eof = feof(fh);
244 if (read_count) {
245 read_data->buf_b64 = g_base64_encode(buf, read_count);
246 }
247 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500248 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500249 clearerr(fh);
250
251 return read_data;
252}
253
254GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
255 bool has_count, int64_t count, Error **err)
256{
257 GuestFileWrite *write_data = NULL;
258 guchar *buf;
259 gsize buf_len;
260 int write_count;
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200261 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500262 FILE *fh;
263
264 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500265 return NULL;
266 }
267
268 fh = gfh->fh;
269 buf = g_base64_decode(buf_b64, &buf_len);
270
271 if (!has_count) {
272 count = buf_len;
273 } else if (count < 0 || count > buf_len) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200274 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
275 count);
Anthony Liguori7267c092011-08-20 22:09:37 -0500276 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500277 return NULL;
278 }
279
280 write_count = fwrite(buf, 1, count, fh);
281 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200282 error_setg_errno(err, errno, "failed to write to file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500283 slog("guest-file-write failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500284 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500285 write_data = g_malloc0(sizeof(GuestFileWrite));
Michael Rothe3d4d252011-07-19 15:41:55 -0500286 write_data->count = write_count;
287 write_data->eof = feof(fh);
288 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500289 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500290 clearerr(fh);
291
292 return write_data;
293}
294
295struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
296 int64_t whence, Error **err)
297{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200298 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500299 GuestFileSeek *seek_data = NULL;
300 FILE *fh;
301 int ret;
302
303 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500304 return NULL;
305 }
306
307 fh = gfh->fh;
308 ret = fseek(fh, offset, whence);
309 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200310 error_setg_errno(err, errno, "failed to seek file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500311 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500312 seek_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500313 seek_data->position = ftell(fh);
314 seek_data->eof = feof(fh);
315 }
316 clearerr(fh);
317
318 return seek_data;
319}
320
321void qmp_guest_file_flush(int64_t handle, Error **err)
322{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200323 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500324 FILE *fh;
325 int ret;
326
327 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500328 return;
329 }
330
331 fh = gfh->fh;
332 ret = fflush(fh);
333 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200334 error_setg_errno(err, errno, "failed to flush file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500335 }
336}
337
338static void guest_file_init(void)
339{
340 QTAILQ_INIT(&guest_file_state.filehandles);
341}
342
Michael Rothe72c3f22012-03-25 13:59:41 -0500343/* linux-specific implementations. avoid this if at all possible. */
344#if defined(__linux__)
345
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200346#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
Paolo Bonziniaf022032012-06-13 07:41:27 +0200347typedef struct FsMount {
Michael Rothe3d4d252011-07-19 15:41:55 -0500348 char *dirname;
349 char *devtype;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200350 QTAILQ_ENTRY(FsMount) next;
351} FsMount;
Michael Rothe3d4d252011-07-19 15:41:55 -0500352
Paolo Bonziniaf022032012-06-13 07:41:27 +0200353typedef QTAILQ_HEAD(, FsMount) FsMountList;
Michael Roth9e8aded432012-04-16 19:52:17 -0500354
Paolo Bonziniaf022032012-06-13 07:41:27 +0200355static void free_fs_mount_list(FsMountList *mounts)
Michael Roth9e8aded432012-04-16 19:52:17 -0500356{
Paolo Bonziniaf022032012-06-13 07:41:27 +0200357 FsMount *mount, *temp;
Michael Roth9e8aded432012-04-16 19:52:17 -0500358
359 if (!mounts) {
360 return;
361 }
362
363 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
364 QTAILQ_REMOVE(mounts, mount, next);
365 g_free(mount->dirname);
366 g_free(mount->devtype);
367 g_free(mount);
368 }
369}
370
Michael Rothe3d4d252011-07-19 15:41:55 -0500371/*
372 * Walk the mount table and build a list of local file systems
373 */
Luiz Capitulino261551d2012-11-29 15:29:11 -0200374static void build_fs_mount_list(FsMountList *mounts, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500375{
376 struct mntent *ment;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200377 FsMount *mount;
Michael Roth9e2fa412012-05-29 10:08:50 -0500378 char const *mtab = "/proc/self/mounts";
Michael Rothe3d4d252011-07-19 15:41:55 -0500379 FILE *fp;
380
Michael Rothe3d4d252011-07-19 15:41:55 -0500381 fp = setmntent(mtab, "r");
382 if (!fp) {
Luiz Capitulino261551d2012-11-29 15:29:11 -0200383 error_setg(err, "failed to open mtab file: '%s'", mtab);
384 return;
Michael Rothe3d4d252011-07-19 15:41:55 -0500385 }
386
387 while ((ment = getmntent(fp))) {
388 /*
389 * An entry which device name doesn't start with a '/' is
390 * either a dummy file system or a network file system.
391 * Add special handling for smbfs and cifs as is done by
392 * coreutils as well.
393 */
394 if ((ment->mnt_fsname[0] != '/') ||
395 (strcmp(ment->mnt_type, "smbfs") == 0) ||
396 (strcmp(ment->mnt_type, "cifs") == 0)) {
397 continue;
398 }
399
Paolo Bonziniaf022032012-06-13 07:41:27 +0200400 mount = g_malloc0(sizeof(FsMount));
Anthony Liguori7267c092011-08-20 22:09:37 -0500401 mount->dirname = g_strdup(ment->mnt_dir);
402 mount->devtype = g_strdup(ment->mnt_type);
Michael Rothe3d4d252011-07-19 15:41:55 -0500403
Michael Roth9e8aded432012-04-16 19:52:17 -0500404 QTAILQ_INSERT_TAIL(mounts, mount, next);
Michael Rothe3d4d252011-07-19 15:41:55 -0500405 }
406
407 endmntent(fp);
Michael Rothe3d4d252011-07-19 15:41:55 -0500408}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200409#endif
410
411#if defined(CONFIG_FSFREEZE)
Michael Rothe3d4d252011-07-19 15:41:55 -0500412
413/*
414 * Return status of freeze/thaw
415 */
416GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
417{
Michael Rothf22d85e2012-04-17 19:01:45 -0500418 if (ga_is_frozen(ga_state)) {
419 return GUEST_FSFREEZE_STATUS_FROZEN;
420 }
421
422 return GUEST_FSFREEZE_STATUS_THAWED;
Michael Rothe3d4d252011-07-19 15:41:55 -0500423}
424
425/*
426 * Walk list of mounted file systems in the guest, and freeze the ones which
427 * are real local file systems.
428 */
429int64_t qmp_guest_fsfreeze_freeze(Error **err)
430{
431 int ret = 0, i = 0;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200432 FsMountList mounts;
433 struct FsMount *mount;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200434 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500435 int fd;
Michael Rothe3d4d252011-07-19 15:41:55 -0500436
437 slog("guest-fsfreeze called");
438
Michael Roth9e8aded432012-04-16 19:52:17 -0500439 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200440 build_fs_mount_list(&mounts, &local_err);
441 if (error_is_set(&local_err)) {
442 error_propagate(err, local_err);
443 return -1;
Michael Rothe3d4d252011-07-19 15:41:55 -0500444 }
445
446 /* cannot risk guest agent blocking itself on a write in this state */
Michael Rothf22d85e2012-04-17 19:01:45 -0500447 ga_set_frozen(ga_state);
Michael Rothe3d4d252011-07-19 15:41:55 -0500448
Michael Roth9e8aded432012-04-16 19:52:17 -0500449 QTAILQ_FOREACH(mount, &mounts, next) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500450 fd = qemu_open(mount->dirname, O_RDONLY);
451 if (fd == -1) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200452 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Michael Rothe3d4d252011-07-19 15:41:55 -0500453 goto error;
454 }
455
456 /* we try to cull filesytems we know won't work in advance, but other
457 * filesytems may not implement fsfreeze for less obvious reasons.
Michael Roth9e8aded432012-04-16 19:52:17 -0500458 * these will report EOPNOTSUPP. we simply ignore these when tallying
459 * the number of frozen filesystems.
460 *
461 * any other error means a failure to freeze a filesystem we
462 * expect to be freezable, so return an error in those cases
463 * and return system to thawed state.
Michael Rothe3d4d252011-07-19 15:41:55 -0500464 */
465 ret = ioctl(fd, FIFREEZE);
Michael Roth9e8aded432012-04-16 19:52:17 -0500466 if (ret == -1) {
467 if (errno != EOPNOTSUPP) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200468 error_setg_errno(err, errno, "failed to freeze %s",
469 mount->dirname);
Michael Roth9e8aded432012-04-16 19:52:17 -0500470 close(fd);
471 goto error;
472 }
473 } else {
474 i++;
Michael Rothe3d4d252011-07-19 15:41:55 -0500475 }
476 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500477 }
478
Paolo Bonziniaf022032012-06-13 07:41:27 +0200479 free_fs_mount_list(&mounts);
Michael Rothe3d4d252011-07-19 15:41:55 -0500480 return i;
481
482error:
Paolo Bonziniaf022032012-06-13 07:41:27 +0200483 free_fs_mount_list(&mounts);
Michael Roth9e8aded432012-04-16 19:52:17 -0500484 qmp_guest_fsfreeze_thaw(NULL);
Michael Rothe3d4d252011-07-19 15:41:55 -0500485 return 0;
486}
487
488/*
489 * Walk list of frozen file systems in the guest, and thaw them.
490 */
491int64_t qmp_guest_fsfreeze_thaw(Error **err)
492{
493 int ret;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200494 FsMountList mounts;
495 FsMount *mount;
Michael Roth9e8aded432012-04-16 19:52:17 -0500496 int fd, i = 0, logged;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200497 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500498
Michael Roth9e8aded432012-04-16 19:52:17 -0500499 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200500 build_fs_mount_list(&mounts, &local_err);
501 if (error_is_set(&local_err)) {
502 error_propagate(err, local_err);
Michael Roth9e8aded432012-04-16 19:52:17 -0500503 return 0;
504 }
505
506 QTAILQ_FOREACH(mount, &mounts, next) {
507 logged = false;
Michael Rothe3d4d252011-07-19 15:41:55 -0500508 fd = qemu_open(mount->dirname, O_RDONLY);
509 if (fd == -1) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500510 continue;
511 }
Michael Roth9e8aded432012-04-16 19:52:17 -0500512 /* we have no way of knowing whether a filesystem was actually unfrozen
513 * as a result of a successful call to FITHAW, only that if an error
514 * was returned the filesystem was *not* unfrozen by that particular
515 * call.
516 *
Jim Meyeringa31f0532012-05-09 05:12:04 +0000517 * since multiple preceding FIFREEZEs require multiple calls to FITHAW
Michael Roth9e8aded432012-04-16 19:52:17 -0500518 * to unfreeze, continuing issuing FITHAW until an error is returned,
519 * in which case either the filesystem is in an unfreezable state, or,
520 * more likely, it was thawed previously (and remains so afterward).
521 *
522 * also, since the most recent successful call is the one that did
523 * the actual unfreeze, we can use this to provide an accurate count
524 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
525 * may * be useful for determining whether a filesystem was unfrozen
526 * during the freeze/thaw phase by a process other than qemu-ga.
527 */
528 do {
529 ret = ioctl(fd, FITHAW);
530 if (ret == 0 && !logged) {
531 i++;
532 logged = true;
533 }
534 } while (ret == 0);
Michael Rothe3d4d252011-07-19 15:41:55 -0500535 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500536 }
537
Michael Rothf22d85e2012-04-17 19:01:45 -0500538 ga_unset_frozen(ga_state);
Paolo Bonziniaf022032012-06-13 07:41:27 +0200539 free_fs_mount_list(&mounts);
Michael Rothe3d4d252011-07-19 15:41:55 -0500540 return i;
541}
542
Michael Rothe3d4d252011-07-19 15:41:55 -0500543static void guest_fsfreeze_cleanup(void)
544{
545 int64_t ret;
546 Error *err = NULL;
547
Michael Rothf22d85e2012-04-17 19:01:45 -0500548 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500549 ret = qmp_guest_fsfreeze_thaw(&err);
550 if (ret < 0 || err) {
551 slog("failed to clean up frozen filesystems");
552 }
553 }
554}
Michael Rothe72c3f22012-03-25 13:59:41 -0500555#endif /* CONFIG_FSFREEZE */
Michael Rothe3d4d252011-07-19 15:41:55 -0500556
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200557#if defined(CONFIG_FSTRIM)
558/*
559 * Walk list of mounted file systems in the guest, and trim them.
560 */
561void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
562{
563 int ret = 0;
564 FsMountList mounts;
565 struct FsMount *mount;
566 int fd;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200567 Error *local_err = NULL;
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200568 struct fstrim_range r = {
569 .start = 0,
570 .len = -1,
571 .minlen = has_minimum ? minimum : 0,
572 };
573
574 slog("guest-fstrim called");
575
576 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200577 build_fs_mount_list(&mounts, &local_err);
578 if (error_is_set(&local_err)) {
579 error_propagate(err, local_err);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200580 return;
581 }
582
583 QTAILQ_FOREACH(mount, &mounts, next) {
584 fd = qemu_open(mount->dirname, O_RDONLY);
585 if (fd == -1) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200586 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200587 goto error;
588 }
589
590 /* We try to cull filesytems we know won't work in advance, but other
591 * filesytems may not implement fstrim for less obvious reasons. These
592 * will report EOPNOTSUPP; we simply ignore these errors. Any other
593 * error means an unexpected error, so return it in those cases. In
594 * some other cases ENOTTY will be reported (e.g. CD-ROMs).
595 */
596 ret = ioctl(fd, FITRIM, &r);
597 if (ret == -1) {
598 if (errno != ENOTTY && errno != EOPNOTSUPP) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200599 error_setg_errno(err, errno, "failed to trim %s",
600 mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200601 close(fd);
602 goto error;
603 }
604 }
605 close(fd);
606 }
607
608error:
609 free_fs_mount_list(&mounts);
610}
611#endif /* CONFIG_FSTRIM */
612
613
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300614#define LINUX_SYS_STATE_FILE "/sys/power/state"
615#define SUSPEND_SUPPORTED 0
616#define SUSPEND_NOT_SUPPORTED 1
617
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300618static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
619 const char *sysfile_str, Error **err)
620{
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300621 char *pmutils_path;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300622 pid_t pid, rpid;
623 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300624
625 pmutils_path = g_find_program_in_path(pmutils_bin);
626
627 pid = fork();
628 if (!pid) {
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300629 char buf[32]; /* hopefully big enough */
630 ssize_t ret;
631 int fd;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300632
633 setsid();
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300634 reopen_fd_to_null(0);
635 reopen_fd_to_null(1);
636 reopen_fd_to_null(2);
637
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300638 if (pmutils_path) {
639 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
640 }
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300641
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300642 /*
643 * If we get here either pm-utils is not installed or execle() has
644 * failed. Let's try the manual method if the caller wants it.
645 */
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300646
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300647 if (!sysfile_str) {
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300648 _exit(SUSPEND_NOT_SUPPORTED);
649 }
650
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300651 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
652 if (fd < 0) {
653 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300654 }
655
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300656 ret = read(fd, buf, sizeof(buf)-1);
657 if (ret <= 0) {
658 _exit(SUSPEND_NOT_SUPPORTED);
659 }
660 buf[ret] = '\0';
661
662 if (strstr(buf, sysfile_str)) {
663 _exit(SUSPEND_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300664 }
665
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300666 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300667 }
668
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300669 g_free(pmutils_path);
670
671 if (pid < 0) {
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300672 goto undef_err;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300673 }
674
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300675 do {
676 rpid = waitpid(pid, &status, 0);
677 } while (rpid == -1 && errno == EINTR);
678 if (rpid == pid && WIFEXITED(status)) {
679 switch (WEXITSTATUS(status)) {
680 case SUSPEND_SUPPORTED:
681 return;
682 case SUSPEND_NOT_SUPPORTED:
683 error_set(err, QERR_UNSUPPORTED);
684 return;
685 default:
686 goto undef_err;
687 }
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300688 }
689
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300690undef_err:
691 error_set(err, QERR_UNDEFINED_ERROR);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300692}
693
694static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
695 Error **err)
696{
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300697 char *pmutils_path;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300698 pid_t rpid, pid;
699 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300700
701 pmutils_path = g_find_program_in_path(pmutils_bin);
702
703 pid = fork();
704 if (pid == 0) {
705 /* child */
706 int fd;
707
708 setsid();
709 reopen_fd_to_null(0);
710 reopen_fd_to_null(1);
711 reopen_fd_to_null(2);
712
713 if (pmutils_path) {
714 execle(pmutils_path, pmutils_bin, NULL, environ);
715 }
716
717 /*
718 * If we get here either pm-utils is not installed or execle() has
719 * failed. Let's try the manual method if the caller wants it.
720 */
721
722 if (!sysfile_str) {
723 _exit(EXIT_FAILURE);
724 }
725
726 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
727 if (fd < 0) {
728 _exit(EXIT_FAILURE);
729 }
730
731 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
732 _exit(EXIT_FAILURE);
733 }
734
735 _exit(EXIT_SUCCESS);
736 }
737
738 g_free(pmutils_path);
739
740 if (pid < 0) {
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300741 goto exit_err;
742 }
743
744 do {
745 rpid = waitpid(pid, &status, 0);
746 } while (rpid == -1 && errno == EINTR);
747 if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300748 return;
749 }
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300750
751exit_err:
752 error_set(err, QERR_UNDEFINED_ERROR);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300753}
754
755void qmp_guest_suspend_disk(Error **err)
756{
757 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
758 if (error_is_set(err)) {
759 return;
760 }
761
762 guest_suspend("pm-hibernate", "disk", err);
763}
764
Luiz Capitulinofbf42212012-02-28 11:03:04 -0300765void qmp_guest_suspend_ram(Error **err)
766{
767 bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
768 if (error_is_set(err)) {
769 return;
770 }
771
772 guest_suspend("pm-suspend", "mem", err);
773}
774
Luiz Capitulino95f4f402012-02-28 11:03:05 -0300775void qmp_guest_suspend_hybrid(Error **err)
776{
777 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
778 if (error_is_set(err)) {
779 return;
780 }
781
782 guest_suspend("pm-suspend-hybrid", NULL, err);
783}
784
Michal Privoznik3424fc92012-02-29 17:02:23 +0100785static GuestNetworkInterfaceList *
786guest_find_interface(GuestNetworkInterfaceList *head,
787 const char *name)
788{
789 for (; head; head = head->next) {
790 if (strcmp(head->value->name, name) == 0) {
791 break;
792 }
793 }
794
795 return head;
796}
797
798/*
799 * Build information about guest interfaces
800 */
801GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
802{
803 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
804 struct ifaddrs *ifap, *ifa;
Michal Privoznik3424fc92012-02-29 17:02:23 +0100805
806 if (getifaddrs(&ifap) < 0) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200807 error_setg_errno(errp, errno, "getifaddrs failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100808 goto error;
809 }
810
811 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
812 GuestNetworkInterfaceList *info;
813 GuestIpAddressList **address_list = NULL, *address_item = NULL;
814 char addr4[INET_ADDRSTRLEN];
815 char addr6[INET6_ADDRSTRLEN];
816 int sock;
817 struct ifreq ifr;
818 unsigned char *mac_addr;
819 void *p;
820
821 g_debug("Processing %s interface", ifa->ifa_name);
822
823 info = guest_find_interface(head, ifa->ifa_name);
824
825 if (!info) {
826 info = g_malloc0(sizeof(*info));
827 info->value = g_malloc0(sizeof(*info->value));
828 info->value->name = g_strdup(ifa->ifa_name);
829
830 if (!cur_item) {
831 head = cur_item = info;
832 } else {
833 cur_item->next = info;
834 cur_item = info;
835 }
836 }
837
838 if (!info->value->has_hardware_address &&
839 ifa->ifa_flags & SIOCGIFHWADDR) {
840 /* we haven't obtained HW address yet */
841 sock = socket(PF_INET, SOCK_STREAM, 0);
842 if (sock == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200843 error_setg_errno(errp, errno, "failed to create socket");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100844 goto error;
845 }
846
847 memset(&ifr, 0, sizeof(ifr));
Jim Meyering1ab516e2012-10-04 13:09:58 +0200848 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100849 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200850 error_setg_errno(errp, errno,
851 "failed to get MAC address of %s",
852 ifa->ifa_name);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100853 goto error;
854 }
855
856 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
857
858 if (asprintf(&info->value->hardware_address,
859 "%02x:%02x:%02x:%02x:%02x:%02x",
860 (int) mac_addr[0], (int) mac_addr[1],
861 (int) mac_addr[2], (int) mac_addr[3],
862 (int) mac_addr[4], (int) mac_addr[5]) == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200863 error_setg_errno(errp, errno, "failed to format MAC");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100864 goto error;
865 }
866
867 info->value->has_hardware_address = true;
868 close(sock);
869 }
870
871 if (ifa->ifa_addr &&
872 ifa->ifa_addr->sa_family == AF_INET) {
873 /* interface with IPv4 address */
874 address_item = g_malloc0(sizeof(*address_item));
875 address_item->value = g_malloc0(sizeof(*address_item->value));
876 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
877 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200878 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100879 goto error;
880 }
881
882 address_item->value->ip_address = g_strdup(addr4);
883 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
884
885 if (ifa->ifa_netmask) {
886 /* Count the number of set bits in netmask.
887 * This is safe as '1' and '0' cannot be shuffled in netmask. */
888 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
889 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
890 }
891 } else if (ifa->ifa_addr &&
892 ifa->ifa_addr->sa_family == AF_INET6) {
893 /* interface with IPv6 address */
894 address_item = g_malloc0(sizeof(*address_item));
895 address_item->value = g_malloc0(sizeof(*address_item->value));
896 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
897 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200898 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100899 goto error;
900 }
901
902 address_item->value->ip_address = g_strdup(addr6);
903 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
904
905 if (ifa->ifa_netmask) {
906 /* Count the number of set bits in netmask.
907 * This is safe as '1' and '0' cannot be shuffled in netmask. */
908 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
909 address_item->value->prefix =
910 ctpop32(((uint32_t *) p)[0]) +
911 ctpop32(((uint32_t *) p)[1]) +
912 ctpop32(((uint32_t *) p)[2]) +
913 ctpop32(((uint32_t *) p)[3]);
914 }
915 }
916
917 if (!address_item) {
918 continue;
919 }
920
921 address_list = &info->value->ip_addresses;
922
923 while (*address_list && (*address_list)->next) {
924 address_list = &(*address_list)->next;
925 }
926
927 if (!*address_list) {
928 *address_list = address_item;
929 } else {
930 (*address_list)->next = address_item;
931 }
932
933 info->value->has_ip_addresses = true;
934
935
936 }
937
938 freeifaddrs(ifap);
939 return head;
940
941error:
942 freeifaddrs(ifap);
943 qapi_free_GuestNetworkInterfaceList(head);
944 return NULL;
945}
946
Michael Rothe72c3f22012-03-25 13:59:41 -0500947#else /* defined(__linux__) */
948
Michael Rothe72c3f22012-03-25 13:59:41 -0500949void qmp_guest_suspend_disk(Error **err)
950{
951 error_set(err, QERR_UNSUPPORTED);
952}
953
954void qmp_guest_suspend_ram(Error **err)
955{
956 error_set(err, QERR_UNSUPPORTED);
957}
958
959void qmp_guest_suspend_hybrid(Error **err)
960{
961 error_set(err, QERR_UNSUPPORTED);
962}
963
964GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
965{
966 error_set(errp, QERR_UNSUPPORTED);
967 return NULL;
968}
969
970#endif
971
Michael Rothd35d4cb2012-04-13 21:07:36 -0500972#if !defined(CONFIG_FSFREEZE)
973
974GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
975{
976 error_set(err, QERR_UNSUPPORTED);
977
978 return 0;
979}
980
981int64_t qmp_guest_fsfreeze_freeze(Error **err)
982{
983 error_set(err, QERR_UNSUPPORTED);
984
985 return 0;
986}
987
988int64_t qmp_guest_fsfreeze_thaw(Error **err)
989{
990 error_set(err, QERR_UNSUPPORTED);
991
992 return 0;
993}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200994#endif /* CONFIG_FSFREEZE */
Michael Rothd35d4cb2012-04-13 21:07:36 -0500995
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200996#if !defined(CONFIG_FSTRIM)
997void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
998{
999 error_set(err, QERR_UNSUPPORTED);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001000}
Michael Rothd35d4cb2012-04-13 21:07:36 -05001001#endif
1002
Michael Rothe3d4d252011-07-19 15:41:55 -05001003/* register init/cleanup routines for stateful command groups */
1004void ga_command_state_init(GAState *s, GACommandState *cs)
1005{
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001006#if defined(CONFIG_FSFREEZE)
Michael Rothf22d85e2012-04-17 19:01:45 -05001007 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001008#endif
Michael Rothe3d4d252011-07-19 15:41:55 -05001009 ga_command_state_add(cs, guest_file_init, NULL);
1010}