2 * QEMU Guest Agent POSIX-specific command implementations
4 * Copyright IBM Corp. 2011
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Michal Privoznik <mprivozn@redhat.com>
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.
15 #include <sys/types.h>
16 #include <sys/ioctl.h>
18 #include "qga/guest-agent-core.h"
19 #include "qga-qmp-commands.h"
21 #include "qemu-queue.h"
22 #include "host-utils.h"
24 #ifndef CONFIG_HAS_ENVIRON
26 #include <crt_externs.h>
27 #define environ (*_NSGetEnviron())
29 extern char **environ
;
33 #if defined(__linux__)
37 #include <arpa/inet.h>
38 #include <sys/socket.h>
42 #define CONFIG_FSFREEZE
49 void qmp_guest_shutdown(bool has_mode
, const char *mode
, Error
**err
)
51 const char *shutdown_flag
;
55 slog("guest-shutdown called, mode: %s", mode
);
56 if (!has_mode
|| strcmp(mode
, "powerdown") == 0) {
58 } else if (strcmp(mode
, "halt") == 0) {
60 } else if (strcmp(mode
, "reboot") == 0) {
63 error_set(err
, QERR_INVALID_PARAMETER_VALUE
, "mode",
64 "halt|powerdown|reboot");
70 /* child, start the shutdown */
76 execle("/sbin/shutdown", "shutdown", shutdown_flag
, "+0",
77 "hypervisor initiated shutdown", (char*)NULL
, environ
);
84 rpid
= waitpid(pid
, &status
, 0);
85 } while (rpid
== -1 && errno
== EINTR
);
86 if (rpid
== pid
&& WIFEXITED(status
) && !WEXITSTATUS(status
)) {
91 error_set(err
, QERR_UNDEFINED_ERROR
);
94 typedef struct GuestFileHandle
{
97 QTAILQ_ENTRY(GuestFileHandle
) next
;
101 QTAILQ_HEAD(, GuestFileHandle
) filehandles
;
104 static void guest_file_handle_add(FILE *fh
)
106 GuestFileHandle
*gfh
;
108 gfh
= g_malloc0(sizeof(GuestFileHandle
));
109 gfh
->id
= fileno(fh
);
111 QTAILQ_INSERT_TAIL(&guest_file_state
.filehandles
, gfh
, next
);
114 static GuestFileHandle
*guest_file_handle_find(int64_t id
)
116 GuestFileHandle
*gfh
;
118 QTAILQ_FOREACH(gfh
, &guest_file_state
.filehandles
, next
)
128 int64_t qmp_guest_file_open(const char *path
, bool has_mode
, const char *mode
, Error
**err
)
137 slog("guest-file-open called, filepath: %s, mode: %s", path
, mode
);
138 fh
= fopen(path
, mode
);
140 error_set(err
, QERR_OPEN_FILE_FAILED
, path
);
144 /* set fd non-blocking to avoid common use cases (like reading from a
145 * named pipe) from hanging the agent
148 ret
= fcntl(fd
, F_GETFL
);
149 ret
= fcntl(fd
, F_SETFL
, ret
| O_NONBLOCK
);
151 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fcntl() failed");
156 guest_file_handle_add(fh
);
157 slog("guest-file-open, handle: %d", fd
);
161 void qmp_guest_file_close(int64_t handle
, Error
**err
)
163 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
166 slog("guest-file-close called, handle: %ld", handle
);
168 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
172 ret
= fclose(gfh
->fh
);
174 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fclose() failed");
178 QTAILQ_REMOVE(&guest_file_state
.filehandles
, gfh
, next
);
182 struct GuestFileRead
*qmp_guest_file_read(int64_t handle
, bool has_count
,
183 int64_t count
, Error
**err
)
185 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
186 GuestFileRead
*read_data
= NULL
;
192 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
197 count
= QGA_READ_COUNT_DEFAULT
;
198 } else if (count
< 0) {
199 error_set(err
, QERR_INVALID_PARAMETER
, "count");
204 buf
= g_malloc0(count
+1);
205 read_count
= fread(buf
, 1, count
, fh
);
207 slog("guest-file-read failed, handle: %ld", handle
);
208 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fread() failed");
211 read_data
= g_malloc0(sizeof(GuestFileRead
));
212 read_data
->count
= read_count
;
213 read_data
->eof
= feof(fh
);
215 read_data
->buf_b64
= g_base64_encode(buf
, read_count
);
224 GuestFileWrite
*qmp_guest_file_write(int64_t handle
, const char *buf_b64
,
225 bool has_count
, int64_t count
, Error
**err
)
227 GuestFileWrite
*write_data
= NULL
;
231 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
235 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
240 buf
= g_base64_decode(buf_b64
, &buf_len
);
244 } else if (count
< 0 || count
> buf_len
) {
246 error_set(err
, QERR_INVALID_PARAMETER
, "count");
250 write_count
= fwrite(buf
, 1, count
, fh
);
252 slog("guest-file-write failed, handle: %ld", handle
);
253 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fwrite() error");
255 write_data
= g_malloc0(sizeof(GuestFileWrite
));
256 write_data
->count
= write_count
;
257 write_data
->eof
= feof(fh
);
265 struct GuestFileSeek
*qmp_guest_file_seek(int64_t handle
, int64_t offset
,
266 int64_t whence
, Error
**err
)
268 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
269 GuestFileSeek
*seek_data
= NULL
;
274 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
279 ret
= fseek(fh
, offset
, whence
);
281 error_set(err
, QERR_QGA_COMMAND_FAILED
, strerror(errno
));
283 seek_data
= g_malloc0(sizeof(GuestFileRead
));
284 seek_data
->position
= ftell(fh
);
285 seek_data
->eof
= feof(fh
);
292 void qmp_guest_file_flush(int64_t handle
, Error
**err
)
294 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
299 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
306 error_set(err
, QERR_QGA_COMMAND_FAILED
, strerror(errno
));
310 static void guest_file_init(void)
312 QTAILQ_INIT(&guest_file_state
.filehandles
);
315 /* linux-specific implementations. avoid this if at all possible. */
316 #if defined(__linux__)
318 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
319 typedef struct FsMount
{
322 QTAILQ_ENTRY(FsMount
) next
;
325 typedef QTAILQ_HEAD(, FsMount
) FsMountList
;
327 static void free_fs_mount_list(FsMountList
*mounts
)
329 FsMount
*mount
, *temp
;
335 QTAILQ_FOREACH_SAFE(mount
, mounts
, next
, temp
) {
336 QTAILQ_REMOVE(mounts
, mount
, next
);
337 g_free(mount
->dirname
);
338 g_free(mount
->devtype
);
344 * Walk the mount table and build a list of local file systems
346 static int build_fs_mount_list(FsMountList
*mounts
)
350 char const *mtab
= "/proc/self/mounts";
353 fp
= setmntent(mtab
, "r");
355 g_warning("fsfreeze: unable to read mtab");
359 while ((ment
= getmntent(fp
))) {
361 * An entry which device name doesn't start with a '/' is
362 * either a dummy file system or a network file system.
363 * Add special handling for smbfs and cifs as is done by
366 if ((ment
->mnt_fsname
[0] != '/') ||
367 (strcmp(ment
->mnt_type
, "smbfs") == 0) ||
368 (strcmp(ment
->mnt_type
, "cifs") == 0)) {
372 mount
= g_malloc0(sizeof(FsMount
));
373 mount
->dirname
= g_strdup(ment
->mnt_dir
);
374 mount
->devtype
= g_strdup(ment
->mnt_type
);
376 QTAILQ_INSERT_TAIL(mounts
, mount
, next
);
385 #if defined(CONFIG_FSFREEZE)
388 * Return status of freeze/thaw
390 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
392 if (ga_is_frozen(ga_state
)) {
393 return GUEST_FSFREEZE_STATUS_FROZEN
;
396 return GUEST_FSFREEZE_STATUS_THAWED
;
400 * Walk list of mounted file systems in the guest, and freeze the ones which
401 * are real local file systems.
403 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
407 struct FsMount
*mount
;
411 slog("guest-fsfreeze called");
413 QTAILQ_INIT(&mounts
);
414 ret
= build_fs_mount_list(&mounts
);
419 /* cannot risk guest agent blocking itself on a write in this state */
420 ga_set_frozen(ga_state
);
422 QTAILQ_FOREACH(mount
, &mounts
, next
) {
423 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
425 sprintf(err_msg
, "failed to open %s, %s", mount
->dirname
,
427 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
431 /* we try to cull filesytems we know won't work in advance, but other
432 * filesytems may not implement fsfreeze for less obvious reasons.
433 * these will report EOPNOTSUPP. we simply ignore these when tallying
434 * the number of frozen filesystems.
436 * any other error means a failure to freeze a filesystem we
437 * expect to be freezable, so return an error in those cases
438 * and return system to thawed state.
440 ret
= ioctl(fd
, FIFREEZE
);
442 if (errno
!= EOPNOTSUPP
) {
443 sprintf(err_msg
, "failed to freeze %s, %s",
444 mount
->dirname
, strerror(errno
));
445 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
455 free_fs_mount_list(&mounts
);
459 free_fs_mount_list(&mounts
);
460 qmp_guest_fsfreeze_thaw(NULL
);
465 * Walk list of frozen file systems in the guest, and thaw them.
467 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
472 int fd
, i
= 0, logged
;
474 QTAILQ_INIT(&mounts
);
475 ret
= build_fs_mount_list(&mounts
);
477 error_set(err
, QERR_QGA_COMMAND_FAILED
,
478 "failed to enumerate filesystems");
482 QTAILQ_FOREACH(mount
, &mounts
, next
) {
484 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
488 /* we have no way of knowing whether a filesystem was actually unfrozen
489 * as a result of a successful call to FITHAW, only that if an error
490 * was returned the filesystem was *not* unfrozen by that particular
493 * since multiple preceding FIFREEZEs require multiple calls to FITHAW
494 * to unfreeze, continuing issuing FITHAW until an error is returned,
495 * in which case either the filesystem is in an unfreezable state, or,
496 * more likely, it was thawed previously (and remains so afterward).
498 * also, since the most recent successful call is the one that did
499 * the actual unfreeze, we can use this to provide an accurate count
500 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
501 * may * be useful for determining whether a filesystem was unfrozen
502 * during the freeze/thaw phase by a process other than qemu-ga.
505 ret
= ioctl(fd
, FITHAW
);
506 if (ret
== 0 && !logged
) {
514 ga_unset_frozen(ga_state
);
515 free_fs_mount_list(&mounts
);
519 static void guest_fsfreeze_cleanup(void)
524 if (ga_is_frozen(ga_state
) == GUEST_FSFREEZE_STATUS_FROZEN
) {
525 ret
= qmp_guest_fsfreeze_thaw(&err
);
526 if (ret
< 0 || err
) {
527 slog("failed to clean up frozen filesystems");
531 #endif /* CONFIG_FSFREEZE */
533 #if defined(CONFIG_FSTRIM)
535 * Walk list of mounted file systems in the guest, and trim them.
537 void qmp_guest_fstrim(bool has_minimum
, int64_t minimum
, Error
**err
)
541 struct FsMount
*mount
;
544 struct fstrim_range r
= {
547 .minlen
= has_minimum
? minimum
: 0,
550 slog("guest-fstrim called");
552 QTAILQ_INIT(&mounts
);
553 ret
= build_fs_mount_list(&mounts
);
558 QTAILQ_FOREACH(mount
, &mounts
, next
) {
559 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
561 sprintf(err_msg
, "failed to open %s, %s", mount
->dirname
,
563 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
567 /* We try to cull filesytems we know won't work in advance, but other
568 * filesytems may not implement fstrim for less obvious reasons. These
569 * will report EOPNOTSUPP; we simply ignore these errors. Any other
570 * error means an unexpected error, so return it in those cases. In
571 * some other cases ENOTTY will be reported (e.g. CD-ROMs).
573 ret
= ioctl(fd
, FITRIM
, &r
);
575 if (errno
!= ENOTTY
&& errno
!= EOPNOTSUPP
) {
576 sprintf(err_msg
, "failed to trim %s, %s",
577 mount
->dirname
, strerror(errno
));
578 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
587 free_fs_mount_list(&mounts
);
589 #endif /* CONFIG_FSTRIM */
592 #define LINUX_SYS_STATE_FILE "/sys/power/state"
593 #define SUSPEND_SUPPORTED 0
594 #define SUSPEND_NOT_SUPPORTED 1
596 static void bios_supports_mode(const char *pmutils_bin
, const char *pmutils_arg
,
597 const char *sysfile_str
, Error
**err
)
603 pmutils_path
= g_find_program_in_path(pmutils_bin
);
607 char buf
[32]; /* hopefully big enough */
612 reopen_fd_to_null(0);
613 reopen_fd_to_null(1);
614 reopen_fd_to_null(2);
617 execle(pmutils_path
, pmutils_bin
, pmutils_arg
, NULL
, environ
);
621 * If we get here either pm-utils is not installed or execle() has
622 * failed. Let's try the manual method if the caller wants it.
626 _exit(SUSPEND_NOT_SUPPORTED
);
629 fd
= open(LINUX_SYS_STATE_FILE
, O_RDONLY
);
631 _exit(SUSPEND_NOT_SUPPORTED
);
634 ret
= read(fd
, buf
, sizeof(buf
)-1);
636 _exit(SUSPEND_NOT_SUPPORTED
);
640 if (strstr(buf
, sysfile_str
)) {
641 _exit(SUSPEND_SUPPORTED
);
644 _exit(SUSPEND_NOT_SUPPORTED
);
647 g_free(pmutils_path
);
654 rpid
= waitpid(pid
, &status
, 0);
655 } while (rpid
== -1 && errno
== EINTR
);
656 if (rpid
== pid
&& WIFEXITED(status
)) {
657 switch (WEXITSTATUS(status
)) {
658 case SUSPEND_SUPPORTED
:
660 case SUSPEND_NOT_SUPPORTED
:
661 error_set(err
, QERR_UNSUPPORTED
);
669 error_set(err
, QERR_UNDEFINED_ERROR
);
672 static void guest_suspend(const char *pmutils_bin
, const char *sysfile_str
,
679 pmutils_path
= g_find_program_in_path(pmutils_bin
);
687 reopen_fd_to_null(0);
688 reopen_fd_to_null(1);
689 reopen_fd_to_null(2);
692 execle(pmutils_path
, pmutils_bin
, NULL
, environ
);
696 * If we get here either pm-utils is not installed or execle() has
697 * failed. Let's try the manual method if the caller wants it.
704 fd
= open(LINUX_SYS_STATE_FILE
, O_WRONLY
);
709 if (write(fd
, sysfile_str
, strlen(sysfile_str
)) < 0) {
716 g_free(pmutils_path
);
723 rpid
= waitpid(pid
, &status
, 0);
724 } while (rpid
== -1 && errno
== EINTR
);
725 if (rpid
== pid
&& WIFEXITED(status
) && !WEXITSTATUS(status
)) {
730 error_set(err
, QERR_UNDEFINED_ERROR
);
733 void qmp_guest_suspend_disk(Error
**err
)
735 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err
);
736 if (error_is_set(err
)) {
740 guest_suspend("pm-hibernate", "disk", err
);
743 void qmp_guest_suspend_ram(Error
**err
)
745 bios_supports_mode("pm-is-supported", "--suspend", "mem", err
);
746 if (error_is_set(err
)) {
750 guest_suspend("pm-suspend", "mem", err
);
753 void qmp_guest_suspend_hybrid(Error
**err
)
755 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL
, err
);
756 if (error_is_set(err
)) {
760 guest_suspend("pm-suspend-hybrid", NULL
, err
);
763 static GuestNetworkInterfaceList
*
764 guest_find_interface(GuestNetworkInterfaceList
*head
,
767 for (; head
; head
= head
->next
) {
768 if (strcmp(head
->value
->name
, name
) == 0) {
777 * Build information about guest interfaces
779 GuestNetworkInterfaceList
*qmp_guest_network_get_interfaces(Error
**errp
)
781 GuestNetworkInterfaceList
*head
= NULL
, *cur_item
= NULL
;
782 struct ifaddrs
*ifap
, *ifa
;
785 if (getifaddrs(&ifap
) < 0) {
786 snprintf(err_msg
, sizeof(err_msg
),
787 "getifaddrs failed: %s", strerror(errno
));
788 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
792 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
793 GuestNetworkInterfaceList
*info
;
794 GuestIpAddressList
**address_list
= NULL
, *address_item
= NULL
;
795 char addr4
[INET_ADDRSTRLEN
];
796 char addr6
[INET6_ADDRSTRLEN
];
799 unsigned char *mac_addr
;
802 g_debug("Processing %s interface", ifa
->ifa_name
);
804 info
= guest_find_interface(head
, ifa
->ifa_name
);
807 info
= g_malloc0(sizeof(*info
));
808 info
->value
= g_malloc0(sizeof(*info
->value
));
809 info
->value
->name
= g_strdup(ifa
->ifa_name
);
812 head
= cur_item
= info
;
814 cur_item
->next
= info
;
819 if (!info
->value
->has_hardware_address
&&
820 ifa
->ifa_flags
& SIOCGIFHWADDR
) {
821 /* we haven't obtained HW address yet */
822 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
824 snprintf(err_msg
, sizeof(err_msg
),
825 "failed to create socket: %s", strerror(errno
));
826 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
830 memset(&ifr
, 0, sizeof(ifr
));
831 strncpy(ifr
.ifr_name
, info
->value
->name
, IF_NAMESIZE
);
832 if (ioctl(sock
, SIOCGIFHWADDR
, &ifr
) == -1) {
833 snprintf(err_msg
, sizeof(err_msg
),
834 "failed to get MAC address of %s: %s",
837 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
841 mac_addr
= (unsigned char *) &ifr
.ifr_hwaddr
.sa_data
;
843 if (asprintf(&info
->value
->hardware_address
,
844 "%02x:%02x:%02x:%02x:%02x:%02x",
845 (int) mac_addr
[0], (int) mac_addr
[1],
846 (int) mac_addr
[2], (int) mac_addr
[3],
847 (int) mac_addr
[4], (int) mac_addr
[5]) == -1) {
848 snprintf(err_msg
, sizeof(err_msg
),
849 "failed to format MAC: %s", strerror(errno
));
850 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
854 info
->value
->has_hardware_address
= true;
859 ifa
->ifa_addr
->sa_family
== AF_INET
) {
860 /* interface with IPv4 address */
861 address_item
= g_malloc0(sizeof(*address_item
));
862 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
863 p
= &((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
;
864 if (!inet_ntop(AF_INET
, p
, addr4
, sizeof(addr4
))) {
865 snprintf(err_msg
, sizeof(err_msg
),
866 "inet_ntop failed : %s", strerror(errno
));
867 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
871 address_item
->value
->ip_address
= g_strdup(addr4
);
872 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV4
;
874 if (ifa
->ifa_netmask
) {
875 /* Count the number of set bits in netmask.
876 * This is safe as '1' and '0' cannot be shuffled in netmask. */
877 p
= &((struct sockaddr_in
*)ifa
->ifa_netmask
)->sin_addr
;
878 address_item
->value
->prefix
= ctpop32(((uint32_t *) p
)[0]);
880 } else if (ifa
->ifa_addr
&&
881 ifa
->ifa_addr
->sa_family
== AF_INET6
) {
882 /* interface with IPv6 address */
883 address_item
= g_malloc0(sizeof(*address_item
));
884 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
885 p
= &((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_addr
;
886 if (!inet_ntop(AF_INET6
, p
, addr6
, sizeof(addr6
))) {
887 snprintf(err_msg
, sizeof(err_msg
),
888 "inet_ntop failed : %s", strerror(errno
));
889 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
893 address_item
->value
->ip_address
= g_strdup(addr6
);
894 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV6
;
896 if (ifa
->ifa_netmask
) {
897 /* Count the number of set bits in netmask.
898 * This is safe as '1' and '0' cannot be shuffled in netmask. */
899 p
= &((struct sockaddr_in6
*)ifa
->ifa_netmask
)->sin6_addr
;
900 address_item
->value
->prefix
=
901 ctpop32(((uint32_t *) p
)[0]) +
902 ctpop32(((uint32_t *) p
)[1]) +
903 ctpop32(((uint32_t *) p
)[2]) +
904 ctpop32(((uint32_t *) p
)[3]);
912 address_list
= &info
->value
->ip_addresses
;
914 while (*address_list
&& (*address_list
)->next
) {
915 address_list
= &(*address_list
)->next
;
918 if (!*address_list
) {
919 *address_list
= address_item
;
921 (*address_list
)->next
= address_item
;
924 info
->value
->has_ip_addresses
= true;
934 qapi_free_GuestNetworkInterfaceList(head
);
938 #else /* defined(__linux__) */
940 void qmp_guest_suspend_disk(Error
**err
)
942 error_set(err
, QERR_UNSUPPORTED
);
945 void qmp_guest_suspend_ram(Error
**err
)
947 error_set(err
, QERR_UNSUPPORTED
);
950 void qmp_guest_suspend_hybrid(Error
**err
)
952 error_set(err
, QERR_UNSUPPORTED
);
955 GuestNetworkInterfaceList
*qmp_guest_network_get_interfaces(Error
**errp
)
957 error_set(errp
, QERR_UNSUPPORTED
);
963 #if !defined(CONFIG_FSFREEZE)
965 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
967 error_set(err
, QERR_UNSUPPORTED
);
972 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
974 error_set(err
, QERR_UNSUPPORTED
);
979 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
981 error_set(err
, QERR_UNSUPPORTED
);
985 #endif /* CONFIG_FSFREEZE */
987 #if !defined(CONFIG_FSTRIM)
988 void qmp_guest_fstrim(bool has_minimum
, int64_t minimum
, Error
**err
)
990 error_set(err
, QERR_UNSUPPORTED
);
996 /* register init/cleanup routines for stateful command groups */
997 void ga_command_state_init(GAState
*s
, GACommandState
*cs
)
999 #if defined(CONFIG_FSFREEZE)
1000 ga_command_state_add(cs
, NULL
, guest_fsfreeze_cleanup
);
1002 ga_command_state_add(cs
, guest_file_init
, NULL
);