]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
rxgen: Fix rxrpc_send_data()
authorDavid Howells <dhowells@redhat.com>
Tue, 15 Apr 2014 09:42:23 +0000 (10:42 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 15 Apr 2014 09:59:13 +0000 (10:59 +0100)
Make three Fixes to rxrpc_send_data():

 (1) Advance to the next buffer when filling the iovec array rather than
     endlessly cycling over the first one.

 (2) Only clear MSG_MORE if we have sent all the buffered data at the end of
     the transmission phase of a call.

 (3) Don't turn the return value of sendmsg() into just -1 or 0 as we need the
     number of bytes actually sent to allow us to correctly advance the buffer
     cursor.

Signed-off-by: David Howells <dhowells@redhat.com>
af_rxrpc.c

index 859a9da50e390c1614c120ac5aedc4cc5d7a437d..510b0914e854d6754f73f41fae43207b3176c1af 100644 (file)
@@ -329,6 +329,7 @@ int rxrpc_send_data(struct rx_call *call)
        size_t ctrllen;
        unsigned char control[128];
        struct iovec iov[16];
+       unsigned more;
        int ioc, ret, i;
 
        debug("-->rxrpc_send_data(%u,0x%x)\n", call->state, call->data_count);
@@ -348,6 +349,7 @@ int rxrpc_send_data(struct rx_call *call)
                abort();
        }
 
+more_to_send:
        /* Request an operation */
        ctrllen = 0;
        RXRPC_ADD_CALLID(control, ctrllen, (unsigned long)call);
@@ -374,6 +376,7 @@ int rxrpc_send_data(struct rx_call *call)
                free(sent);
        }
 
+       more = MSG_MORE;
        for (ioc = 0; ioc < 16; ioc++) {
                rxrpc_check_buf(cursor);
 
@@ -390,9 +393,12 @@ int rxrpc_send_data(struct rx_call *call)
                iov[ioc].iov_base = cursor->buf + io_cursor;
                iov[ioc].iov_len = end - io_cursor;
                if (cursor == call->buffer_tail) {
+                       if (!call->more)
+                               more = 0;
                        ioc++;
                        break;
                }
+               cursor = cursor->next;
        }
        msg.msg_iovlen = ioc;
 
@@ -403,8 +409,8 @@ int rxrpc_send_data(struct rx_call *call)
                debug("IOV[%02u] %04zu %p\n",
                      i, msg.msg_iov[i].iov_len, msg.msg_iov[i].iov_base);
 
-       ret = sendmsg(call->conn->fd, &msg, call->more ? MSG_MORE : 0) == -1 ? -1 : 0;
-       debug("SENDMSG: %d\n", ret);
+       ret = sendmsg(call->conn->fd, &msg, more);
+       debug("SENDMSG: %d%s\n", ret, more ? " [more]" : "");
        if (ret == -1)
                return -1;
 
@@ -436,6 +442,8 @@ int rxrpc_send_data(struct rx_call *call)
 
        rxrpc_check_call(call);
 
+       if (call->data_count > 0)
+               goto more_to_send;
        if (call->data_count == 0 && !call->more)
                call->state++;