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 #include <net/ethernet.h>
27 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
28 bool build_fs_mount_list(FsMountList
*mounts
, Error
**errp
)
31 struct statfs
*mntbuf
, *mntp
;
35 count
= getmntinfo(&mntbuf
, MNT_NOWAIT
);
37 error_setg_errno(errp
, errno
, "getmntinfo failed");
41 for (i
= 0; i
< count
; i
++) {
43 ret
= stat(mntp
->f_mntonname
, &statbuf
);
45 error_setg_errno(errp
, errno
, "stat failed on %s",
50 mount
= g_new0(FsMount
, 1);
52 mount
->dirname
= g_strdup(mntp
->f_mntonname
);
53 mount
->devtype
= g_strdup(mntp
->f_fstypename
);
54 mount
->devmajor
= major(mount
->dev
);
55 mount
->devminor
= minor(mount
->dev
);
56 mount
->fsid
= mntp
->f_fsid
;
57 mount
->dev
= statbuf
.st_dev
;
59 QTAILQ_INSERT_TAIL(mounts
, mount
, next
);
63 #endif /* CONFIG_FSFREEZE || CONFIG_FSTRIM */
65 #if defined(CONFIG_FSFREEZE)
66 static int ufssuspend_fd
= -1;
67 static int ufssuspend_cnt
;
69 int64_t qmp_guest_fsfreeze_do_freeze_list(bool has_mountpoints
,
76 struct FsMount
*mount
;
78 if (ufssuspend_fd
!= -1) {
79 error_setg(errp
, "filesystems have already frozen");
84 ufssuspend_fd
= qemu_open(_PATH_UFSSUSPEND
, O_RDWR
, errp
);
85 if (ufssuspend_fd
== -1) {
89 QTAILQ_FOREACH_REVERSE(mount
, &mounts
, next
) {
91 * To issue fsfreeze in the reverse order of mounts, check if the
92 * mount is listed in the list here
94 if (has_mountpoints
) {
95 for (list
= mountpoints
; list
; list
= list
->next
) {
96 if (g_str_equal(list
->value
, mount
->dirname
)) {
105 /* Only UFS supports suspend */
106 if (!g_str_equal(mount
->devtype
, "ufs")) {
110 ret
= ioctl(ufssuspend_fd
, UFSSUSPEND
, &mount
->fsid
);
113 * ioctl returns EBUSY for all the FS except the first one
116 if (errno
== EBUSY
) {
119 error_setg_errno(errp
, errno
, "failed to freeze %s",
125 return ufssuspend_cnt
;
127 close(ufssuspend_fd
);
134 * We don't need to call UFSRESUME ioctl because all the frozen FS
135 * are thawed on /dev/ufssuspend closing.
137 int qmp_guest_fsfreeze_do_thaw(Error
**errp
)
139 int ret
= ufssuspend_cnt
;
141 if (ufssuspend_fd
!= -1) {
142 close(ufssuspend_fd
);
148 GuestFilesystemInfoList
*qmp_guest_get_fsinfo(Error
**errp
)
150 error_setg(errp
, QERR_UNSUPPORTED
);
154 GuestDiskInfoList
*qmp_guest_get_disks(Error
**errp
)
156 error_setg(errp
, QERR_UNSUPPORTED
);
160 GuestDiskStatsInfoList
*qmp_guest_get_diskstats(Error
**errp
)
162 error_setg(errp
, QERR_UNSUPPORTED
);
166 GuestCpuStatsList
*qmp_guest_get_cpustats(Error
**errp
)
168 error_setg(errp
, QERR_UNSUPPORTED
);
171 #endif /* CONFIG_FSFREEZE */
173 #ifdef HAVE_GETIFADDRS
175 * Fill "buf" with MAC address by ifaddrs. Pointer buf must point to a
176 * buffer with ETHER_ADDR_LEN length at least.
178 * Returns false in case of an error, otherwise true. "obtained" arguument
179 * is true if a MAC address was obtained successful, otherwise false.
181 bool guest_get_hw_addr(struct ifaddrs
*ifa
, unsigned char *buf
,
182 bool *obtained
, Error
**errp
)
184 struct sockaddr_dl
*sdp
;
188 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
) {
189 /* We can get HW address only for AF_LINK family. */
190 g_debug("failed to get MAC address of %s", ifa
->ifa_name
);
194 sdp
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
195 memcpy(buf
, sdp
->sdl_data
+ sdp
->sdl_nlen
, ETHER_ADDR_LEN
);
200 #endif /* HAVE_GETIFADDRS */