commands-linux.c 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. /*
  2. * QEMU Guest Agent Linux-specific command implementations
  3. *
  4. * Copyright IBM Corp. 2011
  5. *
  6. * Authors:
  7. * Michael Roth <mdroth@linux.vnet.ibm.com>
  8. * Michal Privoznik <mprivozn@redhat.com>
  9. *
  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. #include "qemu/osdep.h"
  14. #include "qapi/error.h"
  15. #include "qga-qapi-commands.h"
  16. #include "qapi/error.h"
  17. #include "commands-common.h"
  18. #include "cutils.h"
  19. #include <mntent.h>
  20. #include <sys/ioctl.h>
  21. #include <mntent.h>
  22. #include <linux/nvme_ioctl.h>
  23. #include "block/nvme.h"
  24. #ifdef CONFIG_LIBUDEV
  25. #include <libudev.h>
  26. #endif
  27. #ifdef HAVE_GETIFADDRS
  28. #include <net/if.h>
  29. #endif
  30. #include <sys/statvfs.h>
  31. #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
  32. static int dev_major_minor(const char *devpath,
  33. unsigned int *devmajor, unsigned int *devminor)
  34. {
  35. struct stat st;
  36. *devmajor = 0;
  37. *devminor = 0;
  38. if (stat(devpath, &st) < 0) {
  39. slog("failed to stat device file '%s': %s", devpath, strerror(errno));
  40. return -1;
  41. }
  42. if (S_ISDIR(st.st_mode)) {
  43. /* It is bind mount */
  44. return -2;
  45. }
  46. if (S_ISBLK(st.st_mode)) {
  47. *devmajor = major(st.st_rdev);
  48. *devminor = minor(st.st_rdev);
  49. return 0;
  50. }
  51. return -1;
  52. }
  53. static bool build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp)
  54. {
  55. struct mntent *ment;
  56. FsMount *mount;
  57. char const *mtab = "/proc/self/mounts";
  58. FILE *fp;
  59. unsigned int devmajor, devminor;
  60. fp = setmntent(mtab, "r");
  61. if (!fp) {
  62. error_setg(errp, "failed to open mtab file: '%s'", mtab);
  63. return false;
  64. }
  65. while ((ment = getmntent(fp))) {
  66. /*
  67. * An entry which device name doesn't start with a '/' is
  68. * either a dummy file system or a network file system.
  69. * Add special handling for smbfs and cifs as is done by
  70. * coreutils as well.
  71. */
  72. if ((ment->mnt_fsname[0] != '/') ||
  73. (strcmp(ment->mnt_type, "smbfs") == 0) ||
  74. (strcmp(ment->mnt_type, "cifs") == 0)) {
  75. continue;
  76. }
  77. if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) {
  78. /* Skip bind mounts */
  79. continue;
  80. }
  81. mount = g_new0(FsMount, 1);
  82. mount->dirname = g_strdup(ment->mnt_dir);
  83. mount->devtype = g_strdup(ment->mnt_type);
  84. mount->devmajor = devmajor;
  85. mount->devminor = devminor;
  86. QTAILQ_INSERT_TAIL(mounts, mount, next);
  87. }
  88. endmntent(fp);
  89. return true;
  90. }
  91. static void decode_mntname(char *name, int len)
  92. {
  93. int i, j = 0;
  94. for (i = 0; i <= len; i++) {
  95. if (name[i] != '\\') {
  96. name[j++] = name[i];
  97. } else if (name[i + 1] == '\\') {
  98. name[j++] = '\\';
  99. i++;
  100. } else if (name[i + 1] >= '0' && name[i + 1] <= '3' &&
  101. name[i + 2] >= '0' && name[i + 2] <= '7' &&
  102. name[i + 3] >= '0' && name[i + 3] <= '7') {
  103. name[j++] = (name[i + 1] - '0') * 64 +
  104. (name[i + 2] - '0') * 8 +
  105. (name[i + 3] - '0');
  106. i += 3;
  107. } else {
  108. name[j++] = name[i];
  109. }
  110. }
  111. }
  112. /*
  113. * Walk the mount table and build a list of local file systems
  114. */
  115. bool build_fs_mount_list(FsMountList *mounts, Error **errp)
  116. {
  117. FsMount *mount;
  118. char const *mountinfo = "/proc/self/mountinfo";
  119. FILE *fp;
  120. char *line = NULL, *dash;
  121. size_t n;
  122. char check;
  123. unsigned int devmajor, devminor;
  124. int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e;
  125. fp = fopen(mountinfo, "r");
  126. if (!fp) {
  127. return build_fs_mount_list_from_mtab(mounts, errp);
  128. }
  129. while (getline(&line, &n, fp) != -1) {
  130. ret = sscanf(line, "%*u %*u %u:%u %*s %n%*s%n%c",
  131. &devmajor, &devminor, &dir_s, &dir_e, &check);
  132. if (ret < 3) {
  133. continue;
  134. }
  135. dash = strstr(line + dir_e, " - ");
  136. if (!dash) {
  137. continue;
  138. }
  139. ret = sscanf(dash, " - %n%*s%n %n%*s%n%c",
  140. &type_s, &type_e, &dev_s, &dev_e, &check);
  141. if (ret < 1) {
  142. continue;
  143. }
  144. line[dir_e] = 0;
  145. dash[type_e] = 0;
  146. dash[dev_e] = 0;
  147. decode_mntname(line + dir_s, dir_e - dir_s);
  148. decode_mntname(dash + dev_s, dev_e - dev_s);
  149. if (devmajor == 0) {
  150. /* btrfs reports major number = 0 */
  151. if (strcmp("btrfs", dash + type_s) != 0 ||
  152. dev_major_minor(dash + dev_s, &devmajor, &devminor) < 0) {
  153. continue;
  154. }
  155. }
  156. mount = g_new0(FsMount, 1);
  157. mount->dirname = g_strdup(line + dir_s);
  158. mount->devtype = g_strdup(dash + type_s);
  159. mount->devmajor = devmajor;
  160. mount->devminor = devminor;
  161. QTAILQ_INSERT_TAIL(mounts, mount, next);
  162. }
  163. free(line);
  164. fclose(fp);
  165. return true;
  166. }
  167. #endif /* CONFIG_FSFREEZE || CONFIG_FSTRIM */
  168. #ifdef CONFIG_FSFREEZE
  169. /*
  170. * Walk list of mounted file systems in the guest, and freeze the ones which
  171. * are real local file systems.
  172. */
  173. int64_t qmp_guest_fsfreeze_do_freeze_list(bool has_mountpoints,
  174. strList *mountpoints,
  175. FsMountList mounts,
  176. Error **errp)
  177. {
  178. struct FsMount *mount;
  179. strList *list;
  180. int fd, ret, i = 0;
  181. QTAILQ_FOREACH_REVERSE(mount, &mounts, next) {
  182. /* To issue fsfreeze in the reverse order of mounts, check if the
  183. * mount is listed in the list here */
  184. if (has_mountpoints) {
  185. for (list = mountpoints; list; list = list->next) {
  186. if (strcmp(list->value, mount->dirname) == 0) {
  187. break;
  188. }
  189. }
  190. if (!list) {
  191. continue;
  192. }
  193. }
  194. fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0);
  195. if (fd == -1) {
  196. error_setg_errno(errp, errno, "failed to open %s", mount->dirname);
  197. return -1;
  198. }
  199. /* we try to cull filesystems we know won't work in advance, but other
  200. * filesystems may not implement fsfreeze for less obvious reasons.
  201. * these will report EOPNOTSUPP. we simply ignore these when tallying
  202. * the number of frozen filesystems.
  203. * if a filesystem is mounted more than once (aka bind mount) a
  204. * consecutive attempt to freeze an already frozen filesystem will
  205. * return EBUSY.
  206. *
  207. * any other error means a failure to freeze a filesystem we
  208. * expect to be freezable, so return an error in those cases
  209. * and return system to thawed state.
  210. */
  211. ret = ioctl(fd, FIFREEZE);
  212. if (ret == -1) {
  213. if (errno != EOPNOTSUPP && errno != EBUSY) {
  214. error_setg_errno(errp, errno, "failed to freeze %s",
  215. mount->dirname);
  216. close(fd);
  217. return -1;
  218. }
  219. } else {
  220. i++;
  221. }
  222. close(fd);
  223. }
  224. return i;
  225. }
  226. int qmp_guest_fsfreeze_do_thaw(Error **errp)
  227. {
  228. int ret;
  229. FsMountList mounts;
  230. FsMount *mount;
  231. int fd, i = 0, logged;
  232. Error *local_err = NULL;
  233. QTAILQ_INIT(&mounts);
  234. if (!build_fs_mount_list(&mounts, &local_err)) {
  235. error_propagate(errp, local_err);
  236. return -1;
  237. }
  238. QTAILQ_FOREACH(mount, &mounts, next) {
  239. logged = false;
  240. fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0);
  241. if (fd == -1) {
  242. continue;
  243. }
  244. /* we have no way of knowing whether a filesystem was actually unfrozen
  245. * as a result of a successful call to FITHAW, only that if an error
  246. * was returned the filesystem was *not* unfrozen by that particular
  247. * call.
  248. *
  249. * since multiple preceding FIFREEZEs require multiple calls to FITHAW
  250. * to unfreeze, continuing issuing FITHAW until an error is returned,
  251. * in which case either the filesystem is in an unfreezable state, or,
  252. * more likely, it was thawed previously (and remains so afterward).
  253. *
  254. * also, since the most recent successful call is the one that did
  255. * the actual unfreeze, we can use this to provide an accurate count
  256. * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
  257. * may * be useful for determining whether a filesystem was unfrozen
  258. * during the freeze/thaw phase by a process other than qemu-ga.
  259. */
  260. do {
  261. ret = ioctl(fd, FITHAW);
  262. if (ret == 0 && !logged) {
  263. i++;
  264. logged = true;
  265. }
  266. } while (ret == 0);
  267. close(fd);
  268. }
  269. free_fs_mount_list(&mounts);
  270. return i;
  271. }
  272. #endif /* CONFIG_FSFREEZE */
  273. #if defined(CONFIG_FSFREEZE)
  274. static char *get_pci_driver(char const *syspath, int pathlen, Error **errp)
  275. {
  276. char *path;
  277. char *dpath;
  278. char *driver = NULL;
  279. char buf[PATH_MAX];
  280. ssize_t len;
  281. path = g_strndup(syspath, pathlen);
  282. dpath = g_strdup_printf("%s/driver", path);
  283. len = readlink(dpath, buf, sizeof(buf) - 1);
  284. if (len != -1) {
  285. buf[len] = 0;
  286. driver = g_path_get_basename(buf);
  287. }
  288. g_free(dpath);
  289. g_free(path);
  290. return driver;
  291. }
  292. static int compare_uint(const void *_a, const void *_b)
  293. {
  294. unsigned int a = *(unsigned int *)_a;
  295. unsigned int b = *(unsigned int *)_b;
  296. return a < b ? -1 : a > b ? 1 : 0;
  297. }
  298. /* Walk the specified sysfs and build a sorted list of host or ata numbers */
  299. static int build_hosts(char const *syspath, char const *host, bool ata,
  300. unsigned int *hosts, int hosts_max, Error **errp)
  301. {
  302. char *path;
  303. DIR *dir;
  304. struct dirent *entry;
  305. int i = 0;
  306. path = g_strndup(syspath, host - syspath);
  307. dir = opendir(path);
  308. if (!dir) {
  309. error_setg_errno(errp, errno, "opendir(\"%s\")", path);
  310. g_free(path);
  311. return -1;
  312. }
  313. while (i < hosts_max) {
  314. entry = readdir(dir);
  315. if (!entry) {
  316. break;
  317. }
  318. if (ata && sscanf(entry->d_name, "ata%d", hosts + i) == 1) {
  319. ++i;
  320. } else if (!ata && sscanf(entry->d_name, "host%d", hosts + i) == 1) {
  321. ++i;
  322. }
  323. }
  324. qsort(hosts, i, sizeof(hosts[0]), compare_uint);
  325. g_free(path);
  326. closedir(dir);
  327. return i;
  328. }
  329. /*
  330. * Store disk device info for devices on the PCI bus.
  331. * Returns true if information has been stored, or false for failure.
  332. */
  333. static bool build_guest_fsinfo_for_pci_dev(char const *syspath,
  334. GuestDiskAddress *disk,
  335. Error **errp)
  336. {
  337. unsigned int pci[4], host, hosts[8], tgt[3];
  338. int i, nhosts = 0, pcilen;
  339. GuestPCIAddress *pciaddr = disk->pci_controller;
  340. bool has_ata = false, has_host = false, has_tgt = false;
  341. char *p, *q, *driver = NULL;
  342. bool ret = false;
  343. p = strstr(syspath, "/devices/pci");
  344. if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n",
  345. pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) {
  346. g_debug("only pci device is supported: sysfs path '%s'", syspath);
  347. return false;
  348. }
  349. p += 12 + pcilen;
  350. while (true) {
  351. driver = get_pci_driver(syspath, p - syspath, errp);
  352. if (driver && (g_str_equal(driver, "ata_piix") ||
  353. g_str_equal(driver, "sym53c8xx") ||
  354. g_str_equal(driver, "virtio-pci") ||
  355. g_str_equal(driver, "ahci") ||
  356. g_str_equal(driver, "nvme") ||
  357. g_str_equal(driver, "xhci_hcd") ||
  358. g_str_equal(driver, "ehci-pci"))) {
  359. break;
  360. }
  361. g_free(driver);
  362. if (sscanf(p, "/%x:%x:%x.%x%n",
  363. pci, pci + 1, pci + 2, pci + 3, &pcilen) == 4) {
  364. p += pcilen;
  365. continue;
  366. }
  367. g_debug("unsupported driver or sysfs path '%s'", syspath);
  368. return false;
  369. }
  370. p = strstr(syspath, "/target");
  371. if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u",
  372. tgt, tgt + 1, tgt + 2) == 3) {
  373. has_tgt = true;
  374. }
  375. p = strstr(syspath, "/ata");
  376. if (p) {
  377. q = p + 4;
  378. has_ata = true;
  379. } else {
  380. p = strstr(syspath, "/host");
  381. q = p + 5;
  382. }
  383. if (p && sscanf(q, "%u", &host) == 1) {
  384. has_host = true;
  385. nhosts = build_hosts(syspath, p, has_ata, hosts,
  386. ARRAY_SIZE(hosts), errp);
  387. if (nhosts < 0) {
  388. goto cleanup;
  389. }
  390. }
  391. pciaddr->domain = pci[0];
  392. pciaddr->bus = pci[1];
  393. pciaddr->slot = pci[2];
  394. pciaddr->function = pci[3];
  395. if (strcmp(driver, "ata_piix") == 0) {
  396. /* a host per ide bus, target*:0:<unit>:0 */
  397. if (!has_host || !has_tgt) {
  398. g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
  399. goto cleanup;
  400. }
  401. for (i = 0; i < nhosts; i++) {
  402. if (host == hosts[i]) {
  403. disk->bus_type = GUEST_DISK_BUS_TYPE_IDE;
  404. disk->bus = i;
  405. disk->unit = tgt[1];
  406. break;
  407. }
  408. }
  409. if (i >= nhosts) {
  410. g_debug("no host for '%s' (driver '%s')", syspath, driver);
  411. goto cleanup;
  412. }
  413. } else if (strcmp(driver, "sym53c8xx") == 0) {
  414. /* scsi(LSI Logic): target*:0:<unit>:0 */
  415. if (!has_tgt) {
  416. g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
  417. goto cleanup;
  418. }
  419. disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
  420. disk->unit = tgt[1];
  421. } else if (strcmp(driver, "virtio-pci") == 0) {
  422. if (has_tgt) {
  423. /* virtio-scsi: target*:0:0:<unit> */
  424. disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
  425. disk->unit = tgt[2];
  426. } else {
  427. /* virtio-blk: 1 disk per 1 device */
  428. disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO;
  429. }
  430. } else if (strcmp(driver, "ahci") == 0) {
  431. /* ahci: 1 host per 1 unit */
  432. if (!has_host || !has_tgt) {
  433. g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver);
  434. goto cleanup;
  435. }
  436. for (i = 0; i < nhosts; i++) {
  437. if (host == hosts[i]) {
  438. disk->unit = i;
  439. disk->bus_type = GUEST_DISK_BUS_TYPE_SATA;
  440. break;
  441. }
  442. }
  443. if (i >= nhosts) {
  444. g_debug("no host for '%s' (driver '%s')", syspath, driver);
  445. goto cleanup;
  446. }
  447. } else if (strcmp(driver, "nvme") == 0) {
  448. disk->bus_type = GUEST_DISK_BUS_TYPE_NVME;
  449. } else if (strcmp(driver, "ehci-pci") == 0 || strcmp(driver, "xhci_hcd") == 0) {
  450. disk->bus_type = GUEST_DISK_BUS_TYPE_USB;
  451. } else {
  452. g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath);
  453. goto cleanup;
  454. }
  455. ret = true;
  456. cleanup:
  457. g_free(driver);
  458. return ret;
  459. }
  460. /*
  461. * Store disk device info for non-PCI virtio devices (for example s390x
  462. * channel I/O devices). Returns true if information has been stored, or
  463. * false for failure.
  464. */
  465. static bool build_guest_fsinfo_for_nonpci_virtio(char const *syspath,
  466. GuestDiskAddress *disk,
  467. Error **errp)
  468. {
  469. unsigned int tgt[3];
  470. char *p;
  471. if (!strstr(syspath, "/virtio") || !strstr(syspath, "/block")) {
  472. g_debug("Unsupported virtio device '%s'", syspath);
  473. return false;
  474. }
  475. p = strstr(syspath, "/target");
  476. if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u",
  477. &tgt[0], &tgt[1], &tgt[2]) == 3) {
  478. /* virtio-scsi: target*:0:<target>:<unit> */
  479. disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI;
  480. disk->bus = tgt[0];
  481. disk->target = tgt[1];
  482. disk->unit = tgt[2];
  483. } else {
  484. /* virtio-blk: 1 disk per 1 device */
  485. disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO;
  486. }
  487. return true;
  488. }
  489. /*
  490. * Store disk device info for CCW devices (s390x channel I/O devices).
  491. * Returns true if information has been stored, or false for failure.
  492. */
  493. static bool build_guest_fsinfo_for_ccw_dev(char const *syspath,
  494. GuestDiskAddress *disk,
  495. Error **errp)
  496. {
  497. unsigned int cssid, ssid, subchno, devno;
  498. char *p;
  499. p = strstr(syspath, "/devices/css");
  500. if (!p || sscanf(p + 12, "%*x/%x.%x.%x/%*x.%*x.%x/",
  501. &cssid, &ssid, &subchno, &devno) < 4) {
  502. g_debug("could not parse ccw device sysfs path: %s", syspath);
  503. return false;
  504. }
  505. disk->ccw_address = g_new0(GuestCCWAddress, 1);
  506. disk->ccw_address->cssid = cssid;
  507. disk->ccw_address->ssid = ssid;
  508. disk->ccw_address->subchno = subchno;
  509. disk->ccw_address->devno = devno;
  510. if (strstr(p, "/virtio")) {
  511. build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
  512. }
  513. return true;
  514. }
  515. /* Store disk device info specified by @sysfs into @fs */
  516. static void build_guest_fsinfo_for_real_device(char const *syspath,
  517. GuestFilesystemInfo *fs,
  518. Error **errp)
  519. {
  520. GuestDiskAddress *disk;
  521. GuestPCIAddress *pciaddr;
  522. bool has_hwinf;
  523. #ifdef CONFIG_LIBUDEV
  524. struct udev *udev = NULL;
  525. struct udev_device *udevice = NULL;
  526. #endif
  527. pciaddr = g_new0(GuestPCIAddress, 1);
  528. pciaddr->domain = -1; /* -1 means field is invalid */
  529. pciaddr->bus = -1;
  530. pciaddr->slot = -1;
  531. pciaddr->function = -1;
  532. disk = g_new0(GuestDiskAddress, 1);
  533. disk->pci_controller = pciaddr;
  534. disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
  535. #ifdef CONFIG_LIBUDEV
  536. udev = udev_new();
  537. udevice = udev_device_new_from_syspath(udev, syspath);
  538. if (udev == NULL || udevice == NULL) {
  539. g_debug("failed to query udev");
  540. } else {
  541. const char *devnode, *serial;
  542. devnode = udev_device_get_devnode(udevice);
  543. if (devnode != NULL) {
  544. disk->dev = g_strdup(devnode);
  545. }
  546. serial = udev_device_get_property_value(udevice, "ID_SERIAL");
  547. if (serial != NULL && *serial != 0) {
  548. disk->serial = g_strdup(serial);
  549. }
  550. }
  551. udev_unref(udev);
  552. udev_device_unref(udevice);
  553. #endif
  554. if (strstr(syspath, "/devices/pci")) {
  555. has_hwinf = build_guest_fsinfo_for_pci_dev(syspath, disk, errp);
  556. } else if (strstr(syspath, "/devices/css")) {
  557. has_hwinf = build_guest_fsinfo_for_ccw_dev(syspath, disk, errp);
  558. } else if (strstr(syspath, "/virtio")) {
  559. has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
  560. } else {
  561. g_debug("Unsupported device type for '%s'", syspath);
  562. has_hwinf = false;
  563. }
  564. if (has_hwinf || disk->dev || disk->serial) {
  565. QAPI_LIST_PREPEND(fs->disk, disk);
  566. } else {
  567. qapi_free_GuestDiskAddress(disk);
  568. }
  569. }
  570. static void build_guest_fsinfo_for_device(char const *devpath,
  571. GuestFilesystemInfo *fs,
  572. Error **errp);
  573. /* Store a list of slave devices of virtual volume specified by @syspath into
  574. * @fs */
  575. static void build_guest_fsinfo_for_virtual_device(char const *syspath,
  576. GuestFilesystemInfo *fs,
  577. Error **errp)
  578. {
  579. Error *err = NULL;
  580. DIR *dir;
  581. char *dirpath;
  582. struct dirent *entry;
  583. dirpath = g_strdup_printf("%s/slaves", syspath);
  584. dir = opendir(dirpath);
  585. if (!dir) {
  586. if (errno != ENOENT) {
  587. error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath);
  588. }
  589. g_free(dirpath);
  590. return;
  591. }
  592. for (;;) {
  593. errno = 0;
  594. entry = readdir(dir);
  595. if (entry == NULL) {
  596. if (errno) {
  597. error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath);
  598. }
  599. break;
  600. }
  601. if (entry->d_type == DT_LNK) {
  602. char *path;
  603. g_debug(" slave device '%s'", entry->d_name);
  604. path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name);
  605. build_guest_fsinfo_for_device(path, fs, &err);
  606. g_free(path);
  607. if (err) {
  608. error_propagate(errp, err);
  609. break;
  610. }
  611. }
  612. }
  613. g_free(dirpath);
  614. closedir(dir);
  615. }
  616. static bool is_disk_virtual(const char *devpath, Error **errp)
  617. {
  618. g_autofree char *syspath = realpath(devpath, NULL);
  619. if (!syspath) {
  620. error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
  621. return false;
  622. }
  623. return strstr(syspath, "/devices/virtual/block/") != NULL;
  624. }
  625. /* Dispatch to functions for virtual/real device */
  626. static void build_guest_fsinfo_for_device(char const *devpath,
  627. GuestFilesystemInfo *fs,
  628. Error **errp)
  629. {
  630. ERRP_GUARD();
  631. g_autofree char *syspath = NULL;
  632. bool is_virtual = false;
  633. syspath = realpath(devpath, NULL);
  634. if (!syspath) {
  635. if (errno != ENOENT) {
  636. error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
  637. return;
  638. }
  639. /* ENOENT: This devpath may not exist because of container config */
  640. if (!fs->name) {
  641. fs->name = g_path_get_basename(devpath);
  642. }
  643. return;
  644. }
  645. if (!fs->name) {
  646. fs->name = g_path_get_basename(syspath);
  647. }
  648. g_debug(" parse sysfs path '%s'", syspath);
  649. is_virtual = is_disk_virtual(syspath, errp);
  650. if (*errp != NULL) {
  651. return;
  652. }
  653. if (is_virtual) {
  654. build_guest_fsinfo_for_virtual_device(syspath, fs, errp);
  655. } else {
  656. build_guest_fsinfo_for_real_device(syspath, fs, errp);
  657. }
  658. }
  659. #ifdef CONFIG_LIBUDEV
  660. /*
  661. * Wrapper around build_guest_fsinfo_for_device() for getting just
  662. * the disk address.
  663. */
  664. static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp)
  665. {
  666. g_autoptr(GuestFilesystemInfo) fs = NULL;
  667. fs = g_new0(GuestFilesystemInfo, 1);
  668. build_guest_fsinfo_for_device(syspath, fs, errp);
  669. if (fs->disk != NULL) {
  670. return g_steal_pointer(&fs->disk->value);
  671. }
  672. return NULL;
  673. }
  674. static char *get_alias_for_syspath(const char *syspath)
  675. {
  676. struct udev *udev = NULL;
  677. struct udev_device *udevice = NULL;
  678. char *ret = NULL;
  679. udev = udev_new();
  680. if (udev == NULL) {
  681. g_debug("failed to query udev");
  682. goto out;
  683. }
  684. udevice = udev_device_new_from_syspath(udev, syspath);
  685. if (udevice == NULL) {
  686. g_debug("failed to query udev for path: %s", syspath);
  687. goto out;
  688. } else {
  689. const char *alias = udev_device_get_property_value(
  690. udevice, "DM_NAME");
  691. /*
  692. * NULL means there was an error and empty string means there is no
  693. * alias. In case of no alias we return NULL instead of empty string.
  694. */
  695. if (alias == NULL) {
  696. g_debug("failed to query udev for device alias for: %s",
  697. syspath);
  698. } else if (*alias != 0) {
  699. ret = g_strdup(alias);
  700. }
  701. }
  702. out:
  703. udev_unref(udev);
  704. udev_device_unref(udevice);
  705. return ret;
  706. }
  707. static char *get_device_for_syspath(const char *syspath)
  708. {
  709. struct udev *udev = NULL;
  710. struct udev_device *udevice = NULL;
  711. char *ret = NULL;
  712. udev = udev_new();
  713. if (udev == NULL) {
  714. g_debug("failed to query udev");
  715. goto out;
  716. }
  717. udevice = udev_device_new_from_syspath(udev, syspath);
  718. if (udevice == NULL) {
  719. g_debug("failed to query udev for path: %s", syspath);
  720. goto out;
  721. } else {
  722. ret = g_strdup(udev_device_get_devnode(udevice));
  723. }
  724. out:
  725. udev_unref(udev);
  726. udev_device_unref(udevice);
  727. return ret;
  728. }
  729. static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
  730. {
  731. g_autofree char *deps_dir = NULL;
  732. const gchar *dep;
  733. GDir *dp_deps = NULL;
  734. /* List dependent disks */
  735. deps_dir = g_strdup_printf("%s/slaves", disk_dir);
  736. g_debug(" listing entries in: %s", deps_dir);
  737. dp_deps = g_dir_open(deps_dir, 0, NULL);
  738. if (dp_deps == NULL) {
  739. g_debug("failed to list entries in %s", deps_dir);
  740. return;
  741. }
  742. disk->has_dependencies = true;
  743. while ((dep = g_dir_read_name(dp_deps)) != NULL) {
  744. g_autofree char *dep_dir = NULL;
  745. char *dev_name;
  746. /* Add dependent disks */
  747. dep_dir = g_strdup_printf("%s/%s", deps_dir, dep);
  748. dev_name = get_device_for_syspath(dep_dir);
  749. if (dev_name != NULL) {
  750. g_debug(" adding dependent device: %s", dev_name);
  751. QAPI_LIST_PREPEND(disk->dependencies, dev_name);
  752. }
  753. }
  754. g_dir_close(dp_deps);
  755. }
  756. /*
  757. * Detect partitions subdirectory, name is "<disk_name><number>" or
  758. * "<disk_name>p<number>"
  759. *
  760. * @disk_name -- last component of /sys path (e.g. sda)
  761. * @disk_dir -- sys path of the disk (e.g. /sys/block/sda)
  762. * @disk_dev -- device node of the disk (e.g. /dev/sda)
  763. */
  764. static GuestDiskInfoList *get_disk_partitions(
  765. GuestDiskInfoList *list,
  766. const char *disk_name, const char *disk_dir,
  767. const char *disk_dev)
  768. {
  769. GuestDiskInfoList *ret = list;
  770. struct dirent *de_disk;
  771. DIR *dp_disk = NULL;
  772. size_t len = strlen(disk_name);
  773. dp_disk = opendir(disk_dir);
  774. while ((de_disk = readdir(dp_disk)) != NULL) {
  775. g_autofree char *partition_dir = NULL;
  776. char *dev_name;
  777. GuestDiskInfo *partition;
  778. if (!(de_disk->d_type & DT_DIR)) {
  779. continue;
  780. }
  781. if (!(strncmp(disk_name, de_disk->d_name, len) == 0 &&
  782. ((*(de_disk->d_name + len) == 'p' &&
  783. isdigit(*(de_disk->d_name + len + 1))) ||
  784. isdigit(*(de_disk->d_name + len))))) {
  785. continue;
  786. }
  787. partition_dir = g_strdup_printf("%s/%s",
  788. disk_dir, de_disk->d_name);
  789. dev_name = get_device_for_syspath(partition_dir);
  790. if (dev_name == NULL) {
  791. g_debug("Failed to get device name for syspath: %s",
  792. disk_dir);
  793. continue;
  794. }
  795. partition = g_new0(GuestDiskInfo, 1);
  796. partition->name = dev_name;
  797. partition->partition = true;
  798. partition->has_dependencies = true;
  799. /* Add parent disk as dependent for easier tracking of hierarchy */
  800. QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev));
  801. QAPI_LIST_PREPEND(ret, partition);
  802. }
  803. closedir(dp_disk);
  804. return ret;
  805. }
  806. static void get_nvme_smart(GuestDiskInfo *disk)
  807. {
  808. int fd;
  809. GuestNVMeSmart *smart;
  810. NvmeSmartLog log = {0};
  811. struct nvme_admin_cmd cmd = {
  812. .opcode = NVME_ADM_CMD_GET_LOG_PAGE,
  813. .nsid = NVME_NSID_BROADCAST,
  814. .addr = (uintptr_t)&log,
  815. .data_len = sizeof(log),
  816. .cdw10 = NVME_LOG_SMART_INFO | (1 << 15) /* RAE bit */
  817. | (((sizeof(log) >> 2) - 1) << 16)
  818. };
  819. fd = qga_open_cloexec(disk->name, O_RDONLY, 0);
  820. if (fd == -1) {
  821. g_debug("Failed to open device: %s: %s", disk->name, g_strerror(errno));
  822. return;
  823. }
  824. if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd)) {
  825. g_debug("Failed to get smart: %s: %s", disk->name, g_strerror(errno));
  826. close(fd);
  827. return;
  828. }
  829. disk->smart = g_new0(GuestDiskSmart, 1);
  830. disk->smart->type = GUEST_DISK_BUS_TYPE_NVME;
  831. smart = &disk->smart->u.nvme;
  832. smart->critical_warning = log.critical_warning;
  833. smart->temperature = lduw_le_p(&log.temperature); /* unaligned field */
  834. smart->available_spare = log.available_spare;
  835. smart->available_spare_threshold = log.available_spare_threshold;
  836. smart->percentage_used = log.percentage_used;
  837. smart->data_units_read_lo = le64_to_cpu(log.data_units_read[0]);
  838. smart->data_units_read_hi = le64_to_cpu(log.data_units_read[1]);
  839. smart->data_units_written_lo = le64_to_cpu(log.data_units_written[0]);
  840. smart->data_units_written_hi = le64_to_cpu(log.data_units_written[1]);
  841. smart->host_read_commands_lo = le64_to_cpu(log.host_read_commands[0]);
  842. smart->host_read_commands_hi = le64_to_cpu(log.host_read_commands[1]);
  843. smart->host_write_commands_lo = le64_to_cpu(log.host_write_commands[0]);
  844. smart->host_write_commands_hi = le64_to_cpu(log.host_write_commands[1]);
  845. smart->controller_busy_time_lo = le64_to_cpu(log.controller_busy_time[0]);
  846. smart->controller_busy_time_hi = le64_to_cpu(log.controller_busy_time[1]);
  847. smart->power_cycles_lo = le64_to_cpu(log.power_cycles[0]);
  848. smart->power_cycles_hi = le64_to_cpu(log.power_cycles[1]);
  849. smart->power_on_hours_lo = le64_to_cpu(log.power_on_hours[0]);
  850. smart->power_on_hours_hi = le64_to_cpu(log.power_on_hours[1]);
  851. smart->unsafe_shutdowns_lo = le64_to_cpu(log.unsafe_shutdowns[0]);
  852. smart->unsafe_shutdowns_hi = le64_to_cpu(log.unsafe_shutdowns[1]);
  853. smart->media_errors_lo = le64_to_cpu(log.media_errors[0]);
  854. smart->media_errors_hi = le64_to_cpu(log.media_errors[1]);
  855. smart->number_of_error_log_entries_lo =
  856. le64_to_cpu(log.number_of_error_log_entries[0]);
  857. smart->number_of_error_log_entries_hi =
  858. le64_to_cpu(log.number_of_error_log_entries[1]);
  859. close(fd);
  860. }
  861. static void get_disk_smart(GuestDiskInfo *disk)
  862. {
  863. if (disk->address
  864. && (disk->address->bus_type == GUEST_DISK_BUS_TYPE_NVME)) {
  865. get_nvme_smart(disk);
  866. }
  867. }
  868. GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
  869. {
  870. GuestDiskInfoList *ret = NULL;
  871. GuestDiskInfo *disk;
  872. DIR *dp = NULL;
  873. struct dirent *de = NULL;
  874. g_debug("listing /sys/block directory");
  875. dp = opendir("/sys/block");
  876. if (dp == NULL) {
  877. error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"");
  878. return NULL;
  879. }
  880. while ((de = readdir(dp)) != NULL) {
  881. g_autofree char *disk_dir = NULL, *line = NULL,
  882. *size_path = NULL;
  883. char *dev_name;
  884. Error *local_err = NULL;
  885. if (de->d_type != DT_LNK) {
  886. g_debug(" skipping entry: %s", de->d_name);
  887. continue;
  888. }
  889. /* Check size and skip zero-sized disks */
  890. g_debug(" checking disk size");
  891. size_path = g_strdup_printf("/sys/block/%s/size", de->d_name);
  892. if (!g_file_get_contents(size_path, &line, NULL, NULL)) {
  893. g_debug(" failed to read disk size");
  894. continue;
  895. }
  896. if (g_strcmp0(line, "0\n") == 0) {
  897. g_debug(" skipping zero-sized disk");
  898. continue;
  899. }
  900. g_debug(" adding %s", de->d_name);
  901. disk_dir = g_strdup_printf("/sys/block/%s", de->d_name);
  902. dev_name = get_device_for_syspath(disk_dir);
  903. if (dev_name == NULL) {
  904. g_debug("Failed to get device name for syspath: %s",
  905. disk_dir);
  906. continue;
  907. }
  908. disk = g_new0(GuestDiskInfo, 1);
  909. disk->name = dev_name;
  910. disk->partition = false;
  911. disk->alias = get_alias_for_syspath(disk_dir);
  912. QAPI_LIST_PREPEND(ret, disk);
  913. /* Get address for non-virtual devices */
  914. bool is_virtual = is_disk_virtual(disk_dir, &local_err);
  915. if (local_err != NULL) {
  916. g_debug(" failed to check disk path, ignoring error: %s",
  917. error_get_pretty(local_err));
  918. error_free(local_err);
  919. local_err = NULL;
  920. /* Don't try to get the address */
  921. is_virtual = true;
  922. }
  923. if (!is_virtual) {
  924. disk->address = get_disk_address(disk_dir, &local_err);
  925. if (local_err != NULL) {
  926. g_debug(" failed to get device info, ignoring error: %s",
  927. error_get_pretty(local_err));
  928. error_free(local_err);
  929. local_err = NULL;
  930. }
  931. }
  932. get_disk_deps(disk_dir, disk);
  933. get_disk_smart(disk);
  934. ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name);
  935. }
  936. closedir(dp);
  937. return ret;
  938. }
  939. #endif
  940. /* Return a list of the disk device(s)' info which @mount lies on */
  941. static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount,
  942. Error **errp)
  943. {
  944. GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs));
  945. struct statvfs buf;
  946. unsigned long used, nonroot_total, fr_size;
  947. char *devpath = g_strdup_printf("/sys/dev/block/%u:%u",
  948. mount->devmajor, mount->devminor);
  949. fs->mountpoint = g_strdup(mount->dirname);
  950. fs->type = g_strdup(mount->devtype);
  951. build_guest_fsinfo_for_device(devpath, fs, errp);
  952. if (statvfs(fs->mountpoint, &buf) == 0) {
  953. fr_size = buf.f_frsize;
  954. used = buf.f_blocks - buf.f_bfree;
  955. nonroot_total = used + buf.f_bavail;
  956. fs->used_bytes = used * fr_size;
  957. fs->total_bytes = nonroot_total * fr_size;
  958. fs->total_bytes_privileged = buf.f_blocks * fr_size;
  959. fs->has_total_bytes = true;
  960. fs->has_total_bytes_privileged = true;
  961. fs->has_used_bytes = true;
  962. }
  963. g_free(devpath);
  964. return fs;
  965. }
  966. GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
  967. {
  968. FsMountList mounts;
  969. struct FsMount *mount;
  970. GuestFilesystemInfoList *ret = NULL;
  971. Error *local_err = NULL;
  972. QTAILQ_INIT(&mounts);
  973. if (!build_fs_mount_list(&mounts, &local_err)) {
  974. error_propagate(errp, local_err);
  975. return NULL;
  976. }
  977. QTAILQ_FOREACH(mount, &mounts, next) {
  978. g_debug("Building guest fsinfo for '%s'", mount->dirname);
  979. QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
  980. if (local_err) {
  981. error_propagate(errp, local_err);
  982. qapi_free_GuestFilesystemInfoList(ret);
  983. ret = NULL;
  984. break;
  985. }
  986. }
  987. free_fs_mount_list(&mounts);
  988. return ret;
  989. }
  990. #endif /* CONFIG_FSFREEZE */
  991. #if defined(CONFIG_FSTRIM)
  992. /*
  993. * Walk list of mounted file systems in the guest, and trim them.
  994. */
  995. GuestFilesystemTrimResponse *
  996. qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
  997. {
  998. GuestFilesystemTrimResponse *response;
  999. GuestFilesystemTrimResult *result;
  1000. int ret = 0;
  1001. FsMountList mounts;
  1002. struct FsMount *mount;
  1003. int fd;
  1004. struct fstrim_range r;
  1005. slog("guest-fstrim called");
  1006. QTAILQ_INIT(&mounts);
  1007. if (!build_fs_mount_list(&mounts, errp)) {
  1008. return NULL;
  1009. }
  1010. response = g_malloc0(sizeof(*response));
  1011. QTAILQ_FOREACH(mount, &mounts, next) {
  1012. result = g_malloc0(sizeof(*result));
  1013. result->path = g_strdup(mount->dirname);
  1014. QAPI_LIST_PREPEND(response->paths, result);
  1015. fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0);
  1016. if (fd == -1) {
  1017. result->error = g_strdup_printf("failed to open: %s",
  1018. strerror(errno));
  1019. continue;
  1020. }
  1021. /* We try to cull filesystems we know won't work in advance, but other
  1022. * filesystems may not implement fstrim for less obvious reasons.
  1023. * These will report EOPNOTSUPP; while in some other cases ENOTTY
  1024. * will be reported (e.g. CD-ROMs).
  1025. * Any other error means an unexpected error.
  1026. */
  1027. r.start = 0;
  1028. r.len = -1;
  1029. r.minlen = has_minimum ? minimum : 0;
  1030. ret = ioctl(fd, FITRIM, &r);
  1031. if (ret == -1) {
  1032. if (errno == ENOTTY || errno == EOPNOTSUPP) {
  1033. result->error = g_strdup("trim not supported");
  1034. } else {
  1035. result->error = g_strdup_printf("failed to trim: %s",
  1036. strerror(errno));
  1037. }
  1038. close(fd);
  1039. continue;
  1040. }
  1041. result->has_minimum = true;
  1042. result->minimum = r.minlen;
  1043. result->has_trimmed = true;
  1044. result->trimmed = r.len;
  1045. close(fd);
  1046. }
  1047. free_fs_mount_list(&mounts);
  1048. return response;
  1049. }
  1050. #endif /* CONFIG_FSTRIM */
  1051. #define LINUX_SYS_STATE_FILE "/sys/power/state"
  1052. #define SUSPEND_SUPPORTED 0
  1053. #define SUSPEND_NOT_SUPPORTED 1
  1054. typedef enum {
  1055. SUSPEND_MODE_DISK = 0,
  1056. SUSPEND_MODE_RAM = 1,
  1057. SUSPEND_MODE_HYBRID = 2,
  1058. } SuspendMode;
  1059. /*
  1060. * Executes a command in a child process using g_spawn_sync,
  1061. * returning an int >= 0 representing the exit status of the
  1062. * process.
  1063. *
  1064. * If the program wasn't found in path, returns -1.
  1065. *
  1066. * If a problem happened when creating the child process,
  1067. * returns -1 and errp is set.
  1068. */
  1069. static int run_process_child(const char *command[], Error **errp)
  1070. {
  1071. int exit_status, spawn_flag;
  1072. GError *g_err = NULL;
  1073. bool success;
  1074. spawn_flag = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL |
  1075. G_SPAWN_STDERR_TO_DEV_NULL;
  1076. success = g_spawn_sync(NULL, (char **)command, NULL, spawn_flag,
  1077. NULL, NULL, NULL, NULL,
  1078. &exit_status, &g_err);
  1079. if (success) {
  1080. return WEXITSTATUS(exit_status);
  1081. }
  1082. if (g_err && (g_err->code != G_SPAWN_ERROR_NOENT)) {
  1083. error_setg(errp, "failed to create child process, error '%s'",
  1084. g_err->message);
  1085. }
  1086. g_error_free(g_err);
  1087. return -1;
  1088. }
  1089. static bool systemd_supports_mode(SuspendMode mode, Error **errp)
  1090. {
  1091. const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend",
  1092. "systemd-hybrid-sleep"};
  1093. const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL};
  1094. int status;
  1095. status = run_process_child(cmd, errp);
  1096. /*
  1097. * systemctl status uses LSB return codes so we can expect
  1098. * status > 0 and be ok. To assert if the guest has support
  1099. * for the selected suspend mode, status should be < 4. 4 is
  1100. * the code for unknown service status, the return value when
  1101. * the service does not exist. A common value is status = 3
  1102. * (program is not running).
  1103. */
  1104. if (status > 0 && status < 4) {
  1105. return true;
  1106. }
  1107. return false;
  1108. }
  1109. static void systemd_suspend(SuspendMode mode, Error **errp)
  1110. {
  1111. Error *local_err = NULL;
  1112. const char *systemctl_args[3] = {"hibernate", "suspend", "hybrid-sleep"};
  1113. const char *cmd[3] = {"systemctl", systemctl_args[mode], NULL};
  1114. int status;
  1115. status = run_process_child(cmd, &local_err);
  1116. if (status == 0) {
  1117. return;
  1118. }
  1119. if ((status == -1) && !local_err) {
  1120. error_setg(errp, "the helper program 'systemctl %s' was not found",
  1121. systemctl_args[mode]);
  1122. return;
  1123. }
  1124. if (local_err) {
  1125. error_propagate(errp, local_err);
  1126. } else {
  1127. error_setg(errp, "the helper program 'systemctl %s' returned an "
  1128. "unexpected exit status code (%d)",
  1129. systemctl_args[mode], status);
  1130. }
  1131. }
  1132. static bool pmutils_supports_mode(SuspendMode mode, Error **errp)
  1133. {
  1134. Error *local_err = NULL;
  1135. const char *pmutils_args[3] = {"--hibernate", "--suspend",
  1136. "--suspend-hybrid"};
  1137. const char *cmd[3] = {"pm-is-supported", pmutils_args[mode], NULL};
  1138. int status;
  1139. status = run_process_child(cmd, &local_err);
  1140. if (status == SUSPEND_SUPPORTED) {
  1141. return true;
  1142. }
  1143. if ((status == -1) && !local_err) {
  1144. return false;
  1145. }
  1146. if (local_err) {
  1147. error_propagate(errp, local_err);
  1148. } else {
  1149. error_setg(errp,
  1150. "the helper program '%s' returned an unexpected exit"
  1151. " status code (%d)", "pm-is-supported", status);
  1152. }
  1153. return false;
  1154. }
  1155. static void pmutils_suspend(SuspendMode mode, Error **errp)
  1156. {
  1157. Error *local_err = NULL;
  1158. const char *pmutils_binaries[3] = {"pm-hibernate", "pm-suspend",
  1159. "pm-suspend-hybrid"};
  1160. const char *cmd[2] = {pmutils_binaries[mode], NULL};
  1161. int status;
  1162. status = run_process_child(cmd, &local_err);
  1163. if (status == 0) {
  1164. return;
  1165. }
  1166. if ((status == -1) && !local_err) {
  1167. error_setg(errp, "the helper program '%s' was not found",
  1168. pmutils_binaries[mode]);
  1169. return;
  1170. }
  1171. if (local_err) {
  1172. error_propagate(errp, local_err);
  1173. } else {
  1174. error_setg(errp,
  1175. "the helper program '%s' returned an unexpected exit"
  1176. " status code (%d)", pmutils_binaries[mode], status);
  1177. }
  1178. }
  1179. static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp)
  1180. {
  1181. const char *sysfile_strs[3] = {"disk", "mem", NULL};
  1182. const char *sysfile_str = sysfile_strs[mode];
  1183. char buf[32]; /* hopefully big enough */
  1184. int fd;
  1185. ssize_t ret;
  1186. if (!sysfile_str) {
  1187. error_setg(errp, "unknown guest suspend mode");
  1188. return false;
  1189. }
  1190. fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
  1191. if (fd < 0) {
  1192. return false;
  1193. }
  1194. ret = read(fd, buf, sizeof(buf) - 1);
  1195. close(fd);
  1196. if (ret <= 0) {
  1197. return false;
  1198. }
  1199. buf[ret] = '\0';
  1200. if (strstr(buf, sysfile_str)) {
  1201. return true;
  1202. }
  1203. return false;
  1204. }
  1205. static void linux_sys_state_suspend(SuspendMode mode, Error **errp)
  1206. {
  1207. g_autoptr(GError) local_gerr = NULL;
  1208. const char *sysfile_strs[3] = {"disk", "mem", NULL};
  1209. const char *sysfile_str = sysfile_strs[mode];
  1210. if (!sysfile_str) {
  1211. error_setg(errp, "unknown guest suspend mode");
  1212. return;
  1213. }
  1214. if (!g_file_set_contents(LINUX_SYS_STATE_FILE, sysfile_str,
  1215. -1, &local_gerr)) {
  1216. error_setg(errp, "suspend: cannot write to '%s': %s",
  1217. LINUX_SYS_STATE_FILE, local_gerr->message);
  1218. return;
  1219. }
  1220. }
  1221. static void guest_suspend(SuspendMode mode, Error **errp)
  1222. {
  1223. Error *local_err = NULL;
  1224. bool mode_supported = false;
  1225. if (systemd_supports_mode(mode, &local_err)) {
  1226. mode_supported = true;
  1227. systemd_suspend(mode, &local_err);
  1228. if (!local_err) {
  1229. return;
  1230. }
  1231. }
  1232. error_free(local_err);
  1233. local_err = NULL;
  1234. if (pmutils_supports_mode(mode, &local_err)) {
  1235. mode_supported = true;
  1236. pmutils_suspend(mode, &local_err);
  1237. if (!local_err) {
  1238. return;
  1239. }
  1240. }
  1241. error_free(local_err);
  1242. local_err = NULL;
  1243. if (linux_sys_state_supports_mode(mode, &local_err)) {
  1244. mode_supported = true;
  1245. linux_sys_state_suspend(mode, &local_err);
  1246. }
  1247. if (!mode_supported) {
  1248. error_free(local_err);
  1249. error_setg(errp,
  1250. "the requested suspend mode is not supported by the guest");
  1251. } else {
  1252. error_propagate(errp, local_err);
  1253. }
  1254. }
  1255. void qmp_guest_suspend_disk(Error **errp)
  1256. {
  1257. guest_suspend(SUSPEND_MODE_DISK, errp);
  1258. }
  1259. void qmp_guest_suspend_ram(Error **errp)
  1260. {
  1261. guest_suspend(SUSPEND_MODE_RAM, errp);
  1262. }
  1263. void qmp_guest_suspend_hybrid(Error **errp)
  1264. {
  1265. guest_suspend(SUSPEND_MODE_HYBRID, errp);
  1266. }
  1267. /* Transfer online/offline status between @vcpu and the guest system.
  1268. *
  1269. * On input either @errp or *@errp must be NULL.
  1270. *
  1271. * In system-to-@vcpu direction, the following @vcpu fields are accessed:
  1272. * - R: vcpu->logical_id
  1273. * - W: vcpu->online
  1274. * - W: vcpu->can_offline
  1275. *
  1276. * In @vcpu-to-system direction, the following @vcpu fields are accessed:
  1277. * - R: vcpu->logical_id
  1278. * - R: vcpu->online
  1279. *
  1280. * Written members remain unmodified on error.
  1281. */
  1282. static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
  1283. char *dirpath, Error **errp)
  1284. {
  1285. int fd;
  1286. int res;
  1287. int dirfd;
  1288. static const char fn[] = "online";
  1289. dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
  1290. if (dirfd == -1) {
  1291. error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
  1292. return;
  1293. }
  1294. fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
  1295. if (fd == -1) {
  1296. if (errno != ENOENT) {
  1297. error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
  1298. } else if (sys2vcpu) {
  1299. vcpu->online = true;
  1300. vcpu->can_offline = false;
  1301. } else if (!vcpu->online) {
  1302. error_setg(errp, "logical processor #%" PRId64 " can't be "
  1303. "offlined", vcpu->logical_id);
  1304. } /* otherwise pretend successful re-onlining */
  1305. } else {
  1306. unsigned char status;
  1307. res = pread(fd, &status, 1, 0);
  1308. if (res == -1) {
  1309. error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
  1310. } else if (res == 0) {
  1311. error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
  1312. fn);
  1313. } else if (sys2vcpu) {
  1314. vcpu->online = (status != '0');
  1315. vcpu->can_offline = true;
  1316. } else if (vcpu->online != (status != '0')) {
  1317. status = '0' + vcpu->online;
  1318. if (pwrite(fd, &status, 1, 0) == -1) {
  1319. error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
  1320. fn);
  1321. }
  1322. } /* otherwise pretend successful re-(on|off)-lining */
  1323. res = close(fd);
  1324. g_assert(res == 0);
  1325. }
  1326. res = close(dirfd);
  1327. g_assert(res == 0);
  1328. }
  1329. GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
  1330. {
  1331. GuestLogicalProcessorList *head, **tail;
  1332. const char *cpu_dir = "/sys/devices/system/cpu";
  1333. const gchar *line;
  1334. g_autoptr(GDir) cpu_gdir = NULL;
  1335. Error *local_err = NULL;
  1336. head = NULL;
  1337. tail = &head;
  1338. cpu_gdir = g_dir_open(cpu_dir, 0, NULL);
  1339. if (cpu_gdir == NULL) {
  1340. error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir);
  1341. return NULL;
  1342. }
  1343. while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) {
  1344. GuestLogicalProcessor *vcpu;
  1345. int64_t id;
  1346. if (sscanf(line, "cpu%" PRId64, &id)) {
  1347. g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/"
  1348. "cpu%" PRId64 "/", id);
  1349. vcpu = g_malloc0(sizeof *vcpu);
  1350. vcpu->logical_id = id;
  1351. vcpu->has_can_offline = true; /* lolspeak ftw */
  1352. transfer_vcpu(vcpu, true, path, &local_err);
  1353. QAPI_LIST_APPEND(tail, vcpu);
  1354. }
  1355. }
  1356. if (local_err == NULL) {
  1357. /* there's no guest with zero VCPUs */
  1358. g_assert(head != NULL);
  1359. return head;
  1360. }
  1361. qapi_free_GuestLogicalProcessorList(head);
  1362. error_propagate(errp, local_err);
  1363. return NULL;
  1364. }
  1365. int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
  1366. {
  1367. int64_t processed;
  1368. Error *local_err = NULL;
  1369. processed = 0;
  1370. while (vcpus != NULL) {
  1371. char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
  1372. vcpus->value->logical_id);
  1373. transfer_vcpu(vcpus->value, false, path, &local_err);
  1374. g_free(path);
  1375. if (local_err != NULL) {
  1376. break;
  1377. }
  1378. ++processed;
  1379. vcpus = vcpus->next;
  1380. }
  1381. if (local_err != NULL) {
  1382. if (processed == 0) {
  1383. error_propagate(errp, local_err);
  1384. } else {
  1385. error_free(local_err);
  1386. }
  1387. }
  1388. return processed;
  1389. }
  1390. static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf,
  1391. int size, Error **errp)
  1392. {
  1393. int fd;
  1394. int res;
  1395. errno = 0;
  1396. fd = openat(dirfd, pathname, O_RDONLY);
  1397. if (fd == -1) {
  1398. error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
  1399. return;
  1400. }
  1401. res = pread(fd, buf, size, 0);
  1402. if (res == -1) {
  1403. error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname);
  1404. } else if (res == 0) {
  1405. error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname);
  1406. }
  1407. close(fd);
  1408. }
  1409. static void ga_write_sysfs_file(int dirfd, const char *pathname,
  1410. const char *buf, int size, Error **errp)
  1411. {
  1412. int fd;
  1413. errno = 0;
  1414. fd = openat(dirfd, pathname, O_WRONLY);
  1415. if (fd == -1) {
  1416. error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname);
  1417. return;
  1418. }
  1419. if (pwrite(fd, buf, size, 0) == -1) {
  1420. error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname);
  1421. }
  1422. close(fd);
  1423. }
  1424. /* Transfer online/offline status between @mem_blk and the guest system.
  1425. *
  1426. * On input either @errp or *@errp must be NULL.
  1427. *
  1428. * In system-to-@mem_blk direction, the following @mem_blk fields are accessed:
  1429. * - R: mem_blk->phys_index
  1430. * - W: mem_blk->online
  1431. * - W: mem_blk->can_offline
  1432. *
  1433. * In @mem_blk-to-system direction, the following @mem_blk fields are accessed:
  1434. * - R: mem_blk->phys_index
  1435. * - R: mem_blk->online
  1436. *- R: mem_blk->can_offline
  1437. * Written members remain unmodified on error.
  1438. */
  1439. static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk,
  1440. GuestMemoryBlockResponse *result,
  1441. Error **errp)
  1442. {
  1443. char *dirpath;
  1444. int dirfd;
  1445. char *status;
  1446. Error *local_err = NULL;
  1447. if (!sys2memblk) {
  1448. DIR *dp;
  1449. if (!result) {
  1450. error_setg(errp, "Internal error, 'result' should not be NULL");
  1451. return;
  1452. }
  1453. errno = 0;
  1454. dp = opendir("/sys/devices/system/memory/");
  1455. /* if there is no 'memory' directory in sysfs,
  1456. * we think this VM does not support online/offline memory block,
  1457. * any other solution?
  1458. */
  1459. if (!dp) {
  1460. if (errno == ENOENT) {
  1461. result->response =
  1462. GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
  1463. }
  1464. goto out1;
  1465. }
  1466. closedir(dp);
  1467. }
  1468. dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/",
  1469. mem_blk->phys_index);
  1470. dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
  1471. if (dirfd == -1) {
  1472. if (sys2memblk) {
  1473. error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
  1474. } else {
  1475. if (errno == ENOENT) {
  1476. result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND;
  1477. } else {
  1478. result->response =
  1479. GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
  1480. }
  1481. }
  1482. g_free(dirpath);
  1483. goto out1;
  1484. }
  1485. g_free(dirpath);
  1486. status = g_malloc0(10);
  1487. ga_read_sysfs_file(dirfd, "state", status, 10, &local_err);
  1488. if (local_err) {
  1489. /* treat with sysfs file that not exist in old kernel */
  1490. if (errno == ENOENT) {
  1491. error_free(local_err);
  1492. if (sys2memblk) {
  1493. mem_blk->online = true;
  1494. mem_blk->can_offline = false;
  1495. } else if (!mem_blk->online) {
  1496. result->response =
  1497. GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
  1498. }
  1499. } else {
  1500. if (sys2memblk) {
  1501. error_propagate(errp, local_err);
  1502. } else {
  1503. error_free(local_err);
  1504. result->response =
  1505. GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
  1506. }
  1507. }
  1508. goto out2;
  1509. }
  1510. if (sys2memblk) {
  1511. char removable = '0';
  1512. mem_blk->online = (strncmp(status, "online", 6) == 0);
  1513. ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err);
  1514. if (local_err) {
  1515. /* if no 'removable' file, it doesn't support offline mem blk */
  1516. if (errno == ENOENT) {
  1517. error_free(local_err);
  1518. mem_blk->can_offline = false;
  1519. } else {
  1520. error_propagate(errp, local_err);
  1521. }
  1522. } else {
  1523. mem_blk->can_offline = (removable != '0');
  1524. }
  1525. } else {
  1526. if (mem_blk->online != (strncmp(status, "online", 6) == 0)) {
  1527. const char *new_state = mem_blk->online ? "online" : "offline";
  1528. ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state),
  1529. &local_err);
  1530. if (local_err) {
  1531. error_free(local_err);
  1532. result->response =
  1533. GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED;
  1534. goto out2;
  1535. }
  1536. result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS;
  1537. result->has_error_code = false;
  1538. } /* otherwise pretend successful re-(on|off)-lining */
  1539. }
  1540. g_free(status);
  1541. close(dirfd);
  1542. return;
  1543. out2:
  1544. g_free(status);
  1545. close(dirfd);
  1546. out1:
  1547. if (!sys2memblk) {
  1548. result->has_error_code = true;
  1549. result->error_code = errno;
  1550. }
  1551. }
  1552. GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
  1553. {
  1554. GuestMemoryBlockList *head, **tail;
  1555. Error *local_err = NULL;
  1556. struct dirent *de;
  1557. DIR *dp;
  1558. head = NULL;
  1559. tail = &head;
  1560. dp = opendir("/sys/devices/system/memory/");
  1561. if (!dp) {
  1562. /* it's ok if this happens to be a system that doesn't expose
  1563. * memory blocks via sysfs, but otherwise we should report
  1564. * an error
  1565. */
  1566. if (errno != ENOENT) {
  1567. error_setg_errno(errp, errno, "Can't open directory"
  1568. "\"/sys/devices/system/memory/\"");
  1569. }
  1570. return NULL;
  1571. }
  1572. /* Note: the phys_index of memory block may be discontinuous,
  1573. * this is because a memblk is the unit of the Sparse Memory design, which
  1574. * allows discontinuous memory ranges (ex. NUMA), so here we should
  1575. * traverse the memory block directory.
  1576. */
  1577. while ((de = readdir(dp)) != NULL) {
  1578. GuestMemoryBlock *mem_blk;
  1579. if ((strncmp(de->d_name, "memory", 6) != 0) ||
  1580. !(de->d_type & DT_DIR)) {
  1581. continue;
  1582. }
  1583. mem_blk = g_malloc0(sizeof *mem_blk);
  1584. /* The d_name is "memoryXXX", phys_index is block id, same as XXX */
  1585. mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10);
  1586. mem_blk->has_can_offline = true; /* lolspeak ftw */
  1587. transfer_memory_block(mem_blk, true, NULL, &local_err);
  1588. if (local_err) {
  1589. break;
  1590. }
  1591. QAPI_LIST_APPEND(tail, mem_blk);
  1592. }
  1593. closedir(dp);
  1594. if (local_err == NULL) {
  1595. /* there's no guest with zero memory blocks */
  1596. if (head == NULL) {
  1597. error_setg(errp, "guest reported zero memory blocks!");
  1598. }
  1599. return head;
  1600. }
  1601. qapi_free_GuestMemoryBlockList(head);
  1602. error_propagate(errp, local_err);
  1603. return NULL;
  1604. }
  1605. GuestMemoryBlockResponseList *
  1606. qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
  1607. {
  1608. GuestMemoryBlockResponseList *head, **tail;
  1609. Error *local_err = NULL;
  1610. head = NULL;
  1611. tail = &head;
  1612. while (mem_blks != NULL) {
  1613. GuestMemoryBlockResponse *result;
  1614. GuestMemoryBlock *current_mem_blk = mem_blks->value;
  1615. result = g_malloc0(sizeof(*result));
  1616. result->phys_index = current_mem_blk->phys_index;
  1617. transfer_memory_block(current_mem_blk, false, result, &local_err);
  1618. if (local_err) { /* should never happen */
  1619. goto err;
  1620. }
  1621. QAPI_LIST_APPEND(tail, result);
  1622. mem_blks = mem_blks->next;
  1623. }
  1624. return head;
  1625. err:
  1626. qapi_free_GuestMemoryBlockResponseList(head);
  1627. error_propagate(errp, local_err);
  1628. return NULL;
  1629. }
  1630. GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
  1631. {
  1632. Error *local_err = NULL;
  1633. char *dirpath;
  1634. int dirfd;
  1635. char *buf;
  1636. GuestMemoryBlockInfo *info;
  1637. dirpath = g_strdup_printf("/sys/devices/system/memory/");
  1638. dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
  1639. if (dirfd == -1) {
  1640. error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
  1641. g_free(dirpath);
  1642. return NULL;
  1643. }
  1644. g_free(dirpath);
  1645. buf = g_malloc0(20);
  1646. ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err);
  1647. close(dirfd);
  1648. if (local_err) {
  1649. g_free(buf);
  1650. error_propagate(errp, local_err);
  1651. return NULL;
  1652. }
  1653. info = g_new0(GuestMemoryBlockInfo, 1);
  1654. info->size = strtol(buf, NULL, 16); /* the unit is bytes */
  1655. g_free(buf);
  1656. return info;
  1657. }
  1658. #define MAX_NAME_LEN 128
  1659. static GuestDiskStatsInfoList *guest_get_diskstats(Error **errp)
  1660. {
  1661. GuestDiskStatsInfoList *head = NULL, **tail = &head;
  1662. const char *diskstats = "/proc/diskstats";
  1663. FILE *fp;
  1664. size_t n;
  1665. char *line = NULL;
  1666. fp = fopen(diskstats, "r");
  1667. if (fp == NULL) {
  1668. error_setg_errno(errp, errno, "open(\"%s\")", diskstats);
  1669. return NULL;
  1670. }
  1671. while (getline(&line, &n, fp) != -1) {
  1672. g_autofree GuestDiskStatsInfo *diskstatinfo = NULL;
  1673. g_autofree GuestDiskStats *diskstat = NULL;
  1674. char dev_name[MAX_NAME_LEN];
  1675. unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks, dc_ticks, fl_ticks;
  1676. unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
  1677. unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec;
  1678. unsigned long dc_ios, dc_merges, dc_sec, fl_ios;
  1679. unsigned int major, minor;
  1680. int i;
  1681. i = sscanf(line, "%u %u %s %lu %lu %lu"
  1682. "%lu %lu %lu %lu %u %u %u %u"
  1683. "%lu %lu %lu %u %lu %u",
  1684. &major, &minor, dev_name,
  1685. &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios,
  1686. &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec,
  1687. &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks,
  1688. &dc_ios, &dc_merges, &dc_sec, &dc_ticks,
  1689. &fl_ios, &fl_ticks);
  1690. if (i < 7) {
  1691. continue;
  1692. }
  1693. diskstatinfo = g_new0(GuestDiskStatsInfo, 1);
  1694. diskstatinfo->name = g_strdup(dev_name);
  1695. diskstatinfo->major = major;
  1696. diskstatinfo->minor = minor;
  1697. diskstat = g_new0(GuestDiskStats, 1);
  1698. if (i == 7) {
  1699. diskstat->has_read_ios = true;
  1700. diskstat->read_ios = rd_ios;
  1701. diskstat->has_read_sectors = true;
  1702. diskstat->read_sectors = rd_merges_or_rd_sec;
  1703. diskstat->has_write_ios = true;
  1704. diskstat->write_ios = rd_sec_or_wr_ios;
  1705. diskstat->has_write_sectors = true;
  1706. diskstat->write_sectors = rd_ticks_or_wr_sec;
  1707. }
  1708. if (i >= 14) {
  1709. diskstat->has_read_ios = true;
  1710. diskstat->read_ios = rd_ios;
  1711. diskstat->has_read_sectors = true;
  1712. diskstat->read_sectors = rd_sec_or_wr_ios;
  1713. diskstat->has_read_merges = true;
  1714. diskstat->read_merges = rd_merges_or_rd_sec;
  1715. diskstat->has_read_ticks = true;
  1716. diskstat->read_ticks = rd_ticks_or_wr_sec;
  1717. diskstat->has_write_ios = true;
  1718. diskstat->write_ios = wr_ios;
  1719. diskstat->has_write_sectors = true;
  1720. diskstat->write_sectors = wr_sec;
  1721. diskstat->has_write_merges = true;
  1722. diskstat->write_merges = wr_merges;
  1723. diskstat->has_write_ticks = true;
  1724. diskstat->write_ticks = wr_ticks;
  1725. diskstat->has_ios_pgr = true;
  1726. diskstat->ios_pgr = ios_pgr;
  1727. diskstat->has_total_ticks = true;
  1728. diskstat->total_ticks = tot_ticks;
  1729. diskstat->has_weight_ticks = true;
  1730. diskstat->weight_ticks = rq_ticks;
  1731. }
  1732. if (i >= 18) {
  1733. diskstat->has_discard_ios = true;
  1734. diskstat->discard_ios = dc_ios;
  1735. diskstat->has_discard_merges = true;
  1736. diskstat->discard_merges = dc_merges;
  1737. diskstat->has_discard_sectors = true;
  1738. diskstat->discard_sectors = dc_sec;
  1739. diskstat->has_discard_ticks = true;
  1740. diskstat->discard_ticks = dc_ticks;
  1741. }
  1742. if (i >= 20) {
  1743. diskstat->has_flush_ios = true;
  1744. diskstat->flush_ios = fl_ios;
  1745. diskstat->has_flush_ticks = true;
  1746. diskstat->flush_ticks = fl_ticks;
  1747. }
  1748. diskstatinfo->stats = g_steal_pointer(&diskstat);
  1749. QAPI_LIST_APPEND(tail, diskstatinfo);
  1750. diskstatinfo = NULL;
  1751. }
  1752. free(line);
  1753. fclose(fp);
  1754. return head;
  1755. }
  1756. GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
  1757. {
  1758. return guest_get_diskstats(errp);
  1759. }
  1760. GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
  1761. {
  1762. GuestCpuStatsList *head = NULL, **tail = &head;
  1763. const char *cpustats = "/proc/stat";
  1764. int clk_tck = sysconf(_SC_CLK_TCK);
  1765. FILE *fp;
  1766. size_t n;
  1767. char *line = NULL;
  1768. fp = fopen(cpustats, "r");
  1769. if (fp == NULL) {
  1770. error_setg_errno(errp, errno, "open(\"%s\")", cpustats);
  1771. return NULL;
  1772. }
  1773. while (getline(&line, &n, fp) != -1) {
  1774. GuestCpuStats *cpustat = NULL;
  1775. GuestLinuxCpuStats *linuxcpustat;
  1776. int i;
  1777. unsigned long user, system, idle, iowait, irq, softirq, steal, guest;
  1778. unsigned long nice, guest_nice;
  1779. char name[64];
  1780. i = sscanf(line, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
  1781. name, &user, &nice, &system, &idle, &iowait, &irq, &softirq,
  1782. &steal, &guest, &guest_nice);
  1783. /* drop "cpu 1 2 3 ...", get "cpuX 1 2 3 ..." only */
  1784. if ((i == EOF) || strncmp(name, "cpu", 3) || (name[3] == '\0')) {
  1785. continue;
  1786. }
  1787. if (i < 5) {
  1788. slog("Parsing cpu stat from %s failed, see \"man proc\"", cpustats);
  1789. break;
  1790. }
  1791. cpustat = g_new0(GuestCpuStats, 1);
  1792. cpustat->type = GUEST_CPU_STATS_TYPE_LINUX;
  1793. linuxcpustat = &cpustat->u.q_linux;
  1794. linuxcpustat->cpu = atoi(&name[3]);
  1795. linuxcpustat->user = user * 1000 / clk_tck;
  1796. linuxcpustat->nice = nice * 1000 / clk_tck;
  1797. linuxcpustat->system = system * 1000 / clk_tck;
  1798. linuxcpustat->idle = idle * 1000 / clk_tck;
  1799. if (i > 5) {
  1800. linuxcpustat->has_iowait = true;
  1801. linuxcpustat->iowait = iowait * 1000 / clk_tck;
  1802. }
  1803. if (i > 6) {
  1804. linuxcpustat->has_irq = true;
  1805. linuxcpustat->irq = irq * 1000 / clk_tck;
  1806. linuxcpustat->has_softirq = true;
  1807. linuxcpustat->softirq = softirq * 1000 / clk_tck;
  1808. }
  1809. if (i > 8) {
  1810. linuxcpustat->has_steal = true;
  1811. linuxcpustat->steal = steal * 1000 / clk_tck;
  1812. }
  1813. if (i > 9) {
  1814. linuxcpustat->has_guest = true;
  1815. linuxcpustat->guest = guest * 1000 / clk_tck;
  1816. }
  1817. if (i > 10) {
  1818. linuxcpustat->has_guest = true;
  1819. linuxcpustat->guest = guest * 1000 / clk_tck;
  1820. linuxcpustat->has_guestnice = true;
  1821. linuxcpustat->guestnice = guest_nice * 1000 / clk_tck;
  1822. }
  1823. QAPI_LIST_APPEND(tail, cpustat);
  1824. }
  1825. free(line);
  1826. fclose(fp);
  1827. return head;
  1828. }
  1829. static char *hexToIPAddress(const void *hexValue, int is_ipv6)
  1830. {
  1831. if (is_ipv6) {
  1832. char addr[INET6_ADDRSTRLEN];
  1833. struct in6_addr in6;
  1834. const char *hexStr = (const char *)hexValue;
  1835. int i;
  1836. for (i = 0; i < 16; i++) {
  1837. sscanf(&hexStr[i * 2], "%02hhx", &in6.s6_addr[i]);
  1838. }
  1839. inet_ntop(AF_INET6, &in6, addr, INET6_ADDRSTRLEN);
  1840. return g_strdup(addr);
  1841. } else {
  1842. unsigned int hexInt = *(unsigned int *)hexValue;
  1843. unsigned int byte1 = (hexInt >> 24) & 0xFF;
  1844. unsigned int byte2 = (hexInt >> 16) & 0xFF;
  1845. unsigned int byte3 = (hexInt >> 8) & 0xFF;
  1846. unsigned int byte4 = hexInt & 0xFF;
  1847. return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
  1848. }
  1849. }
  1850. GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
  1851. {
  1852. GuestNetworkRouteList *head = NULL, **tail = &head;
  1853. const char *routeFiles[] = {"/proc/net/route", "/proc/net/ipv6_route"};
  1854. FILE *fp;
  1855. size_t n;
  1856. char *line = NULL;
  1857. int firstLine;
  1858. int is_ipv6;
  1859. int i;
  1860. for (i = 0; i < 2; i++) {
  1861. firstLine = 1;
  1862. is_ipv6 = (i == 1);
  1863. fp = fopen(routeFiles[i], "r");
  1864. if (fp == NULL) {
  1865. error_setg_errno(errp, errno, "open(\"%s\")", routeFiles[i]);
  1866. free(line);
  1867. continue;
  1868. }
  1869. while (getline(&line, &n, fp) != -1) {
  1870. if (firstLine && !is_ipv6) {
  1871. firstLine = 0;
  1872. continue;
  1873. }
  1874. GuestNetworkRoute *route = NULL;
  1875. GuestNetworkRoute *networkroute;
  1876. char Iface[IFNAMSIZ];
  1877. if (is_ipv6) {
  1878. char Destination[33], Source[33], NextHop[33];
  1879. int DesPrefixlen, SrcPrefixlen, Metric, RefCnt, Use, Flags;
  1880. /* Parse the line and extract the values */
  1881. if (sscanf(line, "%32s %x %32s %x %32s %x %x %x %x %s",
  1882. Destination, &DesPrefixlen, Source,
  1883. &SrcPrefixlen, NextHop, &Metric, &RefCnt,
  1884. &Use, &Flags, Iface) != 10) {
  1885. continue;
  1886. }
  1887. route = g_new0(GuestNetworkRoute, 1);
  1888. networkroute = route;
  1889. networkroute->iface = g_strdup(Iface);
  1890. networkroute->destination = hexToIPAddress(Destination, 1);
  1891. networkroute->metric = Metric;
  1892. networkroute->source = hexToIPAddress(Source, 1);
  1893. networkroute->desprefixlen = g_strdup_printf(
  1894. "%d", DesPrefixlen
  1895. );
  1896. networkroute->srcprefixlen = g_strdup_printf(
  1897. "%d", SrcPrefixlen
  1898. );
  1899. networkroute->nexthop = hexToIPAddress(NextHop, 1);
  1900. networkroute->has_flags = true;
  1901. networkroute->flags = Flags;
  1902. networkroute->has_refcnt = true;
  1903. networkroute->refcnt = RefCnt;
  1904. networkroute->has_use = true;
  1905. networkroute->use = Use;
  1906. networkroute->version = 6;
  1907. } else {
  1908. unsigned int Destination, Gateway, Mask, Flags;
  1909. int RefCnt, Use, Metric, MTU, Window, IRTT;
  1910. /* Parse the line and extract the values */
  1911. if (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
  1912. Iface, &Destination, &Gateway, &Flags, &RefCnt,
  1913. &Use, &Metric, &Mask, &MTU, &Window, &IRTT) != 11) {
  1914. continue;
  1915. }
  1916. route = g_new0(GuestNetworkRoute, 1);
  1917. networkroute = route;
  1918. networkroute->iface = g_strdup(Iface);
  1919. networkroute->destination = hexToIPAddress(&Destination, 0);
  1920. networkroute->gateway = hexToIPAddress(&Gateway, 0);
  1921. networkroute->mask = hexToIPAddress(&Mask, 0);
  1922. networkroute->metric = Metric;
  1923. networkroute->has_flags = true;
  1924. networkroute->flags = Flags;
  1925. networkroute->has_refcnt = true;
  1926. networkroute->refcnt = RefCnt;
  1927. networkroute->has_use = true;
  1928. networkroute->use = Use;
  1929. networkroute->has_mtu = true;
  1930. networkroute->mtu = MTU;
  1931. networkroute->has_window = true;
  1932. networkroute->window = Window;
  1933. networkroute->has_irtt = true;
  1934. networkroute->irtt = IRTT;
  1935. networkroute->version = 4;
  1936. }
  1937. QAPI_LIST_APPEND(tail, route);
  1938. }
  1939. free(line);
  1940. fclose(fp);
  1941. }
  1942. return head;
  1943. }