All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close
@ 2010-08-18 15:01 Ian Campbell
  2010-08-18 16:04 ` Christoph Egger
  0 siblings, 1 reply; 5+ messages in thread
From: Ian Campbell @ 2010-08-18 15:01 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Campbell

# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1282143629 -3600
# Node ID b1f4b4be1f94c0007794f86abd019f5c2629c59b
# Parent  ddbd38da07397dca4760fb687551c3f6f9134700
libxc: free thread specific hypercall buffer on xc_interface_close

The per-thread hypercall buffer is usually cleaned up on pthread_exit
by the destructor passed to pthread_key_create. However if the calling
application is not threaded then the destructor is never called.

This frees the data for the current thread only but that is OK since
any other threads will be cleaned up by the destructor.

Changed since v1:
 * Ensure hcall_buf_pkey is initialised before use. Thanks to
   Christoph Egger for his help diagnosing this issue on NetBSD.
 * Remove redundant if (hcall_buf) from xc_clean_hcall_buf since
   _xc_clean_hcall_buf includes the same check.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>

diff -r ddbd38da0739 -r b1f4b4be1f94 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c	Wed Aug 18 13:14:57 2010 +0100
+++ b/tools/libxc/xc_private.c	Wed Aug 18 16:00:29 2010 +0100
@@ -57,6 +57,8 @@ xc_interface *xc_interface_open(xentooll
     return 0;
 }
 
+static void xc_clean_hcall_buf(void);
+
 int xc_interface_close(xc_interface *xch)
 {
     int rc = 0;
@@ -68,6 +70,9 @@ int xc_interface_close(xc_interface *xch
         rc = xc_interface_close_core(xch, xch->fd);
         if (rc) PERROR("Could not close hypervisor interface");
     }
+
+    xc_clean_hcall_buf();
+
     free(xch);
     return rc;
 }
@@ -180,6 +185,8 @@ int hcall_buf_prep(void **addr, size_t l
 int hcall_buf_prep(void **addr, size_t len) { return 0; }
 void hcall_buf_release(void **addr, size_t len) { }
 
+static void xc_clean_hcall_buf(void) { }
+
 #else /* !__sun__ */
 
 int lock_pages(void *addr, size_t len)
@@ -228,6 +235,13 @@ static void _xc_init_hcall_buf(void)
 static void _xc_init_hcall_buf(void)
 {
     pthread_key_create(&hcall_buf_pkey, _xc_clean_hcall_buf);
+}
+
+static void xc_clean_hcall_buf(void)
+{
+    pthread_once(&hcall_buf_pkey_once, _xc_init_hcall_buf);
+
+    _xc_clean_hcall_buf(pthread_getspecific(hcall_buf_pkey));
 }
 
 int hcall_buf_prep(void **addr, size_t len)

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

* Re: [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close
  2010-08-18 15:01 [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close Ian Campbell
@ 2010-08-18 16:04 ` Christoph Egger
  2010-08-18 16:26   ` Ian Campbell
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Egger @ 2010-08-18 16:04 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Campbell


This patch prevents me from starting a guest until
the outstanding issue - namely why is hcall_buf_prep() never called -
is solved.

Christoph



On Wednesday 18 August 2010 17:01:07 Ian Campbell wrote:
> # HG changeset patch
> # User Ian Campbell <ian.campbell@citrix.com>
> # Date 1282143629 -3600
> # Node ID b1f4b4be1f94c0007794f86abd019f5c2629c59b
> # Parent  ddbd38da07397dca4760fb687551c3f6f9134700
> libxc: free thread specific hypercall buffer on xc_interface_close
>
> The per-thread hypercall buffer is usually cleaned up on pthread_exit
> by the destructor passed to pthread_key_create. However if the calling
> application is not threaded then the destructor is never called.
>
> This frees the data for the current thread only but that is OK since
> any other threads will be cleaned up by the destructor.
>
> Changed since v1:
>  * Ensure hcall_buf_pkey is initialised before use. Thanks to
>    Christoph Egger for his help diagnosing this issue on NetBSD.
>  * Remove redundant if (hcall_buf) from xc_clean_hcall_buf since
>    _xc_clean_hcall_buf includes the same check.
>
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
>
> diff -r ddbd38da0739 -r b1f4b4be1f94 tools/libxc/xc_private.c
> --- a/tools/libxc/xc_private.c	Wed Aug 18 13:14:57 2010 +0100
> +++ b/tools/libxc/xc_private.c	Wed Aug 18 16:00:29 2010 +0100
> @@ -57,6 +57,8 @@ xc_interface *xc_interface_open(xentooll
>      return 0;
>  }
>
> +static void xc_clean_hcall_buf(void);
> +
>  int xc_interface_close(xc_interface *xch)
>  {
>      int rc = 0;
> @@ -68,6 +70,9 @@ int xc_interface_close(xc_interface *xch
>          rc = xc_interface_close_core(xch, xch->fd);
>          if (rc) PERROR("Could not close hypervisor interface");
>      }
> +
> +    xc_clean_hcall_buf();
> +
>      free(xch);
>      return rc;
>  }
> @@ -180,6 +185,8 @@ int hcall_buf_prep(void **addr, size_t l
>  int hcall_buf_prep(void **addr, size_t len) { return 0; }
>  void hcall_buf_release(void **addr, size_t len) { }
>
> +static void xc_clean_hcall_buf(void) { }
> +
>  #else /* !__sun__ */
>
>  int lock_pages(void *addr, size_t len)
> @@ -228,6 +235,13 @@ static void _xc_init_hcall_buf(void)
>  static void _xc_init_hcall_buf(void)
>  {
>      pthread_key_create(&hcall_buf_pkey, _xc_clean_hcall_buf);
> +}
> +
> +static void xc_clean_hcall_buf(void)
> +{
> +    pthread_once(&hcall_buf_pkey_once, _xc_init_hcall_buf);
> +
> +    _xc_clean_hcall_buf(pthread_getspecific(hcall_buf_pkey));
>  }
>
>  int hcall_buf_prep(void **addr, size_t len)
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel



-- 
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632

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

* Re: [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close
  2010-08-18 16:04 ` Christoph Egger
