qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] qemu-ga: Add guest-fstrim command.
@ 2012-06-12 10:50 Paolo Bonzini
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 1/2] qemu-ga: make names more generic for mount list functions Paolo Bonzini
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command Paolo Bonzini
  0 siblings, 2 replies; 6+ messages in thread
From: Paolo Bonzini @ 2012-06-12 10:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: mprivozn, mdroth, lcapitulino

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.

Paolo Bonzini (2):
  qemu-ga: make names more generic for mount list functions
  qemu-ga: add guest-fstrim command

 qapi-schema-guest.json |   20 +++++++++
 qga/commands-posix.c   |  108 +++++++++++++++++++++++++++++++++++++++---------
 qga/commands-win32.c   |   11 +++++
 3 files changed, 120 insertions(+), 19 deletions(-)

-- 
1.7.10.2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/2] qemu-ga: make names more generic for mount list functions
  2012-06-12 10:50 [Qemu-devel] [PATCH 0/2] qemu-ga: Add guest-fstrim command Paolo Bonzini
@ 2012-06-12 10:50 ` Paolo Bonzini
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command Paolo Bonzini
  1 sibling, 0 replies; 6+ messages in thread
From: Paolo Bonzini @ 2012-06-12 10:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: mprivozn, mdroth, lcapitulino

We will use these functions and types for more than FSFREEZE, so rename them.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qga/commands-posix.c |   36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 00d035d..b1a7ce6 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -314,17 +314,17 @@ static void guest_file_init(void)
 
 #if defined(CONFIG_FSFREEZE)
 
-typedef struct GuestFsfreezeMount {
+typedef struct FsMount {
     char *dirname;
     char *devtype;
-    QTAILQ_ENTRY(GuestFsfreezeMount) next;
-} GuestFsfreezeMount;
+    QTAILQ_ENTRY(FsMount) next;
+} FsMount;
 
-typedef QTAILQ_HEAD(, GuestFsfreezeMount) GuestFsfreezeMountList;
+typedef QTAILQ_HEAD(, FsMount) FsMountList;
 
-static void guest_fsfreeze_free_mount_list(GuestFsfreezeMountList *mounts)
+static void free_fs_mount_list(FsMountList *mounts)
 {
-     GuestFsfreezeMount *mount, *temp;
+     FsMount *mount, *temp;
 
      if (!mounts) {
          return;
@@ -341,10 +341,10 @@ static void guest_fsfreeze_free_mount_list(GuestFsfreezeMountList *mounts)
 /*
  * Walk the mount table and build a list of local file systems
  */
-static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts)
+static int build_fs_mount_list(FsMountList *mounts)
 {
     struct mntent *ment;
-    GuestFsfreezeMount *mount;
+    FsMount *mount;
     char const *mtab = "/proc/self/mounts";
     FILE *fp;
 
@@ -367,7 +367,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts)
             continue;
         }
 
-        mount = g_malloc0(sizeof(GuestFsfreezeMount));
+        mount = g_malloc0(sizeof(FsMount));
         mount->dirname = g_strdup(ment->mnt_dir);
         mount->devtype = g_strdup(ment->mnt_type);
 
@@ -398,15 +398,15 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
 int64_t qmp_guest_fsfreeze_freeze(Error **err)
 {
     int ret = 0, i = 0;
-    GuestFsfreezeMountList mounts;
-    struct GuestFsfreezeMount *mount;
+    FsMountList mounts;
+    struct FsMount *mount;
     int fd;
     char err_msg[512];
 
     slog("guest-fsfreeze called");
 
     QTAILQ_INIT(&mounts);
-    ret = guest_fsfreeze_build_mount_list(&mounts);
+    ret = build_fs_mount_list(&mounts);
     if (ret < 0) {
         return ret;
     }
@@ -447,11 +447,11 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
         close(fd);
     }
 
-    guest_fsfreeze_free_mount_list(&mounts);
+    free_fs_mount_list(&mounts);
     return i;
 
 error:
-    guest_fsfreeze_free_mount_list(&mounts);
+    free_fs_mount_list(&mounts);
     qmp_guest_fsfreeze_thaw(NULL);
     return 0;
 }
@@ -462,12 +462,12 @@ error:
 int64_t qmp_guest_fsfreeze_thaw(Error **err)
 {
     int ret;
-    GuestFsfreezeMountList mounts;
-    GuestFsfreezeMount *mount;
+    FsMountList mounts;
+    FsMount *mount;
     int fd, i = 0, logged;
 
     QTAILQ_INIT(&mounts);
-    ret = guest_fsfreeze_build_mount_list(&mounts);
+    ret = build_fs_mount_list(&mounts);
     if (ret) {
         error_set(err, QERR_QGA_COMMAND_FAILED,
                   "failed to enumerate filesystems");
@@ -507,7 +507,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
     }
 
     ga_unset_frozen(ga_state);
-    guest_fsfreeze_free_mount_list(&mounts);
+    free_fs_mount_list(&mounts);
     return i;
 }
 
-- 
1.7.10.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command
  2012-06-12 10:50 [Qemu-devel] [PATCH 0/2] qemu-ga: Add guest-fstrim command Paolo Bonzini
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 1/2] qemu-ga: make names more generic for mount list functions Paolo Bonzini
@ 2012-06-12 10:50 ` Paolo Bonzini
  2012-06-12 19:54   ` Luiz Capitulino
  2012-06-12 21:05   ` Michael Roth
  1 sibling, 2 replies; 6+ messages in thread
