qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 2/2] qemu-ga: add guest-fstrim command


From: Michal Privoznik
Subject: Re: [Qemu-devel] [PATCH v2 2/2] qemu-ga: add guest-fstrim command
Date: Wed, 13 Jun 2012 10:11:22 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:13.0) Gecko/20120608 Thunderbird/13.0

On 13.06.2012 07:41, Paolo Bonzini wrote:
> FITRIM is a mounted filesystem feature to discard (or "trim") blocks which
> are not in use by the filesystem. This is useful for solid-state drives
> (SSDs) and thinly-provisioned storage.  Provide access to the feature
> from the host so that filesystems can be trimmed periodically or before
> migration.
> 
> Here is an example using scsi_debug:
> 
>     # modprobe scsi_debug lbpu=1 lbpws=1
>     # sg_vpd -p0xb2 /dev/sdb
>     Logical block provisioning VPD page (SBC):
>       Unmap command supported (LBPU): 1
>       Write same (16) with unmap bit supported (LBWS): 1
>       Write same (10) with unmap bit supported (LBWS10): 0
>     # mke2fs /dev/sdb
>     # cat /sys/bus/pseudo/drivers/scsi_debug/map
>     1-616,16257-16383
>     # mount /dev/sdb /run/media/pbonzini/test
>     # dd if=/dev/zero of=/run/media/pbonzini/test/file
>     # cat map
>     1-616,645-1588,1599-4026,4029-16383
>     # rm /run/media/pbonzini/test/file
>     # ./qemu-ga /dev/fd/0
>     {"execute":"guest-fstrim"}
>     {"return": {}}
>     # cat map
>     1-612
> 
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---

Reviewed-by: Michal Privoznik <address@hidden>

> v1->v2: fix version number, define mount list functions also for CONFIG_FSTRIM
> 
>  qapi-schema-guest.json |   20 +++++++++++++
>  qga/commands-posix.c   |   78 
> ++++++++++++++++++++++++++++++++++++++++++++++--
>  qga/commands-win32.c   |   11 +++++++
>  3 files changed, 106 insertions(+), 3 deletions(-)
> 
> diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
> index d4055d2..d955cf1 100644
> --- a/qapi-schema-guest.json
> +++ b/qapi-schema-guest.json
> @@ -351,6 +351,26 @@
>    'returns': 'int' }
>  
>  ##
> +# @guest-fstrim:
> +#
> +# Discard (or "trim") blocks which are not in use by the filesystem.
> +#
> +# @minimum:
> +#       Minimum contiguous free range to discard, in bytes. Free ranges
> +#       smaller than this may be ignored (this is a hint and the guest
> +#       may not respect it).  By increasing this value, the fstrim
> +#       operation will complete more quickly for filesystems with badly
> +#       fragmented free space, although not all blocks will be discarded.
> +#       The default value is zero, meaning "discard every free block".
> +#
> +# Returns: Nothing.
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'guest-fstrim',
> +  'data': { '*minimum': 'int' } }
> +
> +##
>  # @guest-suspend-disk
>  #
>  # Suspend guest to disk.
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index b1a7ce6..5fcbef4 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -38,9 +38,12 @@ extern char **environ;
>  #include <sys/socket.h>
>  #include <net/if.h>
>  
> -#if defined(__linux__) && defined(FIFREEZE)
> +#ifdef FIFREEZE
>  #define CONFIG_FSFREEZE
>  #endif
> +#ifdef FITRIM
> +#define CONFIG_FSTRIM
> +#endif
>  #endif
>  
>  void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
> @@ -312,8 +315,7 @@ static void guest_file_init(void)
>  /* linux-specific implementations. avoid this if at all possible. */
>  #if defined(__linux__)
>  
> -#if defined(CONFIG_FSFREEZE)
> -
> +#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
>  typedef struct FsMount {
>      char *dirname;
>      char *devtype;
> @@ -378,6 +380,9 @@ static int build_fs_mount_list(FsMountList *mounts)
>  
>      return 0;
>  }
> +#endif
> +
> +#if defined(CONFIG_FSFREEZE)
>  
>  /*
>   * Return status of freeze/thaw
> @@ -525,6 +530,65 @@ static void guest_fsfreeze_cleanup(void)
>  }
>  #endif /* CONFIG_FSFREEZE */
>  
> +#if defined(CONFIG_FSTRIM)
> +/*
> + * Walk list of mounted file systems in the guest, and trim them.
> + */
> +void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
> +{
> +    int ret = 0;
> +    FsMountList mounts;
> +    struct FsMount *mount;
> +    int fd;
> +    char err_msg[512];
> +    struct fstrim_range r = {
> +        .start = 0,
> +        .len = -1,
> +        .minlen = has_minimum ? minimum : 0,
> +    };
> +
> +    slog("guest-fstrim called");
> +
> +    QTAILQ_INIT(&mounts);
> +    ret = build_fs_mount_list(&mounts);
> +    if (ret < 0) {
> +        return;
> +    }
> +
> +    QTAILQ_FOREACH(mount, &mounts, next) {
> +        fd = qemu_open(mount->dirname, O_RDONLY);
> +        if (fd == -1) {
> +            sprintf(err_msg, "failed to open %s, %s", mount->dirname,
> +                    strerror(errno));
> +            error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
> +            goto error;
> +        }
> +
> +        /* We try to cull filesytems we know won't work in advance, but other
> +         * filesytems may not implement fstrim for less obvious reasons.  
> These
> +         * will report EOPNOTSUPP; we simply ignore these errors.  Any other
> +         * error means an unexpected error, so return it in those cases.  In
> +         * some other cases ENOTTY will be reported (e.g. CD-ROMs).
> +         */
> +        ret = ioctl(fd, FITRIM, &r);
> +        if (ret == -1) {
> +            if (errno != ENOTTY && errno != EOPNOTSUPP) {
> +                sprintf(err_msg, "failed to trim %s, %s",
> +                        mount->dirname, strerror(errno));
> +                error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
> +                close(fd);
> +                goto error;
> +            }
> +        }
> +        close(fd);
> +    }
> +
> +error:
> +    free_fs_mount_list(&mounts);
> +}
> +#endif /* CONFIG_FSTRIM */
> +
> +
>  #define LINUX_SYS_STATE_FILE "/sys/power/state"
>  #define SUSPEND_SUPPORTED 0
>  #define SUSPEND_NOT_SUPPORTED 1
> @@ -918,7 +982,15 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
>  
>      return 0;
>  }
> +#endif /* CONFIG_FSFREEZE */
> +
> +#if !defined(CONFIG_FSTRIM)
> +void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
> +{
> +    error_set(err, QERR_UNSUPPORTED);
>  
> +    return;
> +}
>  #endif
>  
>  /* register init/cleanup routines for stateful command groups */
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index eb8d140..54bc546 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -173,6 +173,17 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
>      return 0;
>  }
>  
> +/*
> + * Walk list of mounted file systems in the guest, and discard unused
> + * areas.
> + */
> +void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
> +{
> +    error_set(err, QERR_UNSUPPORTED);
> +
> +    return;
> +}
> +
>  typedef enum {
>      GUEST_SUSPEND_MODE_DISK,
>      GUEST_SUSPEND_MODE_RAM
> 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]