commands-bsd.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * QEMU Guest Agent BSD-specific command implementations
  3. *
  4. * Copyright (c) Virtuozzo International GmbH.
  5. *
  6. * Authors:
  7. * Alexander Ivanov <alexander.ivanov@virtuozzo.com>
  8. *
  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.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qga-qapi-commands.h"
  14. #include "qapi/qmp/qerror.h"
  15. #include "qapi/error.h"
  16. #include "qemu/queue.h"
  17. #include "commands-common.h"
  18. #include <sys/ioctl.h>
  19. #include <sys/param.h>
  20. #include <sys/ucred.h>
  21. #include <sys/mount.h>
  22. #include <paths.h>
  23. #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
  24. bool build_fs_mount_list(FsMountList *mounts, Error **errp)
  25. {
  26. FsMount *mount;
  27. struct statfs *mntbuf, *mntp;
  28. struct stat statbuf;
  29. int i, count, ret;
  30. count = getmntinfo(&mntbuf, MNT_NOWAIT);
  31. if (count == 0) {
  32. error_setg_errno(errp, errno, "getmntinfo failed");
  33. return false;
  34. }
  35. for (i = 0; i < count; i++) {
  36. mntp = &mntbuf[i];
  37. ret = stat(mntp->f_mntonname, &statbuf);
  38. if (ret != 0) {
  39. error_setg_errno(errp, errno, "stat failed on %s",
  40. mntp->f_mntonname);
  41. return false;
  42. }
  43. mount = g_new0(FsMount, 1);
  44. mount->dirname = g_strdup(mntp->f_mntonname);
  45. mount->devtype = g_strdup(mntp->f_fstypename);
  46. mount->devmajor = major(mount->dev);
  47. mount->devminor = minor(mount->dev);
  48. mount->fsid = mntp->f_fsid;
  49. mount->dev = statbuf.st_dev;
  50. QTAILQ_INSERT_TAIL(mounts, mount, next);
  51. }
  52. return true;
  53. }
  54. #endif /* CONFIG_FSFREEZE || CONFIG_FSTRIM */
  55. #if defined(CONFIG_FSFREEZE)
  56. static int ufssuspend_fd = -1;
  57. static int ufssuspend_cnt;
  58. int64_t qmp_guest_fsfreeze_do_freeze_list(bool has_mountpoints,
  59. strList *mountpoints,
  60. FsMountList mounts,
  61. Error **errp)
  62. {
  63. int ret;
  64. strList *list;
  65. struct FsMount *mount;
  66. if (ufssuspend_fd != -1) {
  67. error_setg(errp, "filesystems have already frozen");
  68. return -1;
  69. }
  70. ufssuspend_cnt = 0;
  71. ufssuspend_fd = qemu_open(_PATH_UFSSUSPEND, O_RDWR, errp);
  72. if (ufssuspend_fd == -1) {
  73. return -1;
  74. }
  75. QTAILQ_FOREACH_REVERSE(mount, &mounts, next) {
  76. /*
  77. * To issue fsfreeze in the reverse order of mounts, check if the
  78. * mount is listed in the list here
  79. */
  80. if (has_mountpoints) {
  81. for (list = mountpoints; list; list = list->next) {
  82. if (g_str_equal(list->value, mount->dirname)) {
  83. break;
  84. }
  85. }
  86. if (!list) {
  87. continue;
  88. }
  89. }
  90. /* Only UFS supports suspend */
  91. if (!g_str_equal(mount->devtype, "ufs")) {
  92. continue;
  93. }
  94. ret = ioctl(ufssuspend_fd, UFSSUSPEND, &mount->fsid);
  95. if (ret == -1) {
  96. /*
  97. * ioctl returns EBUSY for all the FS except the first one
  98. * that was suspended
  99. */
  100. if (errno == EBUSY) {
  101. continue;
  102. }
  103. error_setg_errno(errp, errno, "failed to freeze %s",
  104. mount->dirname);
  105. goto error;
  106. }
  107. ufssuspend_cnt++;
  108. }
  109. return ufssuspend_cnt;
  110. error:
  111. close(ufssuspend_fd);
  112. ufssuspend_fd = -1;
  113. return -1;
  114. }
  115. /*
  116. * We don't need to call UFSRESUME ioctl because all the frozen FS
  117. * are thawed on /dev/ufssuspend closing.
  118. */
  119. int qmp_guest_fsfreeze_do_thaw(Error **errp)
  120. {
  121. int ret = ufssuspend_cnt;
  122. ufssuspend_cnt = 0;
  123. if (ufssuspend_fd != -1) {
  124. close(ufssuspend_fd);
  125. ufssuspend_fd = -1;
  126. }
  127. return ret;
  128. }
  129. GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
  130. {
  131. error_setg(errp, QERR_UNSUPPORTED);
  132. return NULL;
  133. }
  134. GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
  135. {
  136. error_setg(errp, QERR_UNSUPPORTED);
  137. return NULL;
  138. }
  139. GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
  140. {
  141. error_setg(errp, QERR_UNSUPPORTED);
  142. return NULL;
  143. }
  144. GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
  145. {
  146. error_setg(errp, QERR_UNSUPPORTED);
  147. return NULL;
  148. }
  149. #endif /* CONFIG_FSFREEZE */
  150. #ifdef HAVE_GETIFADDRS
  151. /*
  152. * Fill "buf" with MAC address by ifaddrs. Pointer buf must point to a
  153. * buffer with ETHER_ADDR_LEN length at least.
  154. *
  155. * Returns false in case of an error, otherwise true. "obtained" arguument
  156. * is true if a MAC address was obtained successful, otherwise false.
  157. */
  158. bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned char *buf,
  159. bool *obtained, Error **errp)
  160. {
  161. *obtained = false;
  162. return true;
  163. }
  164. #endif /* HAVE_GETIFADDRS */