blob: c83d26d0a5b22c569e771e508be1af518ea4ea60 [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
Lei Li6912e6a2013-03-05 17:39:11 +0800122int64_t qmp_guest_get_time(Error **errp)
123{
124 int ret;
125 qemu_timeval tq;
126 int64_t time_ns;
127
128 ret = qemu_gettimeofday(&tq);
129 if (ret < 0) {
130 error_setg_errno(errp, errno, "Failed to get time");
131 return -1;
132 }
133
134 time_ns = tq.tv_sec * 1000000000LL + tq.tv_usec * 1000;
135 return time_ns;
136}
137
Michael Rothe3d4d252011-07-19 15:41:55 -0500138typedef struct GuestFileHandle {
139 uint64_t id;
140 FILE *fh;
141 QTAILQ_ENTRY(GuestFileHandle) next;
142} GuestFileHandle;
143
144static struct {
145 QTAILQ_HEAD(, GuestFileHandle) filehandles;
146} guest_file_state;
147
Michael Roth39097da2013-03-01 11:40:27 -0600148static int64_t guest_file_handle_add(FILE *fh, Error **errp)
Michael Rothe3d4d252011-07-19 15:41:55 -0500149{
150 GuestFileHandle *gfh;
Michael Roth39097da2013-03-01 11:40:27 -0600151 int64_t handle;
152
153 handle = ga_get_fd_handle(ga_state, errp);
154 if (error_is_set(errp)) {
155 return 0;
156 }
Michael Rothe3d4d252011-07-19 15:41:55 -0500157
Anthony Liguori7267c092011-08-20 22:09:37 -0500158 gfh = g_malloc0(sizeof(GuestFileHandle));
Michael Roth39097da2013-03-01 11:40:27 -0600159 gfh->id = handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500160 gfh->fh = fh;
161 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
Michael Roth39097da2013-03-01 11:40:27 -0600162
163 return handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500164}
165
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200166static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500167{
168 GuestFileHandle *gfh;
169
170 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
171 {
172 if (gfh->id == id) {
173 return gfh;
174 }
175 }
176
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200177 error_setg(err, "handle '%" PRId64 "' has not been found", id);
Michael Rothe3d4d252011-07-19 15:41:55 -0500178 return NULL;
179}
180
181int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
182{
183 FILE *fh;
184 int fd;
Michael Roth39097da2013-03-01 11:40:27 -0600185 int64_t ret = -1, handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500186
187 if (!has_mode) {
188 mode = "r";
189 }
190 slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
191 fh = fopen(path, mode);
192 if (!fh) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200193 error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')",
194 path, mode);
Michael Rothe3d4d252011-07-19 15:41:55 -0500195 return -1;
196 }
197
198 /* set fd non-blocking to avoid common use cases (like reading from a
199 * named pipe) from hanging the agent
200 */
201 fd = fileno(fh);
202 ret = fcntl(fd, F_GETFL);
203 ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
204 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200205 error_setg_errno(err, errno, "failed to make file '%s' non-blocking",
206 path);
Michael Rothe3d4d252011-07-19 15:41:55 -0500207 fclose(fh);
208 return -1;
209 }
210
Michael Roth39097da2013-03-01 11:40:27 -0600211 handle = guest_file_handle_add(fh, err);
212 if (error_is_set(err)) {
213 fclose(fh);
214 return -1;
215 }
216
217 slog("guest-file-open, handle: %d", handle);
218 return handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500219}
220
221void qmp_guest_file_close(int64_t handle, Error **err)
222{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200223 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500224 int ret;
225
226 slog("guest-file-close called, handle: %ld", handle);
227 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500228 return;
229 }
230
231 ret = fclose(gfh->fh);
Luiz Capitulino3ac4b7c2012-11-27 11:01:56 -0200232 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200233 error_setg_errno(err, errno, "failed to close handle");
Michael Rothe3d4d252011-07-19 15:41:55 -0500234 return;
235 }
236
237 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
Anthony Liguori7267c092011-08-20 22:09:37 -0500238 g_free(gfh);
Michael Rothe3d4d252011-07-19 15:41:55 -0500239}
240
241struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
242 int64_t count, Error **err)
243{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200244 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500245 GuestFileRead *read_data = NULL;
246 guchar *buf;
247 FILE *fh;
248 size_t read_count;
249
250 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500251 return NULL;
252 }
253
254 if (!has_count) {
255 count = QGA_READ_COUNT_DEFAULT;
256 } else if (count < 0) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200257 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
258 count);
Michael Rothe3d4d252011-07-19 15:41:55 -0500259 return NULL;
260 }
261
262 fh = gfh->fh;
Anthony Liguori7267c092011-08-20 22:09:37 -0500263 buf = g_malloc0(count+1);
Michael Rothe3d4d252011-07-19 15:41:55 -0500264 read_count = fread(buf, 1, count, fh);
265 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200266 error_setg_errno(err, errno, "failed to read file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500267 slog("guest-file-read failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500268 } else {
269 buf[read_count] = 0;
Anthony Liguori7267c092011-08-20 22:09:37 -0500270 read_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500271 read_data->count = read_count;
272 read_data->eof = feof(fh);
273 if (read_count) {
274 read_data->buf_b64 = g_base64_encode(buf, read_count);
275 }
276 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500277 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500278 clearerr(fh);
279
280 return read_data;
281}
282
283GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
284 bool has_count, int64_t count, Error **err)
285{
286 GuestFileWrite *write_data = NULL;
287 guchar *buf;
288 gsize buf_len;
289 int write_count;
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200290 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500291 FILE *fh;
292
293 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500294 return NULL;
295 }
296
297 fh = gfh->fh;
298 buf = g_base64_decode(buf_b64, &buf_len);
299
300 if (!has_count) {
301 count = buf_len;
302 } else if (count < 0 || count > buf_len) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200303 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
304 count);
Anthony Liguori7267c092011-08-20 22:09:37 -0500305 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500306 return NULL;
307 }
308
309 write_count = fwrite(buf, 1, count, fh);
310 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200311 error_setg_errno(err, errno, "failed to write to file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500312 slog("guest-file-write failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500313 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500314 write_data = g_malloc0(sizeof(GuestFileWrite));
Michael Rothe3d4d252011-07-19 15:41:55 -0500315 write_data->count = write_count;
316 write_data->eof = feof(fh);
317 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500318 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500319 clearerr(fh);
320
321 return write_data;
322}
323
324struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
325 int64_t whence, Error **err)
326{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200327 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500328 GuestFileSeek *seek_data = NULL;
329 FILE *fh;
330 int ret;
331
332 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500333 return NULL;
334 }
335
336 fh = gfh->fh;
337 ret = fseek(fh, offset, whence);
338 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200339 error_setg_errno(err, errno, "failed to seek file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500340 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500341 seek_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500342 seek_data->position = ftell(fh);
343 seek_data->eof = feof(fh);
344 }
345 clearerr(fh);
346
347 return seek_data;
348}
349
350void qmp_guest_file_flush(int64_t handle, Error **err)
351{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200352 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500353 FILE *fh;
354 int ret;
355
356 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500357 return;
358 }
359
360 fh = gfh->fh;
361 ret = fflush(fh);
362 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200363 error_setg_errno(err, errno, "failed to flush file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500364 }
365}
366
367static void guest_file_init(void)
368{
369 QTAILQ_INIT(&guest_file_state.filehandles);
370}
371
Michael Rothe72c3f22012-03-25 13:59:41 -0500372/* linux-specific implementations. avoid this if at all possible. */
373#if defined(__linux__)
374
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200375#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
Paolo Bonziniaf022032012-06-13 07:41:27 +0200376typedef struct FsMount {
Michael Rothe3d4d252011-07-19 15:41:55 -0500377 char *dirname;
378 char *devtype;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200379 QTAILQ_ENTRY(FsMount) next;
380} FsMount;
Michael Rothe3d4d252011-07-19 15:41:55 -0500381
Paolo Bonziniaf022032012-06-13 07:41:27 +0200382typedef QTAILQ_HEAD(, FsMount) FsMountList;
Michael Roth9e8aded432012-04-16 19:52:17 -0500383
Paolo Bonziniaf022032012-06-13 07:41:27 +0200384static void free_fs_mount_list(FsMountList *mounts)
Michael Roth9e8aded432012-04-16 19:52:17 -0500385{
Paolo Bonziniaf022032012-06-13 07:41:27 +0200386 FsMount *mount, *temp;
Michael Roth9e8aded432012-04-16 19:52:17 -0500387
388 if (!mounts) {
389 return;
390 }
391
392 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
393 QTAILQ_REMOVE(mounts, mount, next);
394 g_free(mount->dirname);
395 g_free(mount->devtype);
396 g_free(mount);
397 }
398}
399
Michael Rothe3d4d252011-07-19 15:41:55 -0500400/*
401 * Walk the mount table and build a list of local file systems
402 */
Luiz Capitulino261551d2012-11-29 15:29:11 -0200403static void build_fs_mount_list(FsMountList *mounts, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500404{
405 struct mntent *ment;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200406 FsMount *mount;
Michael Roth9e2fa412012-05-29 10:08:50 -0500407 char const *mtab = "/proc/self/mounts";
Michael Rothe3d4d252011-07-19 15:41:55 -0500408 FILE *fp;
409
Michael Rothe3d4d252011-07-19 15:41:55 -0500410 fp = setmntent(mtab, "r");
411 if (!fp) {
Luiz Capitulino261551d2012-11-29 15:29:11 -0200412 error_setg(err, "failed to open mtab file: '%s'", mtab);
413 return;
Michael Rothe3d4d252011-07-19 15:41:55 -0500414 }
415
416 while ((ment = getmntent(fp))) {
417 /*
418 * An entry which device name doesn't start with a '/' is
419 * either a dummy file system or a network file system.
420 * Add special handling for smbfs and cifs as is done by
421 * coreutils as well.
422 */
423 if ((ment->mnt_fsname[0] != '/') ||
424 (strcmp(ment->mnt_type, "smbfs") == 0) ||
425 (strcmp(ment->mnt_type, "cifs") == 0)) {
426 continue;
427 }
428
Paolo Bonziniaf022032012-06-13 07:41:27 +0200429 mount = g_malloc0(sizeof(FsMount));
Anthony Liguori7267c092011-08-20 22:09:37 -0500430 mount->dirname = g_strdup(ment->mnt_dir);
431 mount->devtype = g_strdup(ment->mnt_type);
Michael Rothe3d4d252011-07-19 15:41:55 -0500432
Michael Roth9e8aded432012-04-16 19:52:17 -0500433 QTAILQ_INSERT_TAIL(mounts, mount, next);
Michael Rothe3d4d252011-07-19 15:41:55 -0500434 }
435
436 endmntent(fp);
Michael Rothe3d4d252011-07-19 15:41:55 -0500437}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200438#endif
439
440#if defined(CONFIG_FSFREEZE)
Michael Rothe3d4d252011-07-19 15:41:55 -0500441
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900442typedef enum {
443 FSFREEZE_HOOK_THAW = 0,
444 FSFREEZE_HOOK_FREEZE,
445} FsfreezeHookArg;
446
447const char *fsfreeze_hook_arg_string[] = {
448 "thaw",
449 "freeze",
450};
451
452static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err)
453{
454 int status;
455 pid_t pid;
456 const char *hook;
457 const char *arg_str = fsfreeze_hook_arg_string[arg];
458 Error *local_err = NULL;
459
460 hook = ga_fsfreeze_hook(ga_state);
461 if (!hook) {
462 return;
463 }
464 if (access(hook, X_OK) != 0) {
465 error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook);
466 return;
467 }
468
469 slog("executing fsfreeze hook with arg '%s'", arg_str);
470 pid = fork();
471 if (pid == 0) {
472 setsid();
473 reopen_fd_to_null(0);
474 reopen_fd_to_null(1);
475 reopen_fd_to_null(2);
476
477 execle(hook, hook, arg_str, NULL, environ);
478 _exit(EXIT_FAILURE);
479 } else if (pid < 0) {
480 error_setg_errno(err, errno, "failed to create child process");
481 return;
482 }
483
484 ga_wait_child(pid, &status, &local_err);
485 if (error_is_set(&local_err)) {
486 error_propagate(err, local_err);
487 return;
488 }
489
490 if (!WIFEXITED(status)) {
491 error_setg(err, "fsfreeze hook has terminated abnormally");
492 return;
493 }
494
495 status = WEXITSTATUS(status);
496 if (status) {
497 error_setg(err, "fsfreeze hook has failed with status %d", status);
498 return;
499 }
500}
501
Michael Rothe3d4d252011-07-19 15:41:55 -0500502/*
503 * Return status of freeze/thaw
504 */
505GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
506{
Michael Rothf22d85e2012-04-17 19:01:45 -0500507 if (ga_is_frozen(ga_state)) {
508 return GUEST_FSFREEZE_STATUS_FROZEN;
509 }
510
511 return GUEST_FSFREEZE_STATUS_THAWED;
Michael Rothe3d4d252011-07-19 15:41:55 -0500512}
513
514/*
515 * Walk list of mounted file systems in the guest, and freeze the ones which
516 * are real local file systems.
517 */
518int64_t qmp_guest_fsfreeze_freeze(Error **err)
519{
520 int ret = 0, i = 0;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200521 FsMountList mounts;
522 struct FsMount *mount;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200523 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500524 int fd;
Michael Rothe3d4d252011-07-19 15:41:55 -0500525
526 slog("guest-fsfreeze called");
527
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900528 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
529 if (error_is_set(&local_err)) {
530 error_propagate(err, local_err);
531 return -1;
532 }
533
Michael Roth9e8aded432012-04-16 19:52:17 -0500534 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200535 build_fs_mount_list(&mounts, &local_err);
536 if (error_is_set(&local_err)) {
537 error_propagate(err, local_err);
538 return -1;
Michael Rothe3d4d252011-07-19 15:41:55 -0500539 }
540
541 /* cannot risk guest agent blocking itself on a write in this state */
Michael Rothf22d85e2012-04-17 19:01:45 -0500542 ga_set_frozen(ga_state);
Michael Rothe3d4d252011-07-19 15:41:55 -0500543
Michael Roth9e8aded432012-04-16 19:52:17 -0500544 QTAILQ_FOREACH(mount, &mounts, next) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500545 fd = qemu_open(mount->dirname, O_RDONLY);
546 if (fd == -1) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200547 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Michael Rothe3d4d252011-07-19 15:41:55 -0500548 goto error;
549 }
550
551 /* we try to cull filesytems we know won't work in advance, but other
552 * filesytems may not implement fsfreeze for less obvious reasons.
Michael Roth9e8aded432012-04-16 19:52:17 -0500553 * these will report EOPNOTSUPP. we simply ignore these when tallying
554 * the number of frozen filesystems.
555 *
556 * any other error means a failure to freeze a filesystem we
557 * expect to be freezable, so return an error in those cases
558 * and return system to thawed state.
Michael Rothe3d4d252011-07-19 15:41:55 -0500559 */
560 ret = ioctl(fd, FIFREEZE);
Michael Roth9e8aded432012-04-16 19:52:17 -0500561 if (ret == -1) {
562 if (errno != EOPNOTSUPP) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200563 error_setg_errno(err, errno, "failed to freeze %s",
564 mount->dirname);
Michael Roth9e8aded432012-04-16 19:52:17 -0500565 close(fd);
566 goto error;
567 }
568 } else {
569 i++;
Michael Rothe3d4d252011-07-19 15:41:55 -0500570 }
571 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500572 }
573
Paolo Bonziniaf022032012-06-13 07:41:27 +0200574 free_fs_mount_list(&mounts);
Michael Rothe3d4d252011-07-19 15:41:55 -0500575 return i;
576
577error:
Paolo Bonziniaf022032012-06-13 07:41:27 +0200578 free_fs_mount_list(&mounts);
Michael Roth9e8aded432012-04-16 19:52:17 -0500579 qmp_guest_fsfreeze_thaw(NULL);
Michael Rothe3d4d252011-07-19 15:41:55 -0500580 return 0;
581}
582
583/*
584 * Walk list of frozen file systems in the guest, and thaw them.
585 */
586int64_t qmp_guest_fsfreeze_thaw(Error **err)
587{
588 int ret;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200589 FsMountList mounts;
590 FsMount *mount;
Michael Roth9e8aded432012-04-16 19:52:17 -0500591 int fd, i = 0, logged;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200592 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500593
Michael Roth9e8aded432012-04-16 19:52:17 -0500594 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200595 build_fs_mount_list(&mounts, &local_err);
596 if (error_is_set(&local_err)) {
597 error_propagate(err, local_err);
Michael Roth9e8aded432012-04-16 19:52:17 -0500598 return 0;
599 }
600
601 QTAILQ_FOREACH(mount, &mounts, next) {
602 logged = false;
Michael Rothe3d4d252011-07-19 15:41:55 -0500603 fd = qemu_open(mount->dirname, O_RDONLY);
604 if (fd == -1) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500605 continue;
606 }
Michael Roth9e8aded432012-04-16 19:52:17 -0500607 /* we have no way of knowing whether a filesystem was actually unfrozen
608 * as a result of a successful call to FITHAW, only that if an error
609 * was returned the filesystem was *not* unfrozen by that particular
610 * call.
611 *
Jim Meyeringa31f0532012-05-09 05:12:04 +0000612 * since multiple preceding FIFREEZEs require multiple calls to FITHAW
Michael Roth9e8aded432012-04-16 19:52:17 -0500613 * to unfreeze, continuing issuing FITHAW until an error is returned,
614 * in which case either the filesystem is in an unfreezable state, or,
615 * more likely, it was thawed previously (and remains so afterward).
616 *
617 * also, since the most recent successful call is the one that did
618 * the actual unfreeze, we can use this to provide an accurate count
619 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
620 * may * be useful for determining whether a filesystem was unfrozen
621 * during the freeze/thaw phase by a process other than qemu-ga.
622 */
623 do {
624 ret = ioctl(fd, FITHAW);
625 if (ret == 0 && !logged) {
626 i++;
627 logged = true;
628 }
629 } while (ret == 0);
Michael Rothe3d4d252011-07-19 15:41:55 -0500630 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500631 }
632
Michael Rothf22d85e2012-04-17 19:01:45 -0500633 ga_unset_frozen(ga_state);
Paolo Bonziniaf022032012-06-13 07:41:27 +0200634 free_fs_mount_list(&mounts);
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900635
636 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err);
637
Michael Rothe3d4d252011-07-19 15:41:55 -0500638 return i;
639}
640
Michael Rothe3d4d252011-07-19 15:41:55 -0500641static void guest_fsfreeze_cleanup(void)
642{
Michael Rothe3d4d252011-07-19 15:41:55 -0500643 Error *err = NULL;
644
Michael Rothf22d85e2012-04-17 19:01:45 -0500645 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
Markus Armbruster6f686742013-01-16 18:15:08 +0100646 qmp_guest_fsfreeze_thaw(&err);
647 if (err) {
648 slog("failed to clean up frozen filesystems: %s",
649 error_get_pretty(err));
650 error_free(err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500651 }
652 }
653}
Michael Rothe72c3f22012-03-25 13:59:41 -0500654#endif /* CONFIG_FSFREEZE */
Michael Rothe3d4d252011-07-19 15:41:55 -0500655
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200656#if defined(CONFIG_FSTRIM)
657/*
658 * Walk list of mounted file systems in the guest, and trim them.
659 */
660void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
661{
662 int ret = 0;
663 FsMountList mounts;
664 struct FsMount *mount;
665 int fd;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200666 Error *local_err = NULL;
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200667 struct fstrim_range r = {
668 .start = 0,
669 .len = -1,
670 .minlen = has_minimum ? minimum : 0,
671 };
672
673 slog("guest-fstrim called");
674
675 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200676 build_fs_mount_list(&mounts, &local_err);
677 if (error_is_set(&local_err)) {
678 error_propagate(err, local_err);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200679 return;
680 }
681
682 QTAILQ_FOREACH(mount, &mounts, next) {
683 fd = qemu_open(mount->dirname, O_RDONLY);
684 if (fd == -1) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200685 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200686 goto error;
687 }
688
689 /* We try to cull filesytems we know won't work in advance, but other
690 * filesytems may not implement fstrim for less obvious reasons. These
691 * will report EOPNOTSUPP; we simply ignore these errors. Any other
692 * error means an unexpected error, so return it in those cases. In
693 * some other cases ENOTTY will be reported (e.g. CD-ROMs).
694 */
695 ret = ioctl(fd, FITRIM, &r);
696 if (ret == -1) {
697 if (errno != ENOTTY && errno != EOPNOTSUPP) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200698 error_setg_errno(err, errno, "failed to trim %s",
699 mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200700 close(fd);
701 goto error;
702 }
703 }
704 close(fd);
705 }
706
707error:
708 free_fs_mount_list(&mounts);
709}
710#endif /* CONFIG_FSTRIM */
711
712
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300713#define LINUX_SYS_STATE_FILE "/sys/power/state"
714#define SUSPEND_SUPPORTED 0
715#define SUSPEND_NOT_SUPPORTED 1
716
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300717static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
718 const char *sysfile_str, Error **err)
719{
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200720 Error *local_err = NULL;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300721 char *pmutils_path;
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200722 pid_t pid;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300723 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300724
725 pmutils_path = g_find_program_in_path(pmutils_bin);
726
727 pid = fork();
728 if (!pid) {
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300729 char buf[32]; /* hopefully big enough */
730 ssize_t ret;
731 int fd;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300732
733 setsid();
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300734 reopen_fd_to_null(0);
735 reopen_fd_to_null(1);
736 reopen_fd_to_null(2);
737
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300738 if (pmutils_path) {
739 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
740 }
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300741
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300742 /*
743 * If we get here either pm-utils is not installed or execle() has
744 * failed. Let's try the manual method if the caller wants it.
745 */
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300746
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300747 if (!sysfile_str) {
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300748 _exit(SUSPEND_NOT_SUPPORTED);
749 }
750
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300751 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
752 if (fd < 0) {
753 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300754 }
755
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300756 ret = read(fd, buf, sizeof(buf)-1);
757 if (ret <= 0) {
758 _exit(SUSPEND_NOT_SUPPORTED);
759 }
760 buf[ret] = '\0';
761
762 if (strstr(buf, sysfile_str)) {
763 _exit(SUSPEND_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300764 }
765
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300766 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200767 } else if (pid < 0) {
768 error_setg_errno(err, errno, "failed to create child process");
769 goto out;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300770 }
771
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200772 ga_wait_child(pid, &status, &local_err);
773 if (error_is_set(&local_err)) {
774 error_propagate(err, local_err);
775 goto out;
776 }
777
778 if (!WIFEXITED(status)) {
779 error_setg(err, "child process has terminated abnormally");
780 goto out;
781 }
782
783 switch (WEXITSTATUS(status)) {
784 case SUSPEND_SUPPORTED:
785 goto out;
786 case SUSPEND_NOT_SUPPORTED:
787 error_setg(err,
788 "the requested suspend mode is not supported by the guest");
789 goto out;
790 default:
791 error_setg(err,
792 "the helper program '%s' returned an unexpected exit status"
793 " code (%d)", pmutils_path, WEXITSTATUS(status));
794 goto out;
795 }
796
797out:
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300798 g_free(pmutils_path);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300799}
800
801static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
802 Error **err)
803{
Luiz Capitulino7b376082012-11-27 11:02:04 -0200804 Error *local_err = NULL;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300805 char *pmutils_path;
Luiz Capitulino7b376082012-11-27 11:02:04 -0200806 pid_t pid;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300807 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300808
809 pmutils_path = g_find_program_in_path(pmutils_bin);
810
811 pid = fork();
812 if (pid == 0) {
813 /* child */
814 int fd;
815
816 setsid();
817 reopen_fd_to_null(0);
818 reopen_fd_to_null(1);
819 reopen_fd_to_null(2);
820
821 if (pmutils_path) {
822 execle(pmutils_path, pmutils_bin, NULL, environ);
823 }
824
825 /*
826 * If we get here either pm-utils is not installed or execle() has
827 * failed. Let's try the manual method if the caller wants it.
828 */
829
830 if (!sysfile_str) {
831 _exit(EXIT_FAILURE);
832 }
833
834 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
835 if (fd < 0) {
836 _exit(EXIT_FAILURE);
837 }
838
839 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
840 _exit(EXIT_FAILURE);
841 }
842
843 _exit(EXIT_SUCCESS);
Luiz Capitulino7b376082012-11-27 11:02:04 -0200844 } else if (pid < 0) {
845 error_setg_errno(err, errno, "failed to create child process");
846 goto out;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300847 }
848
Luiz Capitulino7b376082012-11-27 11:02:04 -0200849 ga_wait_child(pid, &status, &local_err);
850 if (error_is_set(&local_err)) {
851 error_propagate(err, local_err);
852 goto out;
853 }
854
855 if (!WIFEXITED(status)) {
856 error_setg(err, "child process has terminated abnormally");
857 goto out;
858 }
859
860 if (WEXITSTATUS(status)) {
861 error_setg(err, "child process has failed to suspend");
862 goto out;
863 }
864
865out:
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300866 g_free(pmutils_path);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300867}
868
869void qmp_guest_suspend_disk(Error **err)
870{
871 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
872 if (error_is_set(err)) {
873 return;
874 }
875
876 guest_suspend("pm-hibernate", "disk", err);
877}
878
Luiz Capitulinofbf42212012-02-28 11:03:04 -0300879void qmp_guest_suspend_ram(Error **err)
880{
881 bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
882 if (error_is_set(err)) {
883 return;
884 }
885
886 guest_suspend("pm-suspend", "mem", err);
887}
888
Luiz Capitulino95f4f402012-02-28 11:03:05 -0300889void qmp_guest_suspend_hybrid(Error **err)
890{
891 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
892 if (error_is_set(err)) {
893 return;
894 }
895
896 guest_suspend("pm-suspend-hybrid", NULL, err);
897}
898
Michal Privoznik3424fc92012-02-29 17:02:23 +0100899static GuestNetworkInterfaceList *
900guest_find_interface(GuestNetworkInterfaceList *head,
901 const char *name)
902{
903 for (; head; head = head->next) {
904 if (strcmp(head->value->name, name) == 0) {
905 break;
906 }
907 }
908
909 return head;
910}
911
912/*
913 * Build information about guest interfaces
914 */
915GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
916{
917 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
918 struct ifaddrs *ifap, *ifa;
Michal Privoznik3424fc92012-02-29 17:02:23 +0100919
920 if (getifaddrs(&ifap) < 0) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200921 error_setg_errno(errp, errno, "getifaddrs failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100922 goto error;
923 }
924
925 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
926 GuestNetworkInterfaceList *info;
927 GuestIpAddressList **address_list = NULL, *address_item = NULL;
928 char addr4[INET_ADDRSTRLEN];
929 char addr6[INET6_ADDRSTRLEN];
930 int sock;
931 struct ifreq ifr;
932 unsigned char *mac_addr;
933 void *p;
934
935 g_debug("Processing %s interface", ifa->ifa_name);
936
937 info = guest_find_interface(head, ifa->ifa_name);
938
939 if (!info) {
940 info = g_malloc0(sizeof(*info));
941 info->value = g_malloc0(sizeof(*info->value));
942 info->value->name = g_strdup(ifa->ifa_name);
943
944 if (!cur_item) {
945 head = cur_item = info;
946 } else {
947 cur_item->next = info;
948 cur_item = info;
949 }
950 }
951
952 if (!info->value->has_hardware_address &&
953 ifa->ifa_flags & SIOCGIFHWADDR) {
954 /* we haven't obtained HW address yet */
955 sock = socket(PF_INET, SOCK_STREAM, 0);
956 if (sock == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200957 error_setg_errno(errp, errno, "failed to create socket");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100958 goto error;
959 }
960
961 memset(&ifr, 0, sizeof(ifr));
Jim Meyering1ab516e2012-10-04 13:09:58 +0200962 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100963 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200964 error_setg_errno(errp, errno,
965 "failed to get MAC address of %s",
966 ifa->ifa_name);
Markus Armbruster10a21582013-01-16 18:15:09 +0100967 close(sock);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100968 goto error;
969 }
970
Markus Armbruster10a21582013-01-16 18:15:09 +0100971 close(sock);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100972 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
973
Stefan Weile4ada482013-01-16 18:37:23 +0100974 info->value->hardware_address =
975 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
976 (int) mac_addr[0], (int) mac_addr[1],
977 (int) mac_addr[2], (int) mac_addr[3],
978 (int) mac_addr[4], (int) mac_addr[5]);
Michal Privoznik3424fc92012-02-29 17:02:23 +0100979
980 info->value->has_hardware_address = true;
Michal Privoznik3424fc92012-02-29 17:02:23 +0100981 }
982
983 if (ifa->ifa_addr &&
984 ifa->ifa_addr->sa_family == AF_INET) {
985 /* interface with IPv4 address */
Michal Privoznik3424fc92012-02-29 17:02:23 +0100986 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
987 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200988 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100989 goto error;
990 }
991
Markus Armbruster10a21582013-01-16 18:15:09 +0100992 address_item = g_malloc0(sizeof(*address_item));
993 address_item->value = g_malloc0(sizeof(*address_item->value));
Michal Privoznik3424fc92012-02-29 17:02:23 +0100994 address_item->value->ip_address = g_strdup(addr4);
995 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
996
997 if (ifa->ifa_netmask) {
998 /* Count the number of set bits in netmask.
999 * This is safe as '1' and '0' cannot be shuffled in netmask. */
1000 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
1001 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
1002 }
1003 } else if (ifa->ifa_addr &&
1004 ifa->ifa_addr->sa_family == AF_INET6) {
1005 /* interface with IPv6 address */
Michal Privoznik3424fc92012-02-29 17:02:23 +01001006 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
1007 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -02001008 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +01001009 goto error;
1010 }
1011
Markus Armbruster10a21582013-01-16 18:15:09 +01001012 address_item = g_malloc0(sizeof(*address_item));
1013 address_item->value = g_malloc0(sizeof(*address_item->value));
Michal Privoznik3424fc92012-02-29 17:02:23 +01001014 address_item->value->ip_address = g_strdup(addr6);
1015 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
1016
1017 if (ifa->ifa_netmask) {
1018 /* Count the number of set bits in netmask.
1019 * This is safe as '1' and '0' cannot be shuffled in netmask. */
1020 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
1021 address_item->value->prefix =
1022 ctpop32(((uint32_t *) p)[0]) +
1023 ctpop32(((uint32_t *) p)[1]) +
1024 ctpop32(((uint32_t *) p)[2]) +
1025 ctpop32(((uint32_t *) p)[3]);
1026 }
1027 }
1028
1029 if (!address_item) {
1030 continue;
1031 }
1032
1033 address_list = &info->value->ip_addresses;
1034
1035 while (*address_list && (*address_list)->next) {
1036 address_list = &(*address_list)->next;
1037 }
1038
1039 if (!*address_list) {
1040 *address_list = address_item;
1041 } else {
1042 (*address_list)->next = address_item;
1043 }
1044
1045 info->value->has_ip_addresses = true;
1046
1047
1048 }
1049
1050 freeifaddrs(ifap);
1051 return head;
1052
1053error:
1054 freeifaddrs(ifap);
1055 qapi_free_GuestNetworkInterfaceList(head);
1056 return NULL;
1057}
1058
Michael Rothe72c3f22012-03-25 13:59:41 -05001059#else /* defined(__linux__) */
1060
Michael Rothe72c3f22012-03-25 13:59:41 -05001061void qmp_guest_suspend_disk(Error **err)
1062{
1063 error_set(err, QERR_UNSUPPORTED);
1064}
1065
1066void qmp_guest_suspend_ram(Error **err)
1067{
1068 error_set(err, QERR_UNSUPPORTED);
1069}
1070
1071void qmp_guest_suspend_hybrid(Error **err)
1072{
1073 error_set(err, QERR_UNSUPPORTED);
1074}
1075
1076GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
1077{
1078 error_set(errp, QERR_UNSUPPORTED);
1079 return NULL;
1080}
1081
1082#endif
1083
Michael Rothd35d4cb2012-04-13 21:07:36 -05001084#if !defined(CONFIG_FSFREEZE)
1085
1086GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
1087{
1088 error_set(err, QERR_UNSUPPORTED);
1089
1090 return 0;
1091}
1092
1093int64_t qmp_guest_fsfreeze_freeze(Error **err)
1094{
1095 error_set(err, QERR_UNSUPPORTED);
1096
1097 return 0;
1098}
1099
1100int64_t qmp_guest_fsfreeze_thaw(Error **err)
1101{
1102 error_set(err, QERR_UNSUPPORTED);
1103
1104 return 0;
1105}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001106#endif /* CONFIG_FSFREEZE */
Michael Rothd35d4cb2012-04-13 21:07:36 -05001107
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001108#if !defined(CONFIG_FSTRIM)
1109void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
1110{
1111 error_set(err, QERR_UNSUPPORTED);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001112}
Michael Rothd35d4cb2012-04-13 21:07:36 -05001113#endif
1114
Michael Rothe3d4d252011-07-19 15:41:55 -05001115/* register init/cleanup routines for stateful command groups */
1116void ga_command_state_init(GAState *s, GACommandState *cs)
1117{
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001118#if defined(CONFIG_FSFREEZE)
Michael Rothf22d85e2012-04-17 19:01:45 -05001119 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001120#endif
Michael Rothe3d4d252011-07-19 15:41:55 -05001121 ga_command_state_add(cs, guest_file_init, NULL);
1122}