qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: Michal Privoznik <mprivozn@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2] qga: Don't require 'time' argument in guest-set-time command
Date: Sun, 23 Feb 2014 19:00:46 -0600	[thread overview]
Message-ID: <20140224010046.3593.2853@loki> (raw)
In-Reply-To: <a2948dbe0f8a451b3f23fb2bc45357a0e7dc53de.1391164056.git.mprivozn@redhat.com>

Quoting Michal Privoznik (2014-01-31 04:29:51)
> As the description to the guest-set-time states, the command is
> there to ease time synchronization after resume. If guest was
> suspended for longer period of time, its system time can go off
> so badly, that even NTP refuses to set it. That's why the command
> was invented: to give users chance to set the time (not
> necessarily 100% correct). However, there's is no real need for
> us to require users to pass an arbitrary time. Especially if we
> can read the correct value from RTC (boiling down to reading
> host's time). Hence this commit enables logic:
> 
> guest-set-time() == guest-set-time($now_from_rtc)
> 
> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>

Thanks, applied to qga tree:                                                                                 

  https://github.com/mdroth/qemu/commits/qga

> ---
> diff to v1:
> -Fix checkpatch.pl warnings 
> 
>  qga/commands-posix.c | 41 +++++++++++++++++++++++++----------------
>  qga/commands-win32.c | 34 +++++++++++++++++++++++-----------
>  qga/qapi-schema.json |  9 +++++----
>  3 files changed, 53 insertions(+), 31 deletions(-)
> 
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 8100bee..7d6665a 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -142,7 +142,7 @@ int64_t qmp_guest_get_time(Error **errp)
>     return time_ns;
>  }
> 
> -void qmp_guest_set_time(int64_t time_ns, Error **errp)
> +void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
>  {
>      int ret;
>      int status;
> @@ -150,22 +150,28 @@ void qmp_guest_set_time(int64_t time_ns, Error **errp)
>      Error *local_err = NULL;
>      struct timeval tv;
> 
> -    /* year-2038 will overflow in case time_t is 32bit */
> -    if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
> -        error_setg(errp, "Time %" PRId64 " is too large", time_ns);
> -        return;
> +    /* If user has passed a time, validate and set it. */
> +    if (has_time) {
> +        /* year-2038 will overflow in case time_t is 32bit */
> +        if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
> +            error_setg(errp, "Time %" PRId64 " is too large", time_ns);
> +            return;
> +        }
> +
> +        tv.tv_sec = time_ns / 1000000000;
> +        tv.tv_usec = (time_ns % 1000000000) / 1000;
> +
> +        ret = settimeofday(&tv, NULL);
> +        if (ret < 0) {
> +            error_setg_errno(errp, errno, "Failed to set time to guest");
> +            return;
> +        }
>      }
> 
> -    tv.tv_sec = time_ns / 1000000000;
> -    tv.tv_usec = (time_ns % 1000000000) / 1000;
> -
> -    ret = settimeofday(&tv, NULL);
> -    if (ret < 0) {
> -        error_setg_errno(errp, errno, "Failed to set time to guest");
> -        return;
> -    }
> -
> -    /* Set the Hardware Clock to the current System Time. */
> +    /* Now, if user has passed a time to set and the system time is set, we
> +     * just need to synchronize the hardware clock. However, if no time was
> +     * passed, user is requesting the opposite: set the system time from the
> +     * hardware clock. */
>      pid = fork();
>      if (pid == 0) {
>          setsid();
> @@ -173,7 +179,10 @@ void qmp_guest_set_time(int64_t time_ns, Error **errp)
>          reopen_fd_to_null(1);
>          reopen_fd_to_null(2);
> 
> -        execle("/sbin/hwclock", "hwclock", "-w", NULL, environ);
> +        /* Use '/sbin/hwclock -w' to set RTC from the system time,
> +         * or '/sbin/hwclock -s' to set the system time from RTC. */
> +        execle("/sbin/hwclock", "hwclock", has_time ? "-w" : "-s",
> +               NULL, environ);
>          _exit(EXIT_FAILURE);
>      } else if (pid < 0) {
>          error_setg_errno(errp, errno, "failed to create child process");
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index a6a0af2..8245f95 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -370,25 +370,37 @@ int64_t qmp_guest_get_time(Error **errp)
>      return time_ns;
>  }
> 
> -void qmp_guest_set_time(int64_t time_ns, Error **errp)
> +void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
>  {
>      SYSTEMTIME ts;
>      FILETIME tf;
>      LONGLONG time;
> 
> -    if (time_ns < 0 || time_ns / 100 > INT64_MAX - W32_FT_OFFSET) {
> -        error_setg(errp, "Time %" PRId64 "is invalid", time_ns);
> -        return;
> -    }
> +    if (has_time) {
> +        /* Okay, user passed a time to set. Validate it. */
> +        if (time_ns < 0 || time_ns / 100 > INT64_MAX - W32_FT_OFFSET) {
> +            error_setg(errp, "Time %" PRId64 "is invalid", time_ns);
> +            return;
> +        }
> 
> -    time = time_ns / 100 + W32_FT_OFFSET;
> +        time = time_ns / 100 + W32_FT_OFFSET;
> 
> -    tf.dwLowDateTime = (DWORD) time;
> -    tf.dwHighDateTime = (DWORD) (time >> 32);
> +        tf.dwLowDateTime = (DWORD) time;
> +        tf.dwHighDateTime = (DWORD) (time >> 32);
> 
> -    if (!FileTimeToSystemTime(&tf, &ts)) {
> -        error_setg(errp, "Failed to convert system time %d", (int)GetLastError());
> -        return;
> +        if (!FileTimeToSystemTime(&tf, &ts)) {
> +            error_setg(errp, "Failed to convert system time %d",
> +                       (int)GetLastError());
> +            return;
> +        }
> +    } else {
> +        /* Otherwise read the time from RTC which contains the correct value.
> +         * Hopefully. */
> +        GetSystemTime(&ts);
> +        if (ts.wYear < 1601 || ts.wYear > 30827) {
> +            error_setg(errp, "Failed to get time");
> +            return;
> +        }
>      }
> 
>      acquire_privilege(SE_SYSTEMTIME_NAME, errp);
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index 245f968..80edca1 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -120,17 +120,18 @@
>  # This command tries to set guest time to the given value,
>  # then sets the Hardware Clock to the current System Time.
>  # This will make it easier for a guest to resynchronize
> -# without waiting for NTP.
> +# without waiting for NTP. If no @time is specified, then
> +# the time to set is read from RTC.
>  #
> -# @time: time of nanoseconds, relative to the Epoch of
> -#        1970-01-01 in UTC.
> +# @time: #optional time of nanoseconds, relative to the Epoch
> +#        of 1970-01-01 in UTC.
>  #
>  # Returns: Nothing on success.
>  #
>  # Since: 1.5
>  ##
>  { 'command': 'guest-set-time',
> -  'data': { 'time': 'int' } }
> +  'data': { '*time': 'int' } }
> 
>  ##
>  # @GuestAgentCommandInfo:
> -- 
> 1.8.5.2

      parent reply	other threads:[~2014-02-24  1:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-31 10:29 [Qemu-devel] [PATCH v2] qga: Don't require 'time' argument in guest-set-time command Michal Privoznik
2014-01-31 18:12 ` Eric Blake
2014-02-13 17:33   ` Michal Privoznik
2014-02-24  1:00 ` Michael Roth [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140224010046.3593.2853@loki \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=mprivozn@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).