1 /* 2 * QEMU Guest Agent POSIX-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 14 #include <glib.h> 15 #include <sys/types.h> 16 #include <sys/ioctl.h> 17 #include <sys/wait.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <dirent.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <sys/stat.h> 25 #include <inttypes.h> 26 #include "qga/guest-agent-core.h" 27 #include "qga-qmp-commands.h" 28 #include "qapi/qmp/qerror.h" 29 #include "qemu/queue.h" 30 #include "qemu/host-utils.h" 31 #include "qemu/sockets.h" 32 #include "qemu/base64.h" 33 34 #ifndef CONFIG_HAS_ENVIRON 35 #ifdef __APPLE__ 36 #include <crt_externs.h> 37 #define environ (*_NSGetEnviron()) 38 #else 39 extern char **environ; 40 #endif 41 #endif 42 43 #if defined(__linux__) 44 #include <mntent.h> 45 #include <linux/fs.h> 46 #include <ifaddrs.h> 47 #include <arpa/inet.h> 48 #include <sys/socket.h> 49 #include <net/if.h> 50 51 #ifdef FIFREEZE 52 #define CONFIG_FSFREEZE 53 #endif 54 #ifdef FITRIM 55 #define CONFIG_FSTRIM 56 #endif 57 #endif 58 59 static void ga_wait_child(pid_t pid, int *status, Error **errp) 60 { 61 pid_t rpid; 62 63 *status = 0; 64 65 do { 66 rpid = waitpid(pid, status, 0); 67 } while (rpid == -1 && errno == EINTR); 68 69 if (rpid == -1) { 70 error_setg_errno(errp, errno, "failed to wait for child (pid: %d)", 71 pid); 72 return; 73 } 74 75 g_assert(rpid == pid); 76 } 77 78 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp) 79 { 80 const char *shutdown_flag; 81 Error *local_err = NULL; 82 pid_t pid; 83 int status; 84 85 slog("guest-shutdown called, mode: %s", mode); 86 if (!has_mode || strcmp(mode, "powerdown") == 0) { 87 shutdown_flag = "-P"; 88 } else if (strcmp(mode, "halt") == 0) { 89 shutdown_flag = "-H"; 90 } else if (strcmp(mode, "reboot") == 0) { 91 shutdown_flag = "-r"; 92 } else { 93 error_setg(errp, 94 "mode is invalid (valid values are: halt|powerdown|reboot"); 95 return; 96 } 97 98 pid = fork(); 99 if (pid == 0) { 100 /* child, start the shutdown */ 101 setsid(); 102 reopen_fd_to_null(0); 103 reopen_fd_to_null(1); 104 reopen_fd_to_null(2); 105 106 execle("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0", 107 "hypervisor initiated shutdown", (char*)NULL, environ); 108 _exit(EXIT_FAILURE); 109 } else if (pid < 0) { 110 error_setg_errno(errp, errno, "failed to create child process"); 111 return; 112 } 113 114 ga_wait_child(pid, &status, &local_err); 115 if (local_err) { 116 error_propagate(errp, local_err); 117 return; 118 } 119 120 if (!WIFEXITED(status)) { 121 error_setg(errp, "child process has terminated abnormally"); 122 return; 123 } 124 125 if (WEXITSTATUS(status)) { 126 error_setg(errp, "child process has failed to shutdown"); 127 return; 128 } 129 130 /* succeeded */ 131 } 132 133 int64_t qmp_guest_get_time(Error **errp) 134 { 135 int ret; 136 qemu_timeval tq; 137 int64_t time_ns; 138 139 ret = qemu_gettimeofday(&tq); 140 if (ret < 0) { 141 error_setg_errno(errp, errno, "Failed to get time"); 142 return -1; 143 } 144 145 time_ns = tq.tv_sec * 1000000000LL + tq.tv_usec * 1000; 146 return time_ns; 147 } 148 149 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) 150 { 151 int ret; 152 int status; 153 pid_t pid; 154 Error *local_err = NULL; 155 struct timeval tv; 156 157 /* If user has passed a time, validate and set it. */ 158 if (has_time) { 159 GDate date = { 0, }; 160 161 /* year-2038 will overflow in case time_t is 32bit */ 162 if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) { 163 error_setg(errp, "Time %" PRId64 " is too large", time_ns); 164 return; 165 } 166 167 tv.tv_sec = time_ns / 1000000000; 168 tv.tv_usec = (time_ns % 1000000000) / 1000; 169 g_date_set_time_t(&date, tv.tv_sec); 170 if (date.year < 1970 || date.year >= 2070) { 171 error_setg_errno(errp, errno, "Invalid time"); 172 return; 173 } 174 175 ret = settimeofday(&tv, NULL); 176 if (ret < 0) { 177 error_setg_errno(errp, errno, "Failed to set time to guest"); 178 return; 179 } 180 } 181 182 /* Now, if user has passed a time to set and the system time is set, we 183 * just need to synchronize the hardware clock. However, if no time was 184 * passed, user is requesting the opposite: set the system time from the 185 * hardware clock (RTC). */ 186 pid = fork(); 187 if (pid == 0) { 188 setsid(); 189 reopen_fd_to_null(0); 190 reopen_fd_to_null(1); 191 reopen_fd_to_null(2); 192 193 /* Use '/sbin/hwclock -w' to set RTC from the system time, 194 * or '/sbin/hwclock -s' to set the system time from RTC. */ 195 execle("/sbin/hwclock", "hwclock", has_time ? "-w" : "-s", 196 NULL, environ); 197 _exit(EXIT_FAILURE); 198 } else if (pid < 0) { 199 error_setg_errno(errp, errno, "failed to create child process"); 200 return; 201 } 202 203 ga_wait_child(pid, &status, &local_err); 204 if (local_err) { 205 error_propagate(errp, local_err); 206 return; 207 } 208 209 if (!WIFEXITED(status)) { 210 error_setg(errp, "child process has terminated abnormally"); 211 return; 212 } 213 214 if (WEXITSTATUS(status)) { 215 error_setg(errp, "hwclock failed to set hardware clock to system time"); 216 return; 217 } 218 } 219 220 typedef enum { 221 RW_STATE_NEW, 222 RW_STATE_READING, 223 RW_STATE_WRITING, 224 } RwState; 225 226 typedef struct GuestFileHandle { 227 uint64_t id; 228 FILE *fh; 229 RwState state; 230 QTAILQ_ENTRY(GuestFileHandle) next; 231 } GuestFileHandle; 232 233 static struct { 234 QTAILQ_HEAD(, GuestFileHandle) filehandles; 235 } guest_file_state = { 236 .filehandles = QTAILQ_HEAD_INITIALIZER(guest_file_state.filehandles), 237 }; 238 239 static int64_t guest_file_handle_add(FILE *fh, Error **errp) 240 { 241 GuestFileHandle *gfh; 242 int64_t handle; 243 244 handle = ga_get_fd_handle(ga_state, errp); 245 if (handle < 0) { 246 return -1; 247 } 248 249 gfh = g_new0(GuestFileHandle, 1); 250 gfh->id = handle; 251 gfh->fh = fh; 252 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); 253 254 return handle; 255 } 256 257 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) 258 { 259 GuestFileHandle *gfh; 260 261 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) 262 { 263 if (gfh->id == id) { 264 return gfh; 265 } 266 } 267 268 error_setg(errp, "handle '%" PRId64 "' has not been found", id); 269 return NULL; 270 } 271 272 typedef const char * const ccpc; 273 274 #ifndef O_BINARY 275 #define O_BINARY 0 276 #endif 277 278 /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */ 279 static const struct { 280 ccpc *forms; 281 int oflag_base; 282 } guest_file_open_modes[] = { 283 { (ccpc[]){ "r", NULL }, O_RDONLY }, 284 { (ccpc[]){ "rb", NULL }, O_RDONLY | O_BINARY }, 285 { (ccpc[]){ "w", NULL }, O_WRONLY | O_CREAT | O_TRUNC }, 286 { (ccpc[]){ "wb", NULL }, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY }, 287 { (ccpc[]){ "a", NULL }, O_WRONLY | O_CREAT | O_APPEND }, 288 { (ccpc[]){ "ab", NULL }, O_WRONLY | O_CREAT | O_APPEND | O_BINARY }, 289 { (ccpc[]){ "r+", NULL }, O_RDWR }, 290 { (ccpc[]){ "rb+", "r+b", NULL }, O_RDWR | O_BINARY }, 291 { (ccpc[]){ "w+", NULL }, O_RDWR | O_CREAT | O_TRUNC }, 292 { (ccpc[]){ "wb+", "w+b", NULL }, O_RDWR | O_CREAT | O_TRUNC | O_BINARY }, 293 { (ccpc[]){ "a+", NULL }, O_RDWR | O_CREAT | O_APPEND }, 294 { (ccpc[]){ "ab+", "a+b", NULL }, O_RDWR | O_CREAT | O_APPEND | O_BINARY } 295 }; 296 297 static int 298 find_open_flag(const char *mode_str, Error **errp) 299 { 300 unsigned mode; 301 302 for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { 303 ccpc *form; 304 305 form = guest_file_open_modes[mode].forms; 306 while (*form != NULL && strcmp(*form, mode_str) != 0) { 307 ++form; 308 } 309 if (*form != NULL) { 310 break; 311 } 312 } 313 314 if (mode == ARRAY_SIZE(guest_file_open_modes)) { 315 error_setg(errp, "invalid file open mode '%s'", mode_str); 316 return -1; 317 } 318 return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK; 319 } 320 321 #define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \ 322 S_IRGRP | S_IWGRP | \ 323 S_IROTH | S_IWOTH) 324 325 static FILE * 326 safe_open_or_create(const char *path, const char *mode, Error **errp) 327 { 328 Error *local_err = NULL; 329 int oflag; 330 331 oflag = find_open_flag(mode, &local_err); 332 if (local_err == NULL) { 333 int fd; 334 335 /* If the caller wants / allows creation of a new file, we implement it 336 * with a two step process: open() + (open() / fchmod()). 337 * 338 * First we insist on creating the file exclusively as a new file. If 339 * that succeeds, we're free to set any file-mode bits on it. (The 340 * motivation is that we want to set those file-mode bits independently 341 * of the current umask.) 342 * 343 * If the exclusive creation fails because the file already exists 344 * (EEXIST is not possible for any other reason), we just attempt to 345 * open the file, but in this case we won't be allowed to change the 346 * file-mode bits on the preexistent file. 347 * 348 * The pathname should never disappear between the two open()s in 349 * practice. If it happens, then someone very likely tried to race us. 350 * In this case just go ahead and report the ENOENT from the second 351 * open() to the caller. 352 * 353 * If the caller wants to open a preexistent file, then the first 354 * open() is decisive and its third argument is ignored, and the second 355 * open() and the fchmod() are never called. 356 */ 357 fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0); 358 if (fd == -1 && errno == EEXIST) { 359 oflag &= ~(unsigned)O_CREAT; 360 fd = open(path, oflag); 361 } 362 363 if (fd == -1) { 364 error_setg_errno(&local_err, errno, "failed to open file '%s' " 365 "(mode: '%s')", path, mode); 366 } else { 367 qemu_set_cloexec(fd); 368 369 if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) { 370 error_setg_errno(&local_err, errno, "failed to set permission " 371 "0%03o on new file '%s' (mode: '%s')", 372 (unsigned)DEFAULT_NEW_FILE_MODE, path, mode); 373 } else { 374 FILE *f; 375 376 f = fdopen(fd, mode); 377 if (f == NULL) { 378 error_setg_errno(&local_err, errno, "failed to associate " 379 "stdio stream with file descriptor %d, " 380 "file '%s' (mode: '%s')", fd, path, mode); 381 } else { 382 return f; 383 } 384 } 385 386 close(fd); 387 if (oflag & O_CREAT) { 388 unlink(path); 389 } 390 } 391 } 392 393 error_propagate(errp, local_err); 394 return NULL; 395 } 396 397 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, 398 Error **errp) 399 { 400 FILE *fh; 401 Error *local_err = NULL; 402 int64_t handle; 403 404 if (!has_mode) { 405 mode = "r"; 406 } 407 slog("guest-file-open called, filepath: %s, mode: %s", path, mode); 408 fh = safe_open_or_create(path, mode, &local_err); 409 if (local_err != NULL) { 410 error_propagate(errp, local_err); 411 return -1; 412 } 413 414 /* set fd non-blocking to avoid common use cases (like reading from a 415 * named pipe) from hanging the agent 416 */ 417 qemu_set_nonblock(fileno(fh)); 418 419 handle = guest_file_handle_add(fh, errp); 420 if (handle < 0) { 421 fclose(fh); 422 return -1; 423 } 424 425 slog("guest-file-open, handle: %" PRId64, handle); 426 return handle; 427 } 428 429 void qmp_guest_file_close(int64_t handle, Error **errp) 430 { 431 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 432 int ret; 433 434 slog("guest-file-close called, handle: %" PRId64, handle); 435 if (!gfh) { 436 return; 437 } 438 439 ret = fclose(gfh->fh); 440 if (ret == EOF) { 441 error_setg_errno(errp, errno, "failed to close handle"); 442 return; 443 } 444 445 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next); 446 g_free(gfh); 447 } 448 449 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, 450 int64_t count, Error **errp) 451 { 452 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 453 GuestFileRead *read_data = NULL; 454 guchar *buf; 455 FILE *fh; 456 size_t read_count; 457 458 if (!gfh) { 459 return NULL; 460 } 461 462 if (!has_count) { 463 count = QGA_READ_COUNT_DEFAULT; 464 } else if (count < 0) { 465 error_setg(errp, "value '%" PRId64 "' is invalid for argument count", 466 count); 467 return NULL; 468 } 469 470 fh = gfh->fh; 471 472 /* explicitly flush when switching from writing to reading */ 473 if (gfh->state == RW_STATE_WRITING) { 474 int ret = fflush(fh); 475 if (ret == EOF) { 476 error_setg_errno(errp, errno, "failed to flush file"); 477 return NULL; 478 } 479 gfh->state = RW_STATE_NEW; 480 } 481 482 buf = g_malloc0(count+1); 483 read_count = fread(buf, 1, count, fh); 484 if (ferror(fh)) { 485 error_setg_errno(errp, errno, "failed to read file"); 486 slog("guest-file-read failed, handle: %" PRId64, handle); 487 } else { 488 buf[read_count] = 0; 489 read_data = g_new0(GuestFileRead, 1); 490 read_data->count = read_count; 491 read_data->eof = feof(fh); 492 if (read_count) { 493 read_data->buf_b64 = g_base64_encode(buf, read_count); 494 } 495 gfh->state = RW_STATE_READING; 496 } 497 g_free(buf); 498 clearerr(fh); 499 500 return read_data; 501 } 502 503 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, 504 bool has_count, int64_t count, 505 Error **errp) 506 { 507 GuestFileWrite *write_data = NULL; 508 guchar *buf; 509 gsize buf_len; 510 int write_count; 511 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 512 FILE *fh; 513 514 if (!gfh) { 515 return NULL; 516 } 517 518 fh = gfh->fh; 519 520 if (gfh->state == RW_STATE_READING) { 521 int ret = fseek(fh, 0, SEEK_CUR); 522 if (ret == -1) { 523 error_setg_errno(errp, errno, "failed to seek file"); 524 return NULL; 525 } 526 gfh->state = RW_STATE_NEW; 527 } 528 529 buf = qbase64_decode(buf_b64, -1, &buf_len, errp); 530 if (!buf) { 531 return NULL; 532 } 533 534 if (!has_count) { 535 count = buf_len; 536 } else if (count < 0 || count > buf_len) { 537 error_setg(errp, "value '%" PRId64 "' is invalid for argument count", 538 count); 539 g_free(buf); 540 return NULL; 541 } 542 543 write_count = fwrite(buf, 1, count, fh); 544 if (ferror(fh)) { 545 error_setg_errno(errp, errno, "failed to write to file"); 546 slog("guest-file-write failed, handle: %" PRId64, handle); 547 } else { 548 write_data = g_new0(GuestFileWrite, 1); 549 write_data->count = write_count; 550 write_data->eof = feof(fh); 551 gfh->state = RW_STATE_WRITING; 552 } 553 g_free(buf); 554 clearerr(fh); 555 556 return write_data; 557 } 558 559 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, 560 int64_t whence_code, Error **errp) 561 { 562 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 563 GuestFileSeek *seek_data = NULL; 564 FILE *fh; 565 int ret; 566 int whence; 567 568 if (!gfh) { 569 return NULL; 570 } 571 572 /* We stupidly exposed 'whence':'int' in our qapi */ 573 switch (whence_code) { 574 case QGA_SEEK_SET: 575 whence = SEEK_SET; 576 break; 577 case QGA_SEEK_CUR: 578 whence = SEEK_CUR; 579 break; 580 case QGA_SEEK_END: 581 whence = SEEK_END; 582 break; 583 default: 584 error_setg(errp, "invalid whence code %"PRId64, whence_code); 585 return NULL; 586 } 587 588 fh = gfh->fh; 589 ret = fseek(fh, offset, whence); 590 if (ret == -1) { 591 error_setg_errno(errp, errno, "failed to seek file"); 592 if (errno == ESPIPE) { 593 /* file is non-seekable, stdio shouldn't be buffering anyways */ 594 gfh->state = RW_STATE_NEW; 595 } 596 } else { 597 seek_data = g_new0(GuestFileSeek, 1); 598 seek_data->position = ftell(fh); 599 seek_data->eof = feof(fh); 600 gfh->state = RW_STATE_NEW; 601 } 602 clearerr(fh); 603 604 return seek_data; 605 } 606 607 void qmp_guest_file_flush(int64_t handle, Error **errp) 608 { 609 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 610 FILE *fh; 611 int ret; 612 613 if (!gfh) { 614 return; 615 } 616 617 fh = gfh->fh; 618 ret = fflush(fh); 619 if (ret == EOF) { 620 error_setg_errno(errp, errno, "failed to flush file"); 621 } else { 622 gfh->state = RW_STATE_NEW; 623 } 624 } 625 626 /* linux-specific implementations. avoid this if at all possible. */ 627 #if defined(__linux__) 628 629 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 630 typedef struct FsMount { 631 char *dirname; 632 char *devtype; 633 unsigned int devmajor, devminor; 634 QTAILQ_ENTRY(FsMount) next; 635 } FsMount; 636 637 typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList; 638 639 static void free_fs_mount_list(FsMountList *mounts) 640 { 641 FsMount *mount, *temp; 642 643 if (!mounts) { 644 return; 645 } 646 647 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 648 QTAILQ_REMOVE(mounts, mount, next); 649 g_free(mount->dirname); 650 g_free(mount->devtype); 651 g_free(mount); 652 } 653 } 654 655 static int dev_major_minor(const char *devpath, 656 unsigned int *devmajor, unsigned int *devminor) 657 { 658 struct stat st; 659 660 *devmajor = 0; 661 *devminor = 0; 662 663 if (stat(devpath, &st) < 0) { 664 slog("failed to stat device file '%s': %s", devpath, strerror(errno)); 665 return -1; 666 } 667 if (S_ISDIR(st.st_mode)) { 668 /* It is bind mount */ 669 return -2; 670 } 671 if (S_ISBLK(st.st_mode)) { 672 *devmajor = major(st.st_rdev); 673 *devminor = minor(st.st_rdev); 674 return 0; 675 } 676 return -1; 677 } 678 679 /* 680 * Walk the mount table and build a list of local file systems 681 */ 682 static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) 683 { 684 struct mntent *ment; 685 FsMount *mount; 686 char const *mtab = "/proc/self/mounts"; 687 FILE *fp; 688 unsigned int devmajor, devminor; 689 690 fp = setmntent(mtab, "r"); 691 if (!fp) { 692 error_setg(errp, "failed to open mtab file: '%s'", mtab); 693 return; 694 } 695 696 while ((ment = getmntent(fp))) { 697 /* 698 * An entry which device name doesn't start with a '/' is 699 * either a dummy file system or a network file system. 700 * Add special handling for smbfs and cifs as is done by 701 * coreutils as well. 702 */ 703 if ((ment->mnt_fsname[0] != '/') || 704 (strcmp(ment->mnt_type, "smbfs") == 0) || 705 (strcmp(ment->mnt_type, "cifs") == 0)) { 706 continue; 707 } 708 if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) { 709 /* Skip bind mounts */ 710 continue; 711 } 712 713 mount = g_new0(FsMount, 1); 714 mount->dirname = g_strdup(ment->mnt_dir); 715 mount->devtype = g_strdup(ment->mnt_type); 716 mount->devmajor = devmajor; 717 mount->devminor = devminor; 718 719 QTAILQ_INSERT_TAIL(mounts, mount, next); 720 } 721 722 endmntent(fp); 723 } 724 725 static void decode_mntname(char *name, int len) 726 { 727 int i, j = 0; 728 for (i = 0; i <= len; i++) { 729 if (name[i] != '\\') { 730 name[j++] = name[i]; 731 } else if (name[i + 1] == '\\') { 732 name[j++] = '\\'; 733 i++; 734 } else if (name[i + 1] >= '0' && name[i + 1] <= '3' && 735 name[i + 2] >= '0' && name[i + 2] <= '7' && 736 name[i + 3] >= '0' && name[i + 3] <= '7') { 737 name[j++] = (name[i + 1] - '0') * 64 + 738 (name[i + 2] - '0') * 8 + 739 (name[i + 3] - '0'); 740 i += 3; 741 } else { 742 name[j++] = name[i]; 743 } 744 } 745 } 746 747 static void build_fs_mount_list(FsMountList *mounts, Error **errp) 748 { 749 FsMount *mount; 750 char const *mountinfo = "/proc/self/mountinfo"; 751 FILE *fp; 752 char *line = NULL, *dash; 753 size_t n; 754 char check; 755 unsigned int devmajor, devminor; 756 int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e; 757 758 fp = fopen(mountinfo, "r"); 759 if (!fp) { 760 build_fs_mount_list_from_mtab(mounts, errp); 761 return; 762 } 763 764 while (getline(&line, &n, fp) != -1) { 765 ret = sscanf(line, "%*u %*u %u:%u %*s %n%*s%n%c", 766 &devmajor, &devminor, &dir_s, &dir_e, &check); 767 if (ret < 3) { 768 continue; 769 } 770 dash = strstr(line + dir_e, " - "); 771 if (!dash) { 772 continue; 773 } 774 ret = sscanf(dash, " - %n%*s%n %n%*s%n%c", 775 &type_s, &type_e, &dev_s, &dev_e, &check); 776 if (ret < 1) { 777 continue; 778 } 779 line[dir_e] = 0; 780 dash[type_e] = 0; 781 dash[dev_e] = 0; 782 decode_mntname(line + dir_s, dir_e - dir_s); 783 decode_mntname(dash + dev_s, dev_e - dev_s); 784 if (devmajor == 0) { 785 /* btrfs reports major number = 0 */ 786 if (strcmp("btrfs", dash + type_s) != 0 || 787 dev_major_minor(dash + dev_s, &devmajor, &devminor) < 0) { 788 continue; 789 } 790 } 791 792 mount = g_new0(FsMount, 1); 793 mount->dirname = g_strdup(line + dir_s); 794 mount->devtype = g_strdup(dash + type_s); 795 mount->devmajor = devmajor; 796 mount->devminor = devminor; 797 798 QTAILQ_INSERT_TAIL(mounts, mount, next); 799 } 800 free(line); 801 802 fclose(fp); 803 } 804 #endif 805 806 #if defined(CONFIG_FSFREEZE) 807 808 static char *get_pci_driver(char const *syspath, int pathlen, Error **errp) 809 { 810 char *path; 811 char *dpath; 812 char *driver = NULL; 813 char buf[PATH_MAX]; 814 ssize_t len; 815 816 path = g_strndup(syspath, pathlen); 817 dpath = g_strdup_printf("%s/driver", path); 818 len = readlink(dpath, buf, sizeof(buf) - 1); 819 if (len != -1) { 820 buf[len] = 0; 821 driver = g_strdup(basename(buf)); 822 } 823 g_free(dpath); 824 g_free(path); 825 return driver; 826 } 827 828 static int compare_uint(const void *_a, const void *_b) 829 { 830 unsigned int a = *(unsigned int *)_a; 831 unsigned int b = *(unsigned int *)_b; 832 833 return a < b ? -1 : a > b ? 1 : 0; 834 } 835 836 /* Walk the specified sysfs and build a sorted list of host or ata numbers */ 837 static int build_hosts(char const *syspath, char const *host, bool ata, 838 unsigned int *hosts, int hosts_max, Error **errp) 839 { 840 char *path; 841 DIR *dir; 842 struct dirent *entry; 843 int i = 0; 844 845 path = g_strndup(syspath, host - syspath); 846 dir = opendir(path); 847 if (!dir) { 848 error_setg_errno(errp, errno, "opendir(\"%s\")", path); 849 g_free(path); 850 return -1; 851 } 852 853 while (i < hosts_max) { 854 entry = readdir(dir); 855 if (!entry) { 856 break; 857 } 858 if (ata && sscanf(entry->d_name, "ata%d", hosts + i) == 1) { 859 ++i; 860 } else if (!ata && sscanf(entry->d_name, "host%d", hosts + i) == 1) { 861 ++i; 862 } 863 } 864 865 qsort(hosts, i, sizeof(hosts[0]), compare_uint); 866 867 g_free(path); 868 closedir(dir); 869 return i; 870 } 871 872 /* Store disk device info specified by @sysfs into @fs */ 873 static void build_guest_fsinfo_for_real_device(char const *syspath, 874 GuestFilesystemInfo *fs, 875 Error **errp) 876 { 877 unsigned int pci[4], host, hosts[8], tgt[3]; 878 int i, nhosts = 0, pcilen; 879 GuestDiskAddress *disk; 880 GuestPCIAddress *pciaddr; 881 GuestDiskAddressList *list = NULL; 882 bool has_ata = false, has_host = false, has_tgt = false; 883 char *p, *q, *driver = NULL; 884 885 p = strstr(syspath, "/devices/pci"); 886 if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n", 887 pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) { 888 g_debug("only pci device is supported: sysfs path \"%s\"", syspath); 889 return; 890 } 891 892 driver = get_pci_driver(syspath, (p + 12 + pcilen) - syspath, errp); 893 if (!driver) { 894 goto cleanup; 895 } 896 897 p = strstr(syspath, "/target"); 898 if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u", 899 tgt, tgt + 1, tgt + 2) == 3) { 900 has_tgt = true; 901 } 902 903 p = strstr(syspath, "/ata"); 904 if (p) { 905 q = p + 4; 906 has_ata = true; 907 } else { 908 p = strstr(syspath, "/host"); 909 q = p + 5; 910 } 911 if (p && sscanf(q, "%u", &host) == 1) { 912 has_host = true; 913 nhosts = build_hosts(syspath, p, has_ata, hosts, 914 sizeof(hosts) / sizeof(hosts[0]), errp); 915 if (nhosts < 0) { 916 goto cleanup; 917 } 918 } 919 920 pciaddr = g_malloc0(sizeof(*pciaddr)); 921 pciaddr->domain = pci[0]; 922 pciaddr->bus = pci[1]; 923 pciaddr->slot = pci[2]; 924 pciaddr->function = pci[3]; 925 926 disk = g_malloc0(sizeof(*disk)); 927 disk->pci_controller = pciaddr; 928 929 list = g_malloc0(sizeof(*list)); 930 list->value = disk; 931 932 if (strcmp(driver, "ata_piix") == 0) { 933 /* a host per ide bus, target*:0:<unit>:0 */ 934 if (!has_host || !has_tgt) { 935 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 936 goto cleanup; 937 } 938 for (i = 0; i < nhosts; i++) { 939 if (host == hosts[i]) { 940 disk->bus_type = GUEST_DISK_BUS_TYPE_IDE; 941 disk->bus = i; 942 disk->unit = tgt[1]; 943 break; 944 } 945 } 946 if (i >= nhosts) { 947 g_debug("no host for '%s' (driver '%s')", syspath, driver); 948 goto cleanup; 949 } 950 } else if (strcmp(driver, "sym53c8xx") == 0) { 951 /* scsi(LSI Logic): target*:0:<unit>:0 */ 952 if (!has_tgt) { 953 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 954 goto cleanup; 955 } 956 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 957 disk->unit = tgt[1]; 958 } else if (strcmp(driver, "virtio-pci") == 0) { 959 if (has_tgt) { 960 /* virtio-scsi: target*:0:0:<unit> */ 961 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 962 disk->unit = tgt[2]; 963 } else { 964 /* virtio-blk: 1 disk per 1 device */ 965 disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO; 966 } 967 } else if (strcmp(driver, "ahci") == 0) { 968 /* ahci: 1 host per 1 unit */ 969 if (!has_host || !has_tgt) { 970 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 971 goto cleanup; 972 } 973 for (i = 0; i < nhosts; i++) { 974 if (host == hosts[i]) { 975 disk->unit = i; 976 disk->bus_type = GUEST_DISK_BUS_TYPE_SATA; 977 break; 978 } 979 } 980 if (i >= nhosts) { 981 g_debug("no host for '%s' (driver '%s')", syspath, driver); 982 goto cleanup; 983 } 984 } else { 985 g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath); 986 goto cleanup; 987 } 988 989 list->next = fs->disk; 990 fs->disk = list; 991 g_free(driver); 992 return; 993 994 cleanup: 995 if (list) { 996 qapi_free_GuestDiskAddressList(list); 997 } 998 g_free(driver); 999 } 1000 1001 static void build_guest_fsinfo_for_device(char const *devpath, 1002 GuestFilesystemInfo *fs, 1003 Error **errp); 1004 1005 /* Store a list of slave devices of virtual volume specified by @syspath into 1006 * @fs */ 1007 static void build_guest_fsinfo_for_virtual_device(char const *syspath, 1008 GuestFilesystemInfo *fs, 1009 Error **errp) 1010 { 1011 DIR *dir; 1012 char *dirpath; 1013 struct dirent *entry; 1014 1015 dirpath = g_strdup_printf("%s/slaves", syspath); 1016 dir = opendir(dirpath); 1017 if (!dir) { 1018 error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath); 1019 g_free(dirpath); 1020 return; 1021 } 1022 1023 for (;;) { 1024 errno = 0; 1025 entry = readdir(dir); 1026 if (entry == NULL) { 1027 if (errno) { 1028 error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath); 1029 } 1030 break; 1031 } 1032 1033 if (entry->d_type == DT_LNK) { 1034 char *path; 1035 1036 g_debug(" slave device '%s'", entry->d_name); 1037 path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name); 1038 build_guest_fsinfo_for_device(path, fs, errp); 1039 g_free(path); 1040 1041 if (*errp) { 1042 break; 1043 } 1044 } 1045 } 1046 1047 g_free(dirpath); 1048 closedir(dir); 1049 } 1050 1051 /* Dispatch to functions for virtual/real device */ 1052 static void build_guest_fsinfo_for_device(char const *devpath, 1053 GuestFilesystemInfo *fs, 1054 Error **errp) 1055 { 1056 char *syspath = realpath(devpath, NULL); 1057 1058 if (!syspath) { 1059 error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); 1060 return; 1061 } 1062 1063 if (!fs->name) { 1064 fs->name = g_strdup(basename(syspath)); 1065 } 1066 1067 g_debug(" parse sysfs path '%s'", syspath); 1068 1069 if (strstr(syspath, "/devices/virtual/block/")) { 1070 build_guest_fsinfo_for_virtual_device(syspath, fs, errp); 1071 } else { 1072 build_guest_fsinfo_for_real_device(syspath, fs, errp); 1073 } 1074 1075 free(syspath); 1076 } 1077 1078 /* Return a list of the disk device(s)' info which @mount lies on */ 1079 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, 1080 Error **errp) 1081 { 1082 GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs)); 1083 char *devpath = g_strdup_printf("/sys/dev/block/%u:%u", 1084 mount->devmajor, mount->devminor); 1085 1086 fs->mountpoint = g_strdup(mount->dirname); 1087 fs->type = g_strdup(mount->devtype); 1088 build_guest_fsinfo_for_device(devpath, fs, errp); 1089 1090 g_free(devpath); 1091 return fs; 1092 } 1093 1094 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 1095 { 1096 FsMountList mounts; 1097 struct FsMount *mount; 1098 GuestFilesystemInfoList *new, *ret = NULL; 1099 Error *local_err = NULL; 1100 1101 QTAILQ_INIT(&mounts); 1102 build_fs_mount_list(&mounts, &local_err); 1103 if (local_err) { 1104 error_propagate(errp, local_err); 1105 return NULL; 1106 } 1107 1108 QTAILQ_FOREACH(mount, &mounts, next) { 1109 g_debug("Building guest fsinfo for '%s'", mount->dirname); 1110 1111 new = g_malloc0(sizeof(*ret)); 1112 new->value = build_guest_fsinfo(mount, &local_err); 1113 new->next = ret; 1114 ret = new; 1115 if (local_err) { 1116 error_propagate(errp, local_err); 1117 qapi_free_GuestFilesystemInfoList(ret); 1118 ret = NULL; 1119 break; 1120 } 1121 } 1122 1123 free_fs_mount_list(&mounts); 1124 return ret; 1125 } 1126 1127 1128 typedef enum { 1129 FSFREEZE_HOOK_THAW = 0, 1130 FSFREEZE_HOOK_FREEZE, 1131 } FsfreezeHookArg; 1132 1133 static const char *fsfreeze_hook_arg_string[] = { 1134 "thaw", 1135 "freeze", 1136 }; 1137 1138 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 1139 { 1140 int status; 1141 pid_t pid; 1142 const char *hook; 1143 const char *arg_str = fsfreeze_hook_arg_string[arg]; 1144 Error *local_err = NULL; 1145 1146 hook = ga_fsfreeze_hook(ga_state); 1147 if (!hook) { 1148 return; 1149 } 1150 if (access(hook, X_OK) != 0) { 1151 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 1152 return; 1153 } 1154 1155 slog("executing fsfreeze hook with arg '%s'", arg_str); 1156 pid = fork(); 1157 if (pid == 0) { 1158 setsid(); 1159 reopen_fd_to_null(0); 1160 reopen_fd_to_null(1); 1161 reopen_fd_to_null(2); 1162 1163 execle(hook, hook, arg_str, NULL, environ); 1164 _exit(EXIT_FAILURE); 1165 } else if (pid < 0) { 1166 error_setg_errno(errp, errno, "failed to create child process"); 1167 return; 1168 } 1169 1170 ga_wait_child(pid, &status, &local_err); 1171 if (local_err) { 1172 error_propagate(errp, local_err); 1173 return; 1174 } 1175 1176 if (!WIFEXITED(status)) { 1177 error_setg(errp, "fsfreeze hook has terminated abnormally"); 1178 return; 1179 } 1180 1181 status = WEXITSTATUS(status); 1182 if (status) { 1183 error_setg(errp, "fsfreeze hook has failed with status %d", status); 1184 return; 1185 } 1186 } 1187 1188 /* 1189 * Return status of freeze/thaw 1190 */ 1191 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 1192 { 1193 if (ga_is_frozen(ga_state)) { 1194 return GUEST_FSFREEZE_STATUS_FROZEN; 1195 } 1196 1197 return GUEST_FSFREEZE_STATUS_THAWED; 1198 } 1199 1200 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 1201 { 1202 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 1203 } 1204 1205 /* 1206 * Walk list of mounted file systems in the guest, and freeze the ones which 1207 * are real local file systems. 1208 */ 1209 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 1210 strList *mountpoints, 1211 Error **errp) 1212 { 1213 int ret = 0, i = 0; 1214 strList *list; 1215 FsMountList mounts; 1216 struct FsMount *mount; 1217 Error *local_err = NULL; 1218 int fd; 1219 1220 slog("guest-fsfreeze called"); 1221 1222 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 1223 if (local_err) { 1224 error_propagate(errp, local_err); 1225 return -1; 1226 } 1227 1228 QTAILQ_INIT(&mounts); 1229 build_fs_mount_list(&mounts, &local_err); 1230 if (local_err) { 1231 error_propagate(errp, local_err); 1232 return -1; 1233 } 1234 1235 /* cannot risk guest agent blocking itself on a write in this state */ 1236 ga_set_frozen(ga_state); 1237 1238 QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) { 1239 /* To issue fsfreeze in the reverse order of mounts, check if the 1240 * mount is listed in the list here */ 1241 if (has_mountpoints) { 1242 for (list = mountpoints; list; list = list->next) { 1243 if (strcmp(list->value, mount->dirname) == 0) { 1244 break; 1245 } 1246 } 1247 if (!list) { 1248 continue; 1249 } 1250 } 1251 1252 fd = qemu_open(mount->dirname, O_RDONLY); 1253 if (fd == -1) { 1254 error_setg_errno(errp, errno, "failed to open %s", mount->dirname); 1255 goto error; 1256 } 1257 1258 /* we try to cull filesytems we know won't work in advance, but other 1259 * filesytems may not implement fsfreeze for less obvious reasons. 1260 * these will report EOPNOTSUPP. we simply ignore these when tallying 1261 * the number of frozen filesystems. 1262 * 1263 * any other error means a failure to freeze a filesystem we 1264 * expect to be freezable, so return an error in those cases 1265 * and return system to thawed state. 1266 */ 1267 ret = ioctl(fd, FIFREEZE); 1268 if (ret == -1) { 1269 if (errno != EOPNOTSUPP) { 1270 error_setg_errno(errp, errno, "failed to freeze %s", 1271 mount->dirname); 1272 close(fd); 1273 goto error; 1274 } 1275 } else { 1276 i++; 1277 } 1278 close(fd); 1279 } 1280 1281 free_fs_mount_list(&mounts); 1282 return i; 1283 1284 error: 1285 free_fs_mount_list(&mounts); 1286 qmp_guest_fsfreeze_thaw(NULL); 1287 return 0; 1288 } 1289 1290 /* 1291 * Walk list of frozen file systems in the guest, and thaw them. 1292 */ 1293 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 1294 { 1295 int ret; 1296 FsMountList mounts; 1297 FsMount *mount; 1298 int fd, i = 0, logged; 1299 Error *local_err = NULL; 1300 1301 QTAILQ_INIT(&mounts); 1302 build_fs_mount_list(&mounts, &local_err); 1303 if (local_err) { 1304 error_propagate(errp, local_err); 1305 return 0; 1306 } 1307 1308 QTAILQ_FOREACH(mount, &mounts, next) { 1309 logged = false; 1310 fd = qemu_open(mount->dirname, O_RDONLY); 1311 if (fd == -1) { 1312 continue; 1313 } 1314 /* we have no way of knowing whether a filesystem was actually unfrozen 1315 * as a result of a successful call to FITHAW, only that if an error 1316 * was returned the filesystem was *not* unfrozen by that particular 1317 * call. 1318 * 1319 * since multiple preceding FIFREEZEs require multiple calls to FITHAW 1320 * to unfreeze, continuing issuing FITHAW until an error is returned, 1321 * in which case either the filesystem is in an unfreezable state, or, 1322 * more likely, it was thawed previously (and remains so afterward). 1323 * 1324 * also, since the most recent successful call is the one that did 1325 * the actual unfreeze, we can use this to provide an accurate count 1326 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which 1327 * may * be useful for determining whether a filesystem was unfrozen 1328 * during the freeze/thaw phase by a process other than qemu-ga. 1329 */ 1330 do { 1331 ret = ioctl(fd, FITHAW); 1332 if (ret == 0 && !logged) { 1333 i++; 1334 logged = true; 1335 } 1336 } while (ret == 0); 1337 close(fd); 1338 } 1339 1340 ga_unset_frozen(ga_state); 1341 free_fs_mount_list(&mounts); 1342 1343 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 1344 1345 return i; 1346 } 1347 1348 static void guest_fsfreeze_cleanup(void) 1349 { 1350 Error *err = NULL; 1351 1352 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 1353 qmp_guest_fsfreeze_thaw(&err); 1354 if (err) { 1355 slog("failed to clean up frozen filesystems: %s", 1356 error_get_pretty(err)); 1357 error_free(err); 1358 } 1359 } 1360 } 1361 #endif /* CONFIG_FSFREEZE */ 1362 1363 #if defined(CONFIG_FSTRIM) 1364 /* 1365 * Walk list of mounted file systems in the guest, and trim them. 1366 */ 1367 GuestFilesystemTrimResponse * 1368 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 1369 { 1370 GuestFilesystemTrimResponse *response; 1371 GuestFilesystemTrimResultList *list; 1372 GuestFilesystemTrimResult *result; 1373 int ret = 0; 1374 FsMountList mounts; 1375 struct FsMount *mount; 1376 int fd; 1377 Error *local_err = NULL; 1378 struct fstrim_range r; 1379 1380 slog("guest-fstrim called"); 1381 1382 QTAILQ_INIT(&mounts); 1383 build_fs_mount_list(&mounts, &local_err); 1384 if (local_err) { 1385 error_propagate(errp, local_err); 1386 return NULL; 1387 } 1388 1389 response = g_malloc0(sizeof(*response)); 1390 1391 QTAILQ_FOREACH(mount, &mounts, next) { 1392 result = g_malloc0(sizeof(*result)); 1393 result->path = g_strdup(mount->dirname); 1394 1395 list = g_malloc0(sizeof(*list)); 1396 list->value = result; 1397 list->next = response->paths; 1398 response->paths = list; 1399 1400 fd = qemu_open(mount->dirname, O_RDONLY); 1401 if (fd == -1) { 1402 result->error = g_strdup_printf("failed to open: %s", 1403 strerror(errno)); 1404 result->has_error = true; 1405 continue; 1406 } 1407 1408 /* We try to cull filesytems we know won't work in advance, but other 1409 * filesytems may not implement fstrim for less obvious reasons. These 1410 * will report EOPNOTSUPP; while in some other cases ENOTTY will be 1411 * reported (e.g. CD-ROMs). 1412 * Any other error means an unexpected error. 1413 */ 1414 r.start = 0; 1415 r.len = -1; 1416 r.minlen = has_minimum ? minimum : 0; 1417 ret = ioctl(fd, FITRIM, &r); 1418 if (ret == -1) { 1419 result->has_error = true; 1420 if (errno == ENOTTY || errno == EOPNOTSUPP) { 1421 result->error = g_strdup("trim not supported"); 1422 } else { 1423 result->error = g_strdup_printf("failed to trim: %s", 1424 strerror(errno)); 1425 } 1426 close(fd); 1427 continue; 1428 } 1429 1430 result->has_minimum = true; 1431 result->minimum = r.minlen; 1432 result->has_trimmed = true; 1433 result->trimmed = r.len; 1434 close(fd); 1435 } 1436 1437 free_fs_mount_list(&mounts); 1438 return response; 1439 } 1440 #endif /* CONFIG_FSTRIM */ 1441 1442 1443 #define LINUX_SYS_STATE_FILE "/sys/power/state" 1444 #define SUSPEND_SUPPORTED 0 1445 #define SUSPEND_NOT_SUPPORTED 1 1446 1447 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, 1448 const char *sysfile_str, Error **errp) 1449 { 1450 Error *local_err = NULL; 1451 char *pmutils_path; 1452 pid_t pid; 1453 int status; 1454 1455 pmutils_path = g_find_program_in_path(pmutils_bin); 1456 1457 pid = fork(); 1458 if (!pid) { 1459 char buf[32]; /* hopefully big enough */ 1460 ssize_t ret; 1461 int fd; 1462 1463 setsid(); 1464 reopen_fd_to_null(0); 1465 reopen_fd_to_null(1); 1466 reopen_fd_to_null(2); 1467 1468 if (pmutils_path) { 1469 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ); 1470 } 1471 1472 /* 1473 * If we get here either pm-utils is not installed or execle() has 1474 * failed. Let's try the manual method if the caller wants it. 1475 */ 1476 1477 if (!sysfile_str) { 1478 _exit(SUSPEND_NOT_SUPPORTED); 1479 } 1480 1481 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 1482 if (fd < 0) { 1483 _exit(SUSPEND_NOT_SUPPORTED); 1484 } 1485 1486 ret = read(fd, buf, sizeof(buf)-1); 1487 if (ret <= 0) { 1488 _exit(SUSPEND_NOT_SUPPORTED); 1489 } 1490 buf[ret] = '\0'; 1491 1492 if (strstr(buf, sysfile_str)) { 1493 _exit(SUSPEND_SUPPORTED); 1494 } 1495 1496 _exit(SUSPEND_NOT_SUPPORTED); 1497 } else if (pid < 0) { 1498 error_setg_errno(errp, errno, "failed to create child process"); 1499 goto out; 1500 } 1501 1502 ga_wait_child(pid, &status, &local_err); 1503 if (local_err) { 1504 error_propagate(errp, local_err); 1505 goto out; 1506 } 1507 1508 if (!WIFEXITED(status)) { 1509 error_setg(errp, "child process has terminated abnormally"); 1510 goto out; 1511 } 1512 1513 switch (WEXITSTATUS(status)) { 1514 case SUSPEND_SUPPORTED: 1515 goto out; 1516 case SUSPEND_NOT_SUPPORTED: 1517 error_setg(errp, 1518 "the requested suspend mode is not supported by the guest"); 1519 goto out; 1520 default: 1521 error_setg(errp, 1522 "the helper program '%s' returned an unexpected exit status" 1523 " code (%d)", pmutils_path, WEXITSTATUS(status)); 1524 goto out; 1525 } 1526 1527 out: 1528 g_free(pmutils_path); 1529 } 1530 1531 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, 1532 Error **errp) 1533 { 1534 Error *local_err = NULL; 1535 char *pmutils_path; 1536 pid_t pid; 1537 int status; 1538 1539 pmutils_path = g_find_program_in_path(pmutils_bin); 1540 1541 pid = fork(); 1542 if (pid == 0) { 1543 /* child */ 1544 int fd; 1545 1546 setsid(); 1547 reopen_fd_to_null(0); 1548 reopen_fd_to_null(1); 1549 reopen_fd_to_null(2); 1550 1551 if (pmutils_path) { 1552 execle(pmutils_path, pmutils_bin, NULL, environ); 1553 } 1554 1555 /* 1556 * If we get here either pm-utils is not installed or execle() has 1557 * failed. Let's try the manual method if the caller wants it. 1558 */ 1559 1560 if (!sysfile_str) { 1561 _exit(EXIT_FAILURE); 1562 } 1563 1564 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 1565 if (fd < 0) { 1566 _exit(EXIT_FAILURE); 1567 } 1568 1569 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 1570 _exit(EXIT_FAILURE); 1571 } 1572 1573 _exit(EXIT_SUCCESS); 1574 } else if (pid < 0) { 1575 error_setg_errno(errp, errno, "failed to create child process"); 1576 goto out; 1577 } 1578 1579 ga_wait_child(pid, &status, &local_err); 1580 if (local_err) { 1581 error_propagate(errp, local_err); 1582 goto out; 1583 } 1584 1585 if (!WIFEXITED(status)) { 1586 error_setg(errp, "child process has terminated abnormally"); 1587 goto out; 1588 } 1589 1590 if (WEXITSTATUS(status)) { 1591 error_setg(errp, "child process has failed to suspend"); 1592 goto out; 1593 } 1594 1595 out: 1596 g_free(pmutils_path); 1597 } 1598 1599 void qmp_guest_suspend_disk(Error **errp) 1600 { 1601 Error *local_err = NULL; 1602 1603 bios_supports_mode("pm-is-supported", "--hibernate", "disk", &local_err); 1604 if (local_err) { 1605 error_propagate(errp, local_err); 1606 return; 1607 } 1608 1609 guest_suspend("pm-hibernate", "disk", errp); 1610 } 1611 1612 void qmp_guest_suspend_ram(Error **errp) 1613 { 1614 Error *local_err = NULL; 1615 1616 bios_supports_mode("pm-is-supported", "--suspend", "mem", &local_err); 1617 if (local_err) { 1618 error_propagate(errp, local_err); 1619 return; 1620 } 1621 1622 guest_suspend("pm-suspend", "mem", errp); 1623 } 1624 1625 void qmp_guest_suspend_hybrid(Error **errp) 1626 { 1627 Error *local_err = NULL; 1628 1629 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, 1630 &local_err); 1631 if (local_err) { 1632 error_propagate(errp, local_err); 1633 return; 1634 } 1635 1636 guest_suspend("pm-suspend-hybrid", NULL, errp); 1637 } 1638 1639 static GuestNetworkInterfaceList * 1640 guest_find_interface(GuestNetworkInterfaceList *head, 1641 const char *name) 1642 { 1643 for (; head; head = head->next) { 1644 if (strcmp(head->value->name, name) == 0) { 1645 break; 1646 } 1647 } 1648 1649 return head; 1650 } 1651 1652 /* 1653 * Build information about guest interfaces 1654 */ 1655 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 1656 { 1657 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 1658 struct ifaddrs *ifap, *ifa; 1659 1660 if (getifaddrs(&ifap) < 0) { 1661 error_setg_errno(errp, errno, "getifaddrs failed"); 1662 goto error; 1663 } 1664 1665 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1666 GuestNetworkInterfaceList *info; 1667 GuestIpAddressList **address_list = NULL, *address_item = NULL; 1668 char addr4[INET_ADDRSTRLEN]; 1669 char addr6[INET6_ADDRSTRLEN]; 1670 int sock; 1671 struct ifreq ifr; 1672 unsigned char *mac_addr; 1673 void *p; 1674 1675 g_debug("Processing %s interface", ifa->ifa_name); 1676 1677 info = guest_find_interface(head, ifa->ifa_name); 1678 1679 if (!info) { 1680 info = g_malloc0(sizeof(*info)); 1681 info->value = g_malloc0(sizeof(*info->value)); 1682 info->value->name = g_strdup(ifa->ifa_name); 1683 1684 if (!cur_item) { 1685 head = cur_item = info; 1686 } else { 1687 cur_item->next = info; 1688 cur_item = info; 1689 } 1690 } 1691 1692 if (!info->value->has_hardware_address && 1693 ifa->ifa_flags & SIOCGIFHWADDR) { 1694 /* we haven't obtained HW address yet */ 1695 sock = socket(PF_INET, SOCK_STREAM, 0); 1696 if (sock == -1) { 1697 error_setg_errno(errp, errno, "failed to create socket"); 1698 goto error; 1699 } 1700 1701 memset(&ifr, 0, sizeof(ifr)); 1702 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); 1703 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 1704 error_setg_errno(errp, errno, 1705 "failed to get MAC address of %s", 1706 ifa->ifa_name); 1707 close(sock); 1708 goto error; 1709 } 1710 1711 close(sock); 1712 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 1713 1714 info->value->hardware_address = 1715 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 1716 (int) mac_addr[0], (int) mac_addr[1], 1717 (int) mac_addr[2], (int) mac_addr[3], 1718 (int) mac_addr[4], (int) mac_addr[5]); 1719 1720 info->value->has_hardware_address = true; 1721 } 1722 1723 if (ifa->ifa_addr && 1724 ifa->ifa_addr->sa_family == AF_INET) { 1725 /* interface with IPv4 address */ 1726 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 1727 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 1728 error_setg_errno(errp, errno, "inet_ntop failed"); 1729 goto error; 1730 } 1731 1732 address_item = g_malloc0(sizeof(*address_item)); 1733 address_item->value = g_malloc0(sizeof(*address_item->value)); 1734 address_item->value->ip_address = g_strdup(addr4); 1735 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 1736 1737 if (ifa->ifa_netmask) { 1738 /* Count the number of set bits in netmask. 1739 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 1740 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 1741 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); 1742 } 1743 } else if (ifa->ifa_addr && 1744 ifa->ifa_addr->sa_family == AF_INET6) { 1745 /* interface with IPv6 address */ 1746 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 1747 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 1748 error_setg_errno(errp, errno, "inet_ntop failed"); 1749 goto error; 1750 } 1751 1752 address_item = g_malloc0(sizeof(*address_item)); 1753 address_item->value = g_malloc0(sizeof(*address_item->value)); 1754 address_item->value->ip_address = g_strdup(addr6); 1755 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 1756 1757 if (ifa->ifa_netmask) { 1758 /* Count the number of set bits in netmask. 1759 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 1760 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 1761 address_item->value->prefix = 1762 ctpop32(((uint32_t *) p)[0]) + 1763 ctpop32(((uint32_t *) p)[1]) + 1764 ctpop32(((uint32_t *) p)[2]) + 1765 ctpop32(((uint32_t *) p)[3]); 1766 } 1767 } 1768 1769 if (!address_item) { 1770 continue; 1771 } 1772 1773 address_list = &info->value->ip_addresses; 1774 1775 while (*address_list && (*address_list)->next) { 1776 address_list = &(*address_list)->next; 1777 } 1778 1779 if (!*address_list) { 1780 *address_list = address_item; 1781 } else { 1782 (*address_list)->next = address_item; 1783 } 1784 1785 info->value->has_ip_addresses = true; 1786 1787 1788 } 1789 1790 freeifaddrs(ifap); 1791 return head; 1792 1793 error: 1794 freeifaddrs(ifap); 1795 qapi_free_GuestNetworkInterfaceList(head); 1796 return NULL; 1797 } 1798 1799 #define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp)) 1800 1801 static long sysconf_exact(int name, const char *name_str, Error **errp) 1802 { 1803 long ret; 1804 1805 errno = 0; 1806 ret = sysconf(name); 1807 if (ret == -1) { 1808 if (errno == 0) { 1809 error_setg(errp, "sysconf(%s): value indefinite", name_str); 1810 } else { 1811 error_setg_errno(errp, errno, "sysconf(%s)", name_str); 1812 } 1813 } 1814 return ret; 1815 } 1816 1817 /* Transfer online/offline status between @vcpu and the guest system. 1818 * 1819 * On input either @errp or *@errp must be NULL. 1820 * 1821 * In system-to-@vcpu direction, the following @vcpu fields are accessed: 1822 * - R: vcpu->logical_id 1823 * - W: vcpu->online 1824 * - W: vcpu->can_offline 1825 * 1826 * In @vcpu-to-system direction, the following @vcpu fields are accessed: 1827 * - R: vcpu->logical_id 1828 * - R: vcpu->online 1829 * 1830 * Written members remain unmodified on error. 1831 */ 1832 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, 1833 Error **errp) 1834 { 1835 char *dirpath; 1836 int dirfd; 1837 1838 dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", 1839 vcpu->logical_id); 1840 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 1841 if (dirfd == -1) { 1842 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 1843 } else { 1844 static const char fn[] = "online"; 1845 int fd; 1846 int res; 1847 1848 fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); 1849 if (fd == -1) { 1850 if (errno != ENOENT) { 1851 error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); 1852 } else if (sys2vcpu) { 1853 vcpu->online = true; 1854 vcpu->can_offline = false; 1855 } else if (!vcpu->online) { 1856 error_setg(errp, "logical processor #%" PRId64 " can't be " 1857 "offlined", vcpu->logical_id); 1858 } /* otherwise pretend successful re-onlining */ 1859 } else { 1860 unsigned char status; 1861 1862 res = pread(fd, &status, 1, 0); 1863 if (res == -1) { 1864 error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); 1865 } else if (res == 0) { 1866 error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, 1867 fn); 1868 } else if (sys2vcpu) { 1869 vcpu->online = (status != '0'); 1870 vcpu->can_offline = true; 1871 } else if (vcpu->online != (status != '0')) { 1872 status = '0' + vcpu->online; 1873 if (pwrite(fd, &status, 1, 0) == -1) { 1874 error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, 1875 fn); 1876 } 1877 } /* otherwise pretend successful re-(on|off)-lining */ 1878 1879 res = close(fd); 1880 g_assert(res == 0); 1881 } 1882 1883 res = close(dirfd); 1884 g_assert(res == 0); 1885 } 1886 1887 g_free(dirpath); 1888 } 1889 1890 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 1891 { 1892 int64_t current; 1893 GuestLogicalProcessorList *head, **link; 1894 long sc_max; 1895 Error *local_err = NULL; 1896 1897 current = 0; 1898 head = NULL; 1899 link = &head; 1900 sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err); 1901 1902 while (local_err == NULL && current < sc_max) { 1903 GuestLogicalProcessor *vcpu; 1904 GuestLogicalProcessorList *entry; 1905 1906 vcpu = g_malloc0(sizeof *vcpu); 1907 vcpu->logical_id = current++; 1908 vcpu->has_can_offline = true; /* lolspeak ftw */ 1909 transfer_vcpu(vcpu, true, &local_err); 1910 1911 entry = g_malloc0(sizeof *entry); 1912 entry->value = vcpu; 1913 1914 *link = entry; 1915 link = &entry->next; 1916 } 1917 1918 if (local_err == NULL) { 1919 /* there's no guest with zero VCPUs */ 1920 g_assert(head != NULL); 1921 return head; 1922 } 1923 1924 qapi_free_GuestLogicalProcessorList(head); 1925 error_propagate(errp, local_err); 1926 return NULL; 1927 } 1928 1929 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 1930 { 1931 int64_t processed; 1932 Error *local_err = NULL; 1933 1934 processed = 0; 1935 while (vcpus != NULL) { 1936 transfer_vcpu(vcpus->value, false, &local_err); 1937 if (local_err != NULL) { 1938 break; 1939 } 1940 ++processed; 1941 vcpus = vcpus->next; 1942 } 1943 1944 if (local_err != NULL) { 1945 if (processed == 0) { 1946 error_propagate(errp, local_err); 1947 } else { 1948 error_free(local_err); 1949 } 1950 } 1951 1952 return processed; 1953 } 1954 1955 void qmp_guest_set_user_password(const char *username, 1956 const char *password, 1957 bool crypted, 1958 Error **errp) 1959 { 1960 Error *local_err = NULL; 1961 char *passwd_path = NULL; 1962 pid_t pid; 1963 int status; 1964 int datafd[2] = { -1, -1 }; 1965 char *rawpasswddata = NULL; 1966 size_t rawpasswdlen; 1967 char *chpasswddata = NULL; 1968 size_t chpasswdlen; 1969 1970 rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp); 1971 if (!rawpasswddata) { 1972 return; 1973 } 1974 rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1); 1975 rawpasswddata[rawpasswdlen] = '\0'; 1976 1977 if (strchr(rawpasswddata, '\n')) { 1978 error_setg(errp, "forbidden characters in raw password"); 1979 goto out; 1980 } 1981 1982 if (strchr(username, '\n') || 1983 strchr(username, ':')) { 1984 error_setg(errp, "forbidden characters in username"); 1985 goto out; 1986 } 1987 1988 chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata); 1989 chpasswdlen = strlen(chpasswddata); 1990 1991 passwd_path = g_find_program_in_path("chpasswd"); 1992 1993 if (!passwd_path) { 1994 error_setg(errp, "cannot find 'passwd' program in PATH"); 1995 goto out; 1996 } 1997 1998 if (pipe(datafd) < 0) { 1999 error_setg(errp, "cannot create pipe FDs"); 2000 goto out; 2001 } 2002 2003 pid = fork(); 2004 if (pid == 0) { 2005 close(datafd[1]); 2006 /* child */ 2007 setsid(); 2008 dup2(datafd[0], 0); 2009 reopen_fd_to_null(1); 2010 reopen_fd_to_null(2); 2011 2012 if (crypted) { 2013 execle(passwd_path, "chpasswd", "-e", NULL, environ); 2014 } else { 2015 execle(passwd_path, "chpasswd", NULL, environ); 2016 } 2017 _exit(EXIT_FAILURE); 2018 } else if (pid < 0) { 2019 error_setg_errno(errp, errno, "failed to create child process"); 2020 goto out; 2021 } 2022 close(datafd[0]); 2023 datafd[0] = -1; 2024 2025 if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) { 2026 error_setg_errno(errp, errno, "cannot write new account password"); 2027 goto out; 2028 } 2029 close(datafd[1]); 2030 datafd[1] = -1; 2031 2032 ga_wait_child(pid, &status, &local_err); 2033 if (local_err) { 2034 error_propagate(errp, local_err); 2035 goto out; 2036 } 2037 2038 if (!WIFEXITED(status)) { 2039 error_setg(errp, "child process has terminated abnormally"); 2040 goto out; 2041 } 2042 2043 if (WEXITSTATUS(status)) { 2044 error_setg(errp, "child process has failed to set user password"); 2045 goto out; 2046 } 2047 2048 out: 2049 g_free(chpasswddata); 2050 g_free(rawpasswddata); 2051 g_free(passwd_path); 2052 if (datafd[0] != -1) { 2053 close(datafd[0]); 2054 } 2055 if (datafd[1] != -1) { 2056 close(datafd[1]); 2057 } 2058 } 2059 2060 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf, 2061 int size, Error **errp) 2062 { 2063 int fd; 2064 int res; 2065 2066 errno = 0; 2067 fd = openat(dirfd, pathname, O_RDONLY); 2068 if (fd == -1) { 2069 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2070 return; 2071 } 2072 2073 res = pread(fd, buf, size, 0); 2074 if (res == -1) { 2075 error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname); 2076 } else if (res == 0) { 2077 error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname); 2078 } 2079 close(fd); 2080 } 2081 2082 static void ga_write_sysfs_file(int dirfd, const char *pathname, 2083 const char *buf, int size, Error **errp) 2084 { 2085 int fd; 2086 2087 errno = 0; 2088 fd = openat(dirfd, pathname, O_WRONLY); 2089 if (fd == -1) { 2090 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2091 return; 2092 } 2093 2094 if (pwrite(fd, buf, size, 0) == -1) { 2095 error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname); 2096 } 2097 2098 close(fd); 2099 } 2100 2101 /* Transfer online/offline status between @mem_blk and the guest system. 2102 * 2103 * On input either @errp or *@errp must be NULL. 2104 * 2105 * In system-to-@mem_blk direction, the following @mem_blk fields are accessed: 2106 * - R: mem_blk->phys_index 2107 * - W: mem_blk->online 2108 * - W: mem_blk->can_offline 2109 * 2110 * In @mem_blk-to-system direction, the following @mem_blk fields are accessed: 2111 * - R: mem_blk->phys_index 2112 * - R: mem_blk->online 2113 *- R: mem_blk->can_offline 2114 * Written members remain unmodified on error. 2115 */ 2116 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, 2117 GuestMemoryBlockResponse *result, 2118 Error **errp) 2119 { 2120 char *dirpath; 2121 int dirfd; 2122 char *status; 2123 Error *local_err = NULL; 2124 2125 if (!sys2memblk) { 2126 DIR *dp; 2127 2128 if (!result) { 2129 error_setg(errp, "Internal error, 'result' should not be NULL"); 2130 return; 2131 } 2132 errno = 0; 2133 dp = opendir("/sys/devices/system/memory/"); 2134 /* if there is no 'memory' directory in sysfs, 2135 * we think this VM does not support online/offline memory block, 2136 * any other solution? 2137 */ 2138 if (!dp && errno == ENOENT) { 2139 result->response = 2140 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2141 goto out1; 2142 } 2143 closedir(dp); 2144 } 2145 2146 dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/", 2147 mem_blk->phys_index); 2148 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2149 if (dirfd == -1) { 2150 if (sys2memblk) { 2151 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2152 } else { 2153 if (errno == ENOENT) { 2154 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND; 2155 } else { 2156 result->response = 2157 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2158 } 2159 } 2160 g_free(dirpath); 2161 goto out1; 2162 } 2163 g_free(dirpath); 2164 2165 status = g_malloc0(10); 2166 ga_read_sysfs_file(dirfd, "state", status, 10, &local_err); 2167 if (local_err) { 2168 /* treat with sysfs file that not exist in old kernel */ 2169 if (errno == ENOENT) { 2170 error_free(local_err); 2171 if (sys2memblk) { 2172 mem_blk->online = true; 2173 mem_blk->can_offline = false; 2174 } else if (!mem_blk->online) { 2175 result->response = 2176 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2177 } 2178 } else { 2179 if (sys2memblk) { 2180 error_propagate(errp, local_err); 2181 } else { 2182 result->response = 2183 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2184 } 2185 } 2186 goto out2; 2187 } 2188 2189 if (sys2memblk) { 2190 char removable = '0'; 2191 2192 mem_blk->online = (strncmp(status, "online", 6) == 0); 2193 2194 ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err); 2195 if (local_err) { 2196 /* if no 'removable' file, it doesn't support offline mem blk */ 2197 if (errno == ENOENT) { 2198 error_free(local_err); 2199 mem_blk->can_offline = false; 2200 } else { 2201 error_propagate(errp, local_err); 2202 } 2203 } else { 2204 mem_blk->can_offline = (removable != '0'); 2205 } 2206 } else { 2207 if (mem_blk->online != (strncmp(status, "online", 6) == 0)) { 2208 char *new_state = mem_blk->online ? g_strdup("online") : 2209 g_strdup("offline"); 2210 2211 ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state), 2212 &local_err); 2213 g_free(new_state); 2214 if (local_err) { 2215 error_free(local_err); 2216 result->response = 2217 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2218 goto out2; 2219 } 2220 2221 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS; 2222 result->has_error_code = false; 2223 } /* otherwise pretend successful re-(on|off)-lining */ 2224 } 2225 g_free(status); 2226 close(dirfd); 2227 return; 2228 2229 out2: 2230 g_free(status); 2231 close(dirfd); 2232 out1: 2233 if (!sys2memblk) { 2234 result->has_error_code = true; 2235 result->error_code = errno; 2236 } 2237 } 2238 2239 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2240 { 2241 GuestMemoryBlockList *head, **link; 2242 Error *local_err = NULL; 2243 struct dirent *de; 2244 DIR *dp; 2245 2246 head = NULL; 2247 link = &head; 2248 2249 dp = opendir("/sys/devices/system/memory/"); 2250 if (!dp) { 2251 /* it's ok if this happens to be a system that doesn't expose 2252 * memory blocks via sysfs, but otherwise we should report 2253 * an error 2254 */ 2255 if (errno != ENOENT) { 2256 error_setg_errno(errp, errno, "Can't open directory" 2257 "\"/sys/devices/system/memory/\""); 2258 } 2259 return NULL; 2260 } 2261 2262 /* Note: the phys_index of memory block may be discontinuous, 2263 * this is because a memblk is the unit of the Sparse Memory design, which 2264 * allows discontinuous memory ranges (ex. NUMA), so here we should 2265 * traverse the memory block directory. 2266 */ 2267 while ((de = readdir(dp)) != NULL) { 2268 GuestMemoryBlock *mem_blk; 2269 GuestMemoryBlockList *entry; 2270 2271 if ((strncmp(de->d_name, "memory", 6) != 0) || 2272 !(de->d_type & DT_DIR)) { 2273 continue; 2274 } 2275 2276 mem_blk = g_malloc0(sizeof *mem_blk); 2277 /* The d_name is "memoryXXX", phys_index is block id, same as XXX */ 2278 mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10); 2279 mem_blk->has_can_offline = true; /* lolspeak ftw */ 2280 transfer_memory_block(mem_blk, true, NULL, &local_err); 2281 2282 entry = g_malloc0(sizeof *entry); 2283 entry->value = mem_blk; 2284 2285 *link = entry; 2286 link = &entry->next; 2287 } 2288 2289 closedir(dp); 2290 if (local_err == NULL) { 2291 /* there's no guest with zero memory blocks */ 2292 if (head == NULL) { 2293 error_setg(errp, "guest reported zero memory blocks!"); 2294 } 2295 return head; 2296 } 2297 2298 qapi_free_GuestMemoryBlockList(head); 2299 error_propagate(errp, local_err); 2300 return NULL; 2301 } 2302 2303 GuestMemoryBlockResponseList * 2304 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2305 { 2306 GuestMemoryBlockResponseList *head, **link; 2307 Error *local_err = NULL; 2308 2309 head = NULL; 2310 link = &head; 2311 2312 while (mem_blks != NULL) { 2313 GuestMemoryBlockResponse *result; 2314 GuestMemoryBlockResponseList *entry; 2315 GuestMemoryBlock *current_mem_blk = mem_blks->value; 2316 2317 result = g_malloc0(sizeof(*result)); 2318 result->phys_index = current_mem_blk->phys_index; 2319 transfer_memory_block(current_mem_blk, false, result, &local_err); 2320 if (local_err) { /* should never happen */ 2321 goto err; 2322 } 2323 entry = g_malloc0(sizeof *entry); 2324 entry->value = result; 2325 2326 *link = entry; 2327 link = &entry->next; 2328 mem_blks = mem_blks->next; 2329 } 2330 2331 return head; 2332 err: 2333 qapi_free_GuestMemoryBlockResponseList(head); 2334 error_propagate(errp, local_err); 2335 return NULL; 2336 } 2337 2338 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2339 { 2340 Error *local_err = NULL; 2341 char *dirpath; 2342 int dirfd; 2343 char *buf; 2344 GuestMemoryBlockInfo *info; 2345 2346 dirpath = g_strdup_printf("/sys/devices/system/memory/"); 2347 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2348 if (dirfd == -1) { 2349 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2350 g_free(dirpath); 2351 return NULL; 2352 } 2353 g_free(dirpath); 2354 2355 buf = g_malloc0(20); 2356 ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err); 2357 close(dirfd); 2358 if (local_err) { 2359 g_free(buf); 2360 error_propagate(errp, local_err); 2361 return NULL; 2362 } 2363 2364 info = g_new0(GuestMemoryBlockInfo, 1); 2365 info->size = strtol(buf, NULL, 16); /* the unit is bytes */ 2366 2367 g_free(buf); 2368 2369 return info; 2370 } 2371 2372 #else /* defined(__linux__) */ 2373 2374 void qmp_guest_suspend_disk(Error **errp) 2375 { 2376 error_setg(errp, QERR_UNSUPPORTED); 2377 } 2378 2379 void qmp_guest_suspend_ram(Error **errp) 2380 { 2381 error_setg(errp, QERR_UNSUPPORTED); 2382 } 2383 2384 void qmp_guest_suspend_hybrid(Error **errp) 2385 { 2386 error_setg(errp, QERR_UNSUPPORTED); 2387 } 2388 2389 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 2390 { 2391 error_setg(errp, QERR_UNSUPPORTED); 2392 return NULL; 2393 } 2394 2395 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2396 { 2397 error_setg(errp, QERR_UNSUPPORTED); 2398 return NULL; 2399 } 2400 2401 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2402 { 2403 error_setg(errp, QERR_UNSUPPORTED); 2404 return -1; 2405 } 2406 2407 void qmp_guest_set_user_password(const char *username, 2408 const char *password, 2409 bool crypted, 2410 Error **errp) 2411 { 2412 error_setg(errp, QERR_UNSUPPORTED); 2413 } 2414 2415 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2416 { 2417 error_setg(errp, QERR_UNSUPPORTED); 2418 return NULL; 2419 } 2420 2421 GuestMemoryBlockResponseList * 2422 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2423 { 2424 error_setg(errp, QERR_UNSUPPORTED); 2425 return NULL; 2426 } 2427 2428 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2429 { 2430 error_setg(errp, QERR_UNSUPPORTED); 2431 return NULL; 2432 } 2433 2434 #endif 2435 2436 #if !defined(CONFIG_FSFREEZE) 2437 2438 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 2439 { 2440 error_setg(errp, QERR_UNSUPPORTED); 2441 return NULL; 2442 } 2443 2444 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 2445 { 2446 error_setg(errp, QERR_UNSUPPORTED); 2447 2448 return 0; 2449 } 2450 2451 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 2452 { 2453 error_setg(errp, QERR_UNSUPPORTED); 2454 2455 return 0; 2456 } 2457 2458 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 2459 strList *mountpoints, 2460 Error **errp) 2461 { 2462 error_setg(errp, QERR_UNSUPPORTED); 2463 2464 return 0; 2465 } 2466 2467 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 2468 { 2469 error_setg(errp, QERR_UNSUPPORTED); 2470 2471 return 0; 2472 } 2473 #endif /* CONFIG_FSFREEZE */ 2474 2475 #if !defined(CONFIG_FSTRIM) 2476 GuestFilesystemTrimResponse * 2477 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 2478 { 2479 error_setg(errp, QERR_UNSUPPORTED); 2480 return NULL; 2481 } 2482 #endif 2483 2484 /* add unsupported commands to the blacklist */ 2485 GList *ga_command_blacklist_init(GList *blacklist) 2486 { 2487 #if !defined(__linux__) 2488 { 2489 const char *list[] = { 2490 "guest-suspend-disk", "guest-suspend-ram", 2491 "guest-suspend-hybrid", "guest-network-get-interfaces", 2492 "guest-get-vcpus", "guest-set-vcpus", 2493 "guest-get-memory-blocks", "guest-set-memory-blocks", 2494 "guest-get-memory-block-size", NULL}; 2495 char **p = (char **)list; 2496 2497 while (*p) { 2498 blacklist = g_list_append(blacklist, g_strdup(*p++)); 2499 } 2500 } 2501 #endif 2502 2503 #if !defined(CONFIG_FSFREEZE) 2504 { 2505 const char *list[] = { 2506 "guest-get-fsinfo", "guest-fsfreeze-status", 2507 "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", 2508 "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL}; 2509 char **p = (char **)list; 2510 2511 while (*p) { 2512 blacklist = g_list_append(blacklist, g_strdup(*p++)); 2513 } 2514 } 2515 #endif 2516 2517 #if !defined(CONFIG_FSTRIM) 2518 blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); 2519 #endif 2520 2521 return blacklist; 2522 } 2523 2524 /* register init/cleanup routines for stateful command groups */ 2525 void ga_command_state_init(GAState *s, GACommandState *cs) 2526 { 2527 #if defined(CONFIG_FSFREEZE) 2528 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 2529 #endif 2530 } 2531