> On 10 Nov 2015, at 11:41, Samuel Thibault <samuel.thiba...@ens-lyon.org> 
> wrote:
> 
> Andrew Cooper, on Tue 10 Nov 2015 10:46:44 +0000, wrote:
>> ml_interface_{read,write}() would miscalculate the quantity of
>> data/space in the ring if it crossed the ring boundary, and incorrectly
>> return a short read/write.
>> 
>> This causes a protocol stall, as either side of the ring ends up waiting
>> for what they believe to be the other side needing to take the next
>> action.
>> 
>> Correct the calculations to cope with crossing the ring boundary.
>> 
>> In addition, correct the error detection.  It is a hard error if the
>> producer index gets more than a ring size ahead of the consumer, or if
>> the consumer ever overtakes the producer.
>> 
>> Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com>
> 
> Reviewed-by: Samuel Thibault <samuel.thiba...@ens-lyon.org>

Looks good to me too

Reviewed-by: David Scott <d...@recoil.org>

> 
>> ---
>> CC: Ian Campbell <ian.campb...@citrix.com>
>> CC: Ian Jackson <ian.jack...@eu.citrix.com>
>> CC: Wei Liu <wei.l...@citrix.com>
>> CC: David Scott <d...@recoil.org>
>> CC: Samuel Thibault <samuel.thiba...@ens-lyon.org>
>> 
>> v2:
>> * Correct error handling adjustments
>> * More fixes to space calculations
>> * Fix whitespace errors
>> * No longer RFC - passed XenServer sanity testing
>> ---
>> tools/ocaml/libs/xb/xs_ring_stubs.c | 64 
>> +++++++++++++++++++++++++------------
>> 1 file changed, 44 insertions(+), 20 deletions(-)
>> 
>> diff --git a/tools/ocaml/libs/xb/xs_ring_stubs.c 
>> b/tools/ocaml/libs/xb/xs_ring_stubs.c
>> index fd561a2..4737870 100644
>> --- a/tools/ocaml/libs/xb/xs_ring_stubs.c
>> +++ b/tools/ocaml/libs/xb/xs_ring_stubs.c
>> @@ -50,7 +50,7 @@ CAMLprim value ml_interface_read(value ml_interface,
>> 
>>      struct xenstore_domain_interface *intf = interface->addr;
>>      XENSTORE_RING_IDX cons, prod; /* offsets only */
>> -    int to_read;
>> +    int total_data, data;
>>      uint32_t connection;
>> 
>>      cons = *(volatile uint32_t*)&intf->req_cons;
>> @@ -65,19 +65,28 @@ CAMLprim value ml_interface_read(value ml_interface,
>>      if ((prod - cons) > XENSTORE_RING_SIZE)
>>              caml_failwith("bad connection");
>> 
>> -    if (prod == cons) {
>> +    /* Check for any pending data at all. */
>> +    total_data = prod - cons;
>> +    if (total_data == 0) {
>> +            /* No pending data at all. */
>>              result = 0;
>>              goto exit;
>>      }
>> -    cons = MASK_XENSTORE_IDX(cons);
>> -    prod = MASK_XENSTORE_IDX(prod);
>> -    if (prod > cons)
>> -            to_read = prod - cons;
>> -    else
>> -            to_read = XENSTORE_RING_SIZE - cons;
>> -    if (to_read < len)
>> -            len = to_read;
>> -    memcpy(buffer, intf->req + cons, len);
>> +    else if (total_data < len)
>> +            /* Some data - make a partial read. */
>> +            len = total_data;
>> +
>> +    /* Check whether data crosses the end of the ring. */
>> +    data = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
>> +    if (len < data)
>> +            /* Data within the remaining part of the ring. */
>> +            memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len);
>> +    else {
>> +            /* Data crosses the ring boundary. Read both halves. */
>> +            memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), data);
>> +            memcpy(buffer + data, intf->req, len - data);
>> +    }
>> +
>>      xen_mb();
>>      intf->req_cons += len;
>>      result = len;
>> @@ -100,7 +109,7 @@ CAMLprim value ml_interface_write(value ml_interface,
>> 
>>      struct xenstore_domain_interface *intf = interface->addr;
>>      XENSTORE_RING_IDX cons, prod;
>> -    int can_write;
>> +    int total_space, space;
>>      uint32_t connection;
>> 
>>      cons = *(volatile uint32_t*)&intf->rsp_cons;
>> @@ -111,17 +120,32 @@ CAMLprim value ml_interface_write(value ml_interface,
>>              caml_raise_constant(*caml_named_value("Xb.Reconnect"));
>> 
>>      xen_mb();
>> -    if ( (prod - cons) >= XENSTORE_RING_SIZE ) {
>> +
>> +    if ((prod - cons) > XENSTORE_RING_SIZE)
>> +            caml_failwith("bad connection");
>> +
>> +    /* Check for space to write the full message. */
>> +    total_space = XENSTORE_RING_SIZE - (prod - cons);
>> +    if (total_space == 0) {
>> +            /* No space at all - exit having done nothing. */
>>              result = 0;
>>              goto exit;
>>      }
>> -    if (MASK_XENSTORE_IDX(prod) >= MASK_XENSTORE_IDX(cons))
>> -            can_write = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
>> -    else 
>> -            can_write = MASK_XENSTORE_IDX(cons) - MASK_XENSTORE_IDX(prod);
>> -    if (can_write < len)
>> -            len = can_write;
>> -    memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len);
>> +    else if (total_space < len)
>> +            /* Some space - make a partial write. */
>> +            len = total_space;
>> +
>> +    /* Check for space until the ring wraps. */
>> +    space = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
>> +    if (len < space)
>> +            /* Message fits inside the remaining part of the ring. */
>> +            memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len);
>> +    else {
>> +            /* Message wraps around the end of the ring. Write both halves. 
>> */
>> +            memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, space);
>> +            memcpy(intf->rsp, buffer + space, len - space);
>> +    }
>> +
>>      xen_mb();
>>      intf->rsp_prod += len;
>>      result = len;
>> -- 
>> 2.1.4
>> 
> 
> -- 
> Samuel
> As usual, this being a 1.3.x release, I haven't even compiled this
> kernel yet.  So if it works, you should be doubly impressed.
> (Linus Torvalds, announcing kernel 1.3.3 on the linux-kernel mailing list.)


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

Reply via email to