@ 2010-08-18 16:26   ` Ian Campbell
  2010-08-19 12:39     ` Christoph Egger
  0 siblings, 1 reply; 5+ messages in thread
From: Ian Campbell @ 2010-08-18 16:26 UTC (permalink / raw)
  To: Christoph Egger; +Cc: xen-devel@lists.xensource.com

[-- Attachment #1: Type: text/plain, Size: 3003 bytes --]

On Wed, 2010-08-18 at 17:04 +0100, Christoph Egger wrote:
> This patch prevents me from starting a guest until
> the outstanding issue - namely why is hcall_buf_prep() never called -
> is solved.

You wouldn't expect hcall_buf_prep to be called if you opened the xc
interface and then closed it without doing a hypercall which required
any locked down memory.

This updated version of the patch was intended to handle exactly this
case since it appears that under NetBSD it can cause issues.

Are you saying that you are seeing hypercalls which you expect to need
memory locking down but for which that has not happened?

The callers of hcall_buf_prep are pretty explicit and there aren't that
many of them.

With the attached patch to libxc I get the following output when
starting xend, so you see it is quite normal for the xc interface to be
called when hcall_buf_prep has never been called and we now handle that
case correctly.

        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_close
        xc_clean_hcall_buf
        _xc_init_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_open
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf

When starting a PV domain I get

        xc_interface_open
        xc_interface_close
        xc_clean_hcall_buf
        _xc_init_hcall_buf
        _xc_clean_hcall_buf
        Using config file "/etc/xen/debian-x86_32p-1".
        xc_interface_open
        hcall_buf_prep(0xbfb56ca8,144)
        _xc_init_hcall_buf
        hcall_buf_prep hcall_buf allocated at 0x804b0d8
        hcall_buf_prep hcall_buf->buf allocated at 0x804c000
        hcall_buf_prep using preallocated buffer at 0x804c000 for 0xbfb56ca8
        hcall_buf_release(0x804c000,144)
        hcall_buf_release releasing preallocated buffer at 0x804c000 for 0xbfb56ca8
        xc_interface_close
        xc_clean_hcall_buf
        _xc_clean_hcall_buf
        _xc_clean_hcall_buf unlock and free hcall_buf->buf 0x804c000
        _xc_clean_hcall_buf free hcall_buf 0x804b0d8

It is also safe to call _xc_clean_hcall_buf and then later call
hcall_buf_prep (and therefore allocate a buffer).

Ian.


[-- Attachment #2: foo --]
[-- Type: text/x-patch, Size: 3483 bytes --]

diff -r 02b341ca3612 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c	Wed Aug 18 16:36:25 2010 +0100
+++ b/tools/libxc/xc_private.c	Wed Aug 18 17:22:34 2010 +0100
@@ -49,6 +49,7 @@ xc_interface *xc_interface_open(xentooll
             goto err;
     }
 
+    fprintf(stderr, "%s %p\n", __func__, xch);
     return xch;
 
  err:
@@ -62,6 +63,8 @@ int xc_interface_close(xc_interface *xch
 int xc_interface_close(xc_interface *xch)
 {
     int rc = 0;
+
+    fprintf(stderr, "%s xch:%p\n", __func__, xch);
 
     xtl_logger_destroy(xch->dombuild_logger_tofree);
     xtl_logger_destroy(xch->error_handler_tofree);
@@ -218,14 +221,17 @@ static void _xc_clean_hcall_buf(void *m)
 {
     struct hcall_buf *hcall_buf = m;
 
+    fprintf(stderr, "%s\n", __func__);
     if ( hcall_buf )
     {
         if ( hcall_buf->buf )
         {
+            fprintf(stderr, "%s unlock and free hcall_buf->buf %p\n", __func__, hcall_buf->buf);
             unlock_pages(hcall_buf->buf, PAGE_SIZE);
             free(hcall_buf->buf);
         }
 
+        fprintf(stderr, "%s free hcall_buf %p\n", __func__, hcall_buf);
         free(hcall_buf);
     }
 
@@ -234,11 +240,14 @@ static void _xc_clean_hcall_buf(void *m)
 
 static void _xc_init_hcall_buf(void)
 {
+    fprintf(stderr, "%s\n", __func__);
     pthread_key_create(&hcall_buf_pkey, _xc_clean_hcall_buf);
 }
 
 static void xc_clean_hcall_buf(void)
 {
+    fprintf(stderr, "%s\n", __func__);
+
     pthread_once(&hcall_buf_pkey_once, _xc_init_hcall_buf);
 
     _xc_clean_hcall_buf(pthread_getspecific(hcall_buf_pkey));
@@ -247,6 +256,8 @@ int hcall_buf_prep(void **addr, size_t l
 int hcall_buf_prep(void **addr, size_t len)
 {
     struct hcall_buf *hcall_buf;
+
+    fprintf(stderr, "%s(%p,%zd)\n", __func__, *addr, len);
 
     pthread_once(&hcall_buf_pkey_once, _xc_init_hcall_buf);
 
@@ -257,6 +268,7 @@ int hcall_buf_prep(void **addr, size_t l
         if ( !hcall_buf )
             goto out;
         pthread_setspecific(hcall_buf_pkey, hcall_buf);
+        fprintf(stderr, "%s hcall_buf allocated at %p\n", __func__, hcall_buf);
     }
 
     if ( !hcall_buf->buf )
@@ -268,10 +280,12 @@ int hcall_buf_prep(void **addr, size_t l
             hcall_buf->buf = NULL;
             goto out;
         }
+        fprintf(stderr, "%s hcall_buf->buf allocated at %p\n", __func__, hcall_buf->buf);
     }
 
     if ( (len < PAGE_SIZE) && !hcall_buf->oldbuf )
     {
+        fprintf(stderr, "%s using preallocated buffer at %p for %p\n", __func__, hcall_buf->buf, *addr);
         memcpy(hcall_buf->buf, *addr, len);
         hcall_buf->oldbuf = *addr;
         *addr = hcall_buf->buf;
@@ -279,6 +293,7 @@ int hcall_buf_prep(void **addr, size_t l
     }
 
  out:
+    fprintf(stderr, "%s locking buffer at %p %zd\n", __func__, *addr, len);
     return lock_pages(*addr, len);
 }
 
@@ -286,14 +301,18 @@ void hcall_buf_release(void **addr, size
 {
     struct hcall_buf *hcall_buf = pthread_getspecific(hcall_buf_pkey);
 
+    fprintf(stderr, "%s(%p,%zd)\n", __func__, *addr, len);
+
     if ( hcall_buf && (hcall_buf->buf == *addr) )
     {
+        fprintf(stderr, "%s releasing preallocated buffer at %p for %p\n", __func__, hcall_buf->buf, hcall_buf->oldbuf);
         memcpy(hcall_buf->oldbuf, *addr, len);
         *addr = hcall_buf->oldbuf;
         hcall_buf->oldbuf = NULL;
     }
     else
     {
+        fprintf(stderr, "%s unlocking buffer at %p %zd\n", __func__, *addr, len);
         unlock_pages(*addr, len);
     }
 }

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* Re: [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close
  2010-08-18 16:26   ` Ian Campbell
@ 2010-08-19 12:39     ` Christoph Egger
  2010-08-19 12:48       ` Ian Campbell
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Egger @ 2010-08-19 12:39 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel@lists.xensource.com

On Wednesday 18 August 2010 18:26:28 Ian Campbell wrote:
> On Wed, 2010-08-18 at 17:04 +0100, Christoph Egger wrote:
> > This patch prevents me from starting a guest until
> > the outstanding issue - namely why is hcall_buf_prep() never called -
> > is solved.
>
> You wouldn't expect hcall_buf_prep to be called if you opened the xc
> interface and then closed it without doing a hypercall which required
> any locked down memory.
>
> This updated version of the patch was intended to handle exactly this
> case

Yes, it works. The issue was in the debug code itself. After
removing the trace code I am able to start guests again.

Thanks for your help.

> since it appears that under NetBSD it can cause issues. 

I am wondering why this issue didn't appear on Linux.
Does Linux have some kind of auto-initialization?

Christoph

-- 
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632

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

* Re: [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close
  2010-08-19 12:39     ` Christoph Egger
@ 2010-08-19 12:48       ` Ian Campbell
  0 siblings, 0 replies; 5+ messages in thread
From: Ian Campbell @ 2010-08-19 12:48 UTC (permalink / raw)
  To: Christoph Egger; +Cc: xen-devel@lists.xensource.com

On Thu, 2010-08-19 at 13:39 +0100, Christoph Egger wrote:
> On Wednesday 18 August 2010 18:26:28 Ian Campbell wrote:
> > On Wed, 2010-08-18 at 17:04 +0100, Christoph Egger wrote:
> > > This patch prevents me from starting a guest until
> > > the outstanding issue - namely why is hcall_buf_prep() never called -
> > > is solved.
> >
> > You wouldn't expect hcall_buf_prep to be called if you opened the xc
> > interface and then closed it without doing a hypercall which required
> > any locked down memory.
> >
> > This updated version of the patch was intended to handle exactly this
> > case
> 
> Yes, it works. The issue was in the debug code itself. After
> removing the trace code I am able to start guests again.
> 
> Thanks for your help.

Thanks for confirming.

> > since it appears that under NetBSD it can cause issues. 
> 
> I am wondering why this issue didn't appear on Linux.
> Does Linux have some kind of auto-initialization?

I think it's just good/bad luck one way or the other if an uninitialised
pthread_key_t looks valid to pthread_getspecific or not. Ultimately
pthread_key_t is likely just an integer so there is always a chance that
an uninitialised pthread_key_t looks like an existing valid key.

Ian.

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

end of thread, other threads:[~2010-08-19 12:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-18 15:01 [PATCH] libxc: free thread specific hypercall buffer on xc_interface_close Ian Campbell
2010-08-18 16:04 ` Christoph Egger
2010-08-18 16:26   ` Ian Campbell
2010-08-19 12:39     ` Christoph Egger
2010-08-19 12:48       ` Ian Campbell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.