[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH RFC] tools/ocaml/xb: Correct calculations of data/space the ring



On 28/10/15 16:18, Samuel Thibault wrote:
> Andrew Cooper, le Wed 28 Oct 2015 16:05:36 +0000, a écrit :
>> @@ -62,22 +62,32 @@ CAMLprim value ml_interface_read(value ml_interface,
>>  
>>      xen_mb();
>>  
>> -    if ((prod - cons) > XENSTORE_RING_SIZE)
>> +    if (((prod - cons) > XENSTORE_RING_SIZE) ||
>> +            ((cons - prod) < -XENSTORE_RING_SIZE))
> prod and cons are uint32_t, so the difference will still be unsigned.

The RHS will also be promoted to unsigned, as int has insufficient range
for the LHS.

> IIRC the test is not bogus even when prod wraps around, (prod - cons)
> will still correctly be the difference between both, modulo 2^32.

(prod - cons) >= XENSTORE_RING_SIZE checks for the prod getting more
than a ring's worth ahead of cons.

(cons - prod) < -XENSTORE_RING_SIZE is supposed to check for cons
getting ahead of prod (the naive (cons > prod) fails when the ring
wraps), although I notice it still buggy in the case where cons == prod.

>
> Indeed, the read side also needs the same two-memcpy fix.
>
>> +    /* Check for any pending data at all. */
>> +    total_data = prod - cons;
>> +    if (total_data == 0) {
> ...
>> +    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);
>> +    }
>> +
> That looks right and nice-looking to me.
>
>>      xen_mb();
>>      intf->req_cons += len;
>>      result = len;
>> @@ -100,7 +110,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 +121,33 @@ 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) ||
>> +            ((cons - prod) < -XENSTORE_RING_SIZE))
> Ditto.
>
>> +    /* Check for space to write the full message. */
>> +    total_space = prod - cons;
>> +    if (total_space == 0) {
> Shouldn't that be total_space == XENSTORE_RING_SIZE?

Yes - I think it should.  (I should probably kill my pending tests -
they are not going to get very far...)

~Andrew

>
>> +            /* No space at all - exit having done nothing. */
>>              result = 0;
>>              goto exit;
>>      }
>> +    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);
>> +    }
> That looks right and nicer-looking than my attempt :)
>
> Samuel


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.