commands-posix.c (518b0d800b5ab046b72fac423ace7549ab187329) | commands-posix.c (bad0001eeb34484c4595c3862e14a4ee22a3abee) |
---|---|
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> --- 19 unchanged lines hidden (view full) --- 28#include "cutils.h" 29 30#ifdef HAVE_UTMPX 31#include <utmpx.h> 32#endif 33 34#if defined(__linux__) 35#include <mntent.h> | 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> --- 19 unchanged lines hidden (view full) --- 28#include "cutils.h" 29 30#ifdef HAVE_UTMPX 31#include <utmpx.h> 32#endif 33 34#if defined(__linux__) 35#include <mntent.h> |
36#include <linux/fs.h> | |
37#include <sys/statvfs.h> 38#include <linux/nvme_ioctl.h> 39 40#ifdef CONFIG_LIBUDEV 41#include <libudev.h> 42#endif | 36#include <sys/statvfs.h> 37#include <linux/nvme_ioctl.h> 38 39#ifdef CONFIG_LIBUDEV 40#include <libudev.h> 41#endif |
43 44#ifdef FIFREEZE 45#define CONFIG_FSFREEZE | |
46#endif | 42#endif |
47#ifdef FITRIM 48#define CONFIG_FSTRIM 49#endif 50#endif | |
51 52#ifdef __FreeBSD__ 53/* 54 * The code under HAVE_GETIFADDRS condition can't be compiled in FreeBSD. 55 * Fix it in one of the following patches. 56 */ 57#undef HAVE_GETIFADDRS 58#endif --- 559 unchanged lines hidden (view full) --- 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 | 43 44#ifdef __FreeBSD__ 45/* 46 * The code under HAVE_GETIFADDRS condition can't be compiled in FreeBSD. 47 * Fix it in one of the following patches. 48 */ 49#undef HAVE_GETIFADDRS 50#endif --- 559 unchanged lines hidden (view full) --- 610 ret = fflush(fh); 611 if (ret == EOF) { 612 error_setg_errno(errp, errno, "failed to flush file"); 613 } else { 614 gfh->state = RW_STATE_NEW; 615 } 616} 617 |
626/* linux-specific implementations. avoid this if at all possible. */ 627#if defined(__linux__) 628 | |
629#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 630void free_fs_mount_list(FsMountList *mounts) 631{ 632 FsMount *mount, *temp; 633 634 if (!mounts) { 635 return; 636 } 637 638 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 639 QTAILQ_REMOVE(mounts, mount, next); 640 g_free(mount->dirname); 641 g_free(mount->devtype); 642 g_free(mount); 643 } 644} 645#endif 646 647#if defined(CONFIG_FSFREEZE) | 618#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 619void free_fs_mount_list(FsMountList *mounts) 620{ 621 FsMount *mount, *temp; 622 623 if (!mounts) { 624 return; 625 } 626 627 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 628 QTAILQ_REMOVE(mounts, mount, next); 629 g_free(mount->dirname); 630 g_free(mount->devtype); 631 g_free(mount); 632 } 633} 634#endif 635 636#if defined(CONFIG_FSFREEZE) |
637typedef enum { 638 FSFREEZE_HOOK_THAW = 0, 639 FSFREEZE_HOOK_FREEZE, 640} FsfreezeHookArg; |
|
648 | 641 |
642static const char *fsfreeze_hook_arg_string[] = { 643 "thaw", 644 "freeze", 645}; 646 647static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 648{ 649 int status; 650 pid_t pid; 651 const char *hook; 652 const char *arg_str = fsfreeze_hook_arg_string[arg]; 653 Error *local_err = NULL; 654 655 hook = ga_fsfreeze_hook(ga_state); 656 if (!hook) { 657 return; 658 } 659 if (access(hook, X_OK) != 0) { 660 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 661 return; 662 } 663 664 slog("executing fsfreeze hook with arg '%s'", arg_str); 665 pid = fork(); 666 if (pid == 0) { 667 setsid(); 668 reopen_fd_to_null(0); 669 reopen_fd_to_null(1); 670 reopen_fd_to_null(2); 671 672 execl(hook, hook, arg_str, NULL); 673 _exit(EXIT_FAILURE); 674 } else if (pid < 0) { 675 error_setg_errno(errp, errno, "failed to create child process"); 676 return; 677 } 678 679 ga_wait_child(pid, &status, &local_err); 680 if (local_err) { 681 error_propagate(errp, local_err); 682 return; 683 } 684 685 if (!WIFEXITED(status)) { 686 error_setg(errp, "fsfreeze hook has terminated abnormally"); 687 return; 688 } 689 690 status = WEXITSTATUS(status); 691 if (status) { 692 error_setg(errp, "fsfreeze hook has failed with status %d", status); 693 return; 694 } 695} 696 697/* 698 * Return status of freeze/thaw 699 */ 700GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 701{ 702 if (ga_is_frozen(ga_state)) { 703 return GUEST_FSFREEZE_STATUS_FROZEN; 704 } 705 706 return GUEST_FSFREEZE_STATUS_THAWED; 707} 708 709int64_t qmp_guest_fsfreeze_freeze(Error **errp) 710{ 711 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 712} 713 714int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 715 strList *mountpoints, 716 Error **errp) 717{ 718 int ret; 719 FsMountList mounts; 720 Error *local_err = NULL; 721 722 slog("guest-fsfreeze called"); 723 724 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 725 if (local_err) { 726 error_propagate(errp, local_err); 727 return -1; 728 } 729 730 QTAILQ_INIT(&mounts); 731 if (!build_fs_mount_list(&mounts, &local_err)) { 732 error_propagate(errp, local_err); 733 return -1; 734 } 735 736 /* cannot risk guest agent blocking itself on a write in this state */ 737 ga_set_frozen(ga_state); 738 739 ret = qmp_guest_fsfreeze_do_freeze_list(has_mountpoints, mountpoints, 740 mounts, errp); 741 742 free_fs_mount_list(&mounts); 743 /* We may not issue any FIFREEZE here. 744 * Just unset ga_state here and ready for the next call. 745 */ 746 if (ret == 0) { 747 ga_unset_frozen(ga_state); 748 } else if (ret < 0) { 749 qmp_guest_fsfreeze_thaw(NULL); 750 } 751 return ret; 752} 753 754int64_t qmp_guest_fsfreeze_thaw(Error **errp) 755{ 756 int ret; 757 758 ret = qmp_guest_fsfreeze_do_thaw(errp); 759 if (ret >= 0) { 760 ga_unset_frozen(ga_state); 761 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 762 } else { 763 ret = 0; 764 } 765 766 return ret; 767} 768 769static void guest_fsfreeze_cleanup(void) 770{ 771 Error *err = NULL; 772 773 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 774 qmp_guest_fsfreeze_thaw(&err); 775 if (err) { 776 slog("failed to clean up frozen filesystems: %s", 777 error_get_pretty(err)); 778 error_free(err); 779 } 780 } 781} 782#endif 783 784/* linux-specific implementations. avoid this if at all possible. */ 785#if defined(__linux__) 786#if defined(CONFIG_FSFREEZE) 787 |
|
649static char *get_pci_driver(char const *syspath, int pathlen, Error **errp) 650{ 651 char *path; 652 char *dpath; 653 char *driver = NULL; 654 char buf[PATH_MAX]; 655 ssize_t len; 656 --- 805 unchanged lines hidden (view full) --- 1462 ret = NULL; 1463 break; 1464 } 1465 } 1466 1467 free_fs_mount_list(&mounts); 1468 return ret; 1469} | 788static char *get_pci_driver(char const *syspath, int pathlen, Error **errp) 789{ 790 char *path; 791 char *dpath; 792 char *driver = NULL; 793 char buf[PATH_MAX]; 794 ssize_t len; 795 --- 805 unchanged lines hidden (view full) --- 1601 ret = NULL; 1602 break; 1603 } 1604 } 1605 1606 free_fs_mount_list(&mounts); 1607 return ret; 1608} |
1470 1471 1472typedef enum { 1473 FSFREEZE_HOOK_THAW = 0, 1474 FSFREEZE_HOOK_FREEZE, 1475} FsfreezeHookArg; 1476 1477static const char *fsfreeze_hook_arg_string[] = { 1478 "thaw", 1479 "freeze", 1480}; 1481 1482static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 1483{ 1484 int status; 1485 pid_t pid; 1486 const char *hook; 1487 const char *arg_str = fsfreeze_hook_arg_string[arg]; 1488 Error *local_err = NULL; 1489 1490 hook = ga_fsfreeze_hook(ga_state); 1491 if (!hook) { 1492 return; 1493 } 1494 if (access(hook, X_OK) != 0) { 1495 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 1496 return; 1497 } 1498 1499 slog("executing fsfreeze hook with arg '%s'", arg_str); 1500 pid = fork(); 1501 if (pid == 0) { 1502 setsid(); 1503 reopen_fd_to_null(0); 1504 reopen_fd_to_null(1); 1505 reopen_fd_to_null(2); 1506 1507 execl(hook, hook, arg_str, NULL); 1508 _exit(EXIT_FAILURE); 1509 } else if (pid < 0) { 1510 error_setg_errno(errp, errno, "failed to create child process"); 1511 return; 1512 } 1513 1514 ga_wait_child(pid, &status, &local_err); 1515 if (local_err) { 1516 error_propagate(errp, local_err); 1517 return; 1518 } 1519 1520 if (!WIFEXITED(status)) { 1521 error_setg(errp, "fsfreeze hook has terminated abnormally"); 1522 return; 1523 } 1524 1525 status = WEXITSTATUS(status); 1526 if (status) { 1527 error_setg(errp, "fsfreeze hook has failed with status %d", status); 1528 return; 1529 } 1530} 1531 1532/* 1533 * Return status of freeze/thaw 1534 */ 1535GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 1536{ 1537 if (ga_is_frozen(ga_state)) { 1538 return GUEST_FSFREEZE_STATUS_FROZEN; 1539 } 1540 1541 return GUEST_FSFREEZE_STATUS_THAWED; 1542} 1543 1544int64_t qmp_guest_fsfreeze_freeze(Error **errp) 1545{ 1546 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 1547} 1548 1549int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 1550 strList *mountpoints, 1551 Error **errp) 1552{ 1553 int ret; 1554 FsMountList mounts; 1555 Error *local_err = NULL; 1556 1557 slog("guest-fsfreeze called"); 1558 1559 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 1560 if (local_err) { 1561 error_propagate(errp, local_err); 1562 return -1; 1563 } 1564 1565 QTAILQ_INIT(&mounts); 1566 if (!build_fs_mount_list(&mounts, &local_err)) { 1567 error_propagate(errp, local_err); 1568 return -1; 1569 } 1570 1571 /* cannot risk guest agent blocking itself on a write in this state */ 1572 ga_set_frozen(ga_state); 1573 1574 ret = qmp_guest_fsfreeze_do_freeze_list(has_mountpoints, mountpoints, 1575 mounts, errp); 1576 1577 free_fs_mount_list(&mounts); 1578 /* We may not issue any FIFREEZE here. 1579 * Just unset ga_state here and ready for the next call. 1580 */ 1581 if (ret == 0) { 1582 ga_unset_frozen(ga_state); 1583 } else if (ret < 0) { 1584 qmp_guest_fsfreeze_thaw(NULL); 1585 } 1586 return ret; 1587} 1588 1589int64_t qmp_guest_fsfreeze_thaw(Error **errp) 1590{ 1591 int ret; 1592 1593 ret = qmp_guest_fsfreeze_do_thaw(errp); 1594 if (ret >= 0) { 1595 ga_unset_frozen(ga_state); 1596 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 1597 } else { 1598 ret = 0; 1599 } 1600 1601 return ret; 1602} 1603 1604static void guest_fsfreeze_cleanup(void) 1605{ 1606 Error *err = NULL; 1607 1608 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 1609 qmp_guest_fsfreeze_thaw(&err); 1610 if (err) { 1611 slog("failed to clean up frozen filesystems: %s", 1612 error_get_pretty(err)); 1613 error_free(err); 1614 } 1615 } 1616} | |
1617#endif /* CONFIG_FSFREEZE */ 1618 1619#if defined(CONFIG_FSTRIM) 1620/* 1621 * Walk list of mounted file systems in the guest, and trim them. 1622 */ 1623GuestFilesystemTrimResponse * 1624qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) --- 1785 unchanged lines hidden --- | 1609#endif /* CONFIG_FSFREEZE */ 1610 1611#if defined(CONFIG_FSTRIM) 1612/* 1613 * Walk list of mounted file systems in the guest, and trim them. 1614 */ 1615GuestFilesystemTrimResponse * 1616qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) --- 1785 unchanged lines hidden --- |