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

[Xen-changelog] [xen stable-4.6] tools/ocaml/xb: Correct calculations of data/space the ring



commit 6150df9f3f99ecbcbd9917002186d1d895b5602e
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Tue Nov 10 10:46:44 2015 +0000
Commit:     Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
CommitDate: Tue Jan 19 13:41:47 2016 +0000

    tools/ocaml/xb: Correct calculations of data/space the ring
    
    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.cooper3@xxxxxxxxxx>
    Reviewed-by: Wei Liu <wei.liu2@xxxxxxxxxx>
    Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
    Reviewed-by: David Scott <dave@xxxxxxxxxx>
    (cherry picked from commit 8a2c11f876e6cf9c74f2bcaed5a997adc57da888)
---
 tools/ocaml/libs/xb/xs_ring_stubs.c |   64 ++++++++++++++++++++++++-----------
 1 files 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;
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.6

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


 


Rackspace

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