2 * QEMU Guest Agent BSD-specific command implementations
4 * Copyright (c) Virtuozzo International GmbH.
7 * Alexander Ivanov <alexander.ivanov@virtuozzo.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qga-qapi-commands.h"
15 #include "qapi/qmp/qerror.h"
16 #include "qapi/error.h"
17 #include "qemu/queue.h"
18 #include "commands-common.h"
19 #include <sys/ioctl.h>
20 #include <sys/param.h>
21 #include <sys/ucred.h>
22 #include <sys/mount.h>
23 #include <net/if_dl.h>
24 #if defined(__NetBSD__) || defined(__OpenBSD__)
25 #include <net/if_arp.h>
26 #include <netinet/if_ether.h>
28 #include <net/ethernet.h>
32 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
33 bool build_fs_mount_list(FsMountList
*mounts
, Error
**errp
)
36 struct statfs
*mntbuf
, *mntp
;
40 count
= getmntinfo(&mntbuf
, MNT_NOWAIT
);
42 error_setg_errno(errp
, errno
, "getmntinfo failed");
46 for (i
= 0; i
< count
; i
++) {
48 ret
= stat(mntp
->f_mntonname
, &statbuf
);
50 error_setg_errno(errp
, errno
, "stat failed on %s",
55 mount
= g_new0(FsMount
, 1);
57 mount
->dirname
= g_strdup(mntp
->f_mntonname
);
58 mount
->devtype
= g_strdup(mntp
->f_fstypename
);
59 mount
->devmajor
= major(mount
->dev
);
60 mount
->devminor
= minor(mount
->dev
);
61 mount
->fsid
= mntp
->f_fsid
;
62 mount
->dev
= statbuf
.st_dev
;
64 QTAILQ_INSERT_TAIL(mounts
, mount
, next
);
68 #endif /* CONFIG_FSFREEZE || CONFIG_FSTRIM */
70 #if defined(CONFIG_FSFREEZE)
71 static int ufssuspend_fd
= -1;
72 static int ufssuspend_cnt
;
74 int64_t qmp_guest_fsfreeze_do_freeze_list(bool has_mountpoints
,
81 struct FsMount
*mount
;
83 if (ufssuspend_fd
!= -1) {
84 error_setg(errp
, "filesystems have already frozen");
89 ufssuspend_fd
= qemu_open(_PATH_UFSSUSPEND
, O_RDWR
, errp
);
90 if (ufssuspend_fd
== -1) {
94 QTAILQ_FOREACH_REVERSE(mount
, &mounts
, next
) {
96 * To issue fsfreeze in the reverse order of mounts, check if the
97 * mount is listed in the list here
99 if (has_mountpoints
) {
100 for (list
= mountpoints
; list
; list
= list
->next
) {
101 if (g_str_equal(list
->value
, mount
->dirname
)) {
110 /* Only UFS supports suspend */
111 if (!g_str_equal(mount
->devtype
, "ufs")) {
115 ret
= ioctl(ufssuspend_fd
, UFSSUSPEND
, &mount
->fsid
);
118 * ioctl returns EBUSY for all the FS except the first one
121 if (errno
== EBUSY
) {
124 error_setg_errno(errp
, errno
, "failed to freeze %s",
130 return ufssuspend_cnt
;
132 close(ufssuspend_fd
);
139 * We don't need to call UFSRESUME ioctl because all the frozen FS
140 * are thawed on /dev/ufssuspend closing.
142 int qmp_guest_fsfreeze_do_thaw(Error
**errp
)
144 int ret
= ufssuspend_cnt
;
146 if (ufssuspend_fd
!= -1) {
147 close(ufssuspend_fd
);
153 GuestFilesystemInfoList
*qmp_guest_get_fsinfo(Error
**errp
)
155 error_setg(errp
, QERR_UNSUPPORTED
);
159 GuestDiskInfoList
*qmp_guest_get_disks(Error
**errp
)
161 error_setg(errp
, QERR_UNSUPPORTED
);
165 GuestDiskStatsInfoList
*qmp_guest_get_diskstats(Error
**errp
)
167 error_setg(errp
, QERR_UNSUPPORTED
);
171 GuestCpuStatsList
*qmp_guest_get_cpustats(Error
**errp
)
173 error_setg(errp
, QERR_UNSUPPORTED
);
176 #endif /* CONFIG_FSFREEZE */
178 #ifdef HAVE_GETIFADDRS
180 * Fill "buf" with MAC address by ifaddrs. Pointer buf must point to a
181 * buffer with ETHER_ADDR_LEN length at least.
183 * Returns false in case of an error, otherwise true. "obtained" arguument
184 * is true if a MAC address was obtained successful, otherwise false.
186 bool guest_get_hw_addr(struct ifaddrs
*ifa
, unsigned char *buf
,
187 bool *obtained
, Error
**errp
)
189 struct sockaddr_dl
*sdp
;
193 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
) {
194 /* We can get HW address only for AF_LINK family. */
195 g_debug("failed to get MAC address of %s", ifa
->ifa_name
);
199 sdp
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
200 memcpy(buf
, sdp
->sdl_data
+ sdp
->sdl_nlen
, ETHER_ADDR_LEN
);
205 #endif /* HAVE_GETIFADDRS */