All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Ian Campbell <Ian.Campbell@citrix.com>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>,
	"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH 1 of 2] tools/ocaml: libxc bindings: Fix stub_xc_readconsolering()
Date: Fri, 15 Feb 2013 15:17:18 +0000	[thread overview]
Message-ID: <511E517E.7090709@citrix.com> (raw)
In-Reply-To: <1360938376.31407.83.camel@zakaz.uk.xensource.com>

On 15/02/13 14:26, Ian Campbell wrote:
> On Thu, 2013-02-14 at 19:29 +0000, Andrew Cooper wrote:
>> There are two problems with this function:
>>   * The caml_{enter,leave}_blocking_section() calls mean that two threads can
>>     compete for use of the static ring[] buffer.
>>   * It fails to retrieve the entire buffer if the hypervisor has used 32K or
>>     more of its console ring.
>>
>> Unfortunately, fixing the code in a sensible is rather difficult.  The Ocaml
>> caller expects to get the entire console ring in a single buffer.  There are
>> no mechanisms to ask Xen for the size of the console ring (which is fixed
>> after boot).
> It would be easy to add a sysctl to get this

Yes.  I didn't because of a combination of the reasons below, and
because I needed a fix for our automated testing, but I think I have had
a cunning idea.

>
>>   Even if there was a way to get the size of the console ring, the
>> XEN_SYSCTL_readconsole hypercall itself races with printk(), leading to
>> possibly discontinuities if the ring is full.
> Right, that one is tricky, but as you say we could accept the
> inefficiencies here.
>
>>   The requirement for a NULL
>> terminating string means that a full console ring will appear to fail when use
>> the correct power of two, forcing us to double up again.
> Double? Or just allocate buffersize + 1? We could also consider fixing
> the XEN_SYSCTL_readconsole interface to remove this issue.

Requires buffersize + 1 + nr_of_chars_from_a_raced_printk to get any
indication back from the hypercall that we have indeed read the full ring.

Choosing buffersize rounded up to the next PAGE_SIZE will suffice except
in extreme circumstances.

>
>> Furthermore, libxc will bounce the allocated buffer, as will caml_copy_string().
> You could avoid the first of these by using xc_hypercall_buffer_alloc or
> xc_hypercall_buffer_alloc_pages in the caller, these are exposed from
> libxc exactly to allow us to avoid bouncing of larger objects.

I will investigate using these.

~Andrew

>
>
>> On the other hand, this is very definitely for debugging and testing, so lets
>> do the best we can to get the entire buffer, and accept the inefficiencies.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>>
>> diff -r 63594ce1708f -r 1daa30509f1c tools/ocaml/libs/xc/xenctrl_stubs.c
>> --- a/tools/ocaml/libs/xc/xenctrl_stubs.c
>> +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
>> @@ -523,27 +523,55 @@ CAMLprim value stub_xc_evtchn_reset(valu
>>  	CAMLreturn(Val_unit);
>>  }
>>  
>> -
>> -#define RING_SIZE 32768
>> -static char ring[RING_SIZE];
>> -
>> +/* Maximum size of console ring we are prepared to read, 16MB */
>> +#define MAX_CONSOLE_RING_SIZE (1U << 24)
>>  CAMLprim value stub_xc_readconsolering(value xch)
>>  {
>> -	unsigned int size = RING_SIZE - 1;
>> -	char *ring_ptr = ring;
>> -	int retval;
>> +	/* 32K starting size (adj for loop doubling at start) */
>> +	unsigned int ring_size = 1U << 14;
>> +	unsigned int nr_chars = ring_size;
>> +	char * ring = NULL;
>> +	int r;
>>  
>>  	CAMLparam1(xch);
>> +	CAMLlocal1(conring);
>>  
>> -	caml_enter_blocking_section();
>> -	retval = xc_readconsolering(_H(xch), ring_ptr, &size, 0, 0, NULL);
>> -	caml_leave_blocking_section();
>> +	do
>> +	{
>> +		ring_size *= 2;
>> +		if ( ring_size > MAX_CONSOLE_RING_SIZE )
>> +		{
>> +			caml_failwith("Console ring too large");
>> +			CAMLreturn(Val_unit);
>> +		}
>> +		nr_chars = ring_size;
>>  
>> -	if (retval)
>> -		failwith_xc(_H(xch));
>> +		free(ring);
>> +		if ( ! ( ring = malloc(ring_size) ) )
>> +		{
>> +			caml_failwith("Out of memory");
>> +			CAMLreturn(Val_unit);
>> +		}
>>  
>> -	ring[size] = '\0';
>> -	CAMLreturn(caml_copy_string(ring));
>> +		caml_enter_blocking_section();
>> +		r = xc_readconsolering(_H(xch), ring, &nr_chars, 0, 0, NULL);
>> +		caml_leave_blocking_section();
>> +
>> +		if ( r )
>> +		{
>> +			failwith_xc(_H(xch));
>> +			free(ring);
>> +			CAMLreturn(Val_unit);
>> +		}
>> +
>> +		/* If nr_chars == ring_size, we have not read the entire ring.
>> +		 * Try again with a larger buffer. */
>> +	} while ( nr_chars >= ring_size );
>> +
>> +	ring[nr_chars] = '\0';
>> +	conring = caml_copy_string(ring);
>> +	free(ring);
>> +	CAMLreturn(conring);
>>  }
>>  
>>  CAMLprim value stub_xc_send_debug_keys(value xch, value keys)
>

      reply	other threads:[~2013-02-15 15:17 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-14 19:29 [PATCH 1 of 2] tools/ocaml: libxc bindings: Fix stub_xc_readconsolering() Andrew Cooper
2013-02-14 19:29 ` [PATCH 2 of 2] tools/ocaml: libxc bindings: Fix failwith_xc() Andrew Cooper
2013-02-15 14:27   ` Ian Campbell
2013-02-15 14:26 ` [PATCH 1 of 2] tools/ocaml: libxc bindings: Fix stub_xc_readconsolering() Ian Campbell
2013-02-15 15:17   ` Andrew Cooper [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=511E517E.7090709@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=xen-devel@lists.xen.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 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.