From: Paolo Bonzini @ 2012-06-12 10:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: mprivozn, mdroth, lcapitulino

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 <pbonzini@redhat.com>
---
 qapi-schema-guest.json |   20 ++++++++++++++
 qga/commands-posix.c   |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
 qga/commands-win32.c   |   11 ++++++++
 3 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index d4055d2..72bedac 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: 0.15.0
+##
+{ '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..802d13a 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)
@@ -525,6 +528,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 +980,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
-- 
1.7.10.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command Paolo Bonzini
@ 2012-06-12 19:54   ` Luiz Capitulino
  2012-06-12 21:05   ` Michael Roth
  1 sibling, 0 replies; 6+ messages in thread
From: Luiz Capitulino @ 2012-06-12 19:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: mprivozn, qemu-devel, mdroth

On Tue, 12 Jun 2012 12:50:08 +0200
Paolo Bonzini <pbonzini@redhat.com> 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 <pbonzini@redhat.com>
> ---
>  qapi-schema-guest.json |   20 ++++++++++++++
>  qga/commands-posix.c   |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
>  qga/commands-win32.c   |   11 ++++++++
>  3 files changed, 102 insertions(+), 1 deletion(-)
> 
> diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
> index d4055d2..72bedac 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: 0.15.0

1.2. Otherwise looks good to me.

> +##
> +{ '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..802d13a 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)
> @@ -525,6 +528,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 +980,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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command
  2012-06-12 10:50 ` [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command Paolo Bonzini
  2012-06-12 19:54   ` Luiz Capitulino
@ 2012-06-12 21:05   ` Michael Roth
  2012-06-13  5:31     ` Paolo Bonzini
  1 sibling, 1 reply; 6+ messages in thread
From: Michael Roth @ 2012-06-12 21:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: mprivozn, qemu-devel, lcapitulino

On Tue, Jun 12, 2012 at 12:50:08PM +0200, 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 <pbonzini@redhat.com>
> ---
>  qapi-schema-guest.json |   20 ++++++++++++++
>  qga/commands-posix.c   |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
>  qga/commands-win32.c   |   11 ++++++++
>  3 files changed, 102 insertions(+), 1 deletion(-)
> 
> diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
> index d4055d2..72bedac 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: 0.15.0
> +##
> +{ '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..802d13a 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)
> @@ -525,6 +528,65 @@ static void guest_fsfreeze_cleanup(void)
>  }
>  #endif /* CONFIG_FSFREEZE */
> 
> +#if defined(CONFIG_FSTRIM)

The FsMount* stuff is still only declared if CONFIG_FSFREEZE is defined,
we'll need to make sure those are declared when CONFIG_FSTRIM is defined
as well.

Other than that looks good.

> +/*
> + * 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 +980,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
> -- 
> 1.7.10.2
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command
  2012-06-12 21:05   ` Michael Roth
@ 2012-06-13  5:31     ` Paolo Bonzini
  0 siblings, 0 replies; 6+ messages in thread
From: Paolo Bonzini @ 2012-06-13  5:31 UTC (permalink / raw)
  To: Michael Roth; +Cc: mprivozn, qemu-devel, lcapitulino

Il 12/06/2012 23:05, Michael Roth ha scritto:
> The FsMount* stuff is still only declared if CONFIG_FSFREEZE is defined,
> we'll need to make sure those are declared when CONFIG_FSTRIM is defined
> as well.

Shouldn't be a problem in practice as FIFREEZE is older:

fcccf502 (Takashi Sato          2009-01-09 16:40:59 -0800  332) #define FIFREEZE        _IOWR('X', 119, int)    /* Freeze */
fcccf502 (Takashi Sato          2009-01-09 16:40:59 -0800  333) #define FITHAW          _IOWR('X', 120, int)    /* Thaw */
367a51a3 (Lukas Czerner         2010-10-27 21:30:11 -0400  334) #define FITRIM          _IOWR('X', 121, struct fstrim_range)    /* Trim */

but I will fix it together with the version number.

Paolo

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-06-13  5:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-12 10:50 [Qemu-devel] [PATCH 0/2] qemu-ga: Add guest-fstrim command Paolo Bonzini
2012-06-12 10:50 ` [Qemu-devel] [PATCH 1/2] qemu-ga: make names more generic for mount list functions Paolo Bonzini
2012-06-12 10:50 ` [Qemu-devel] [PATCH 2/2] qemu-ga: add guest-fstrim command Paolo Bonzini
2012-06-12 19:54   ` Luiz Capitulino
2012-06-12 21:05   ` Michael Roth
2012-06-13  5:31     ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).