]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rds: re-entry of rds_ib_xmit/rds_iw_xmit
authorWengang Wang <wen.gang.wang@oracle.com>
Wed, 12 Aug 2015 02:59:58 +0000 (10:59 +0800)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Wed, 26 Aug 2015 19:24:18 +0000 (12:24 -0700)
The BUG_ON at line 452/453 is triggered in function rds_send_xmit.

 441                         while (ret) {
 442                                 tmp = min_t(int, ret, sg->length -
 443                                                       conn->c_xmit_data_off);
 444                                 conn->c_xmit_data_off += tmp;
 445                                 ret -= tmp;
 446                                 if (conn->c_xmit_data_off == sg->length) {
 447                                         conn->c_xmit_data_off = 0;
 448                                         sg++;
 449                                         conn->c_xmit_sg++;
 450                                         if (ret != 0 && conn->c_xmit_sg == rm->data.op_nents)
 451                                                 printk(KERN_ERR "conn %p rm %p sg %p ret %d\n", conn, rm, sg, ret);
 452                                         BUG_ON(ret != 0 &&
 453                                                conn->c_xmit_sg == rm->data.op_nents);
 454                                 }
 455                         }

It is complaining that total sent length is bigger that we want to send.

rds_ib_xmit() is wrong for the second entry for the same rds_message returning
wrong value.

The sg and off passed by rds_send_xmit() to rds_ib_xmit() is based on
scatterlist.offset/length, but the rds_ib_xmit() action is based on
scatterlist.dma_address/dma_length. In case dma_length is larger than length
there is problem. for the 2nd and later entries of rds_ib_xmit() for same
rds_message, at least one of the following two is wrong:

1) the scatterlist to start with, the chosen one can be far beyond the correct
   one.
2) the offset to start with within the scatterlist.

Fix is to add op_dmasg and op_dmaoff fields to rm_data_op structure indicating
the scatterlist and offset within the it to start with for rds_ib_xmit()
respectively. The op_dmasg and op_dmaoff fields are initialized to zero
when doing dma mapping for the first time of the message and are changed
when filling send slots.

The same applies to rds_iw_xmit() too.

upstream commit: d655a9fbc8a51ac8d92db7ff5a599aab17dce3ca

Orabug: 21324078

Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
net/rds/ib_send.c
net/rds/iw_send.c
net/rds/rds.h

index de826b511e5f22575d812e292355718ab73c6626..0a476fa57e37e46e620eb41538082282671769d5 100644 (file)
@@ -579,6 +579,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
                }
 
                rds_message_addref(rm);
+               rm->data.op_dmasg = 0;
+               rm->data.op_dmaoff = 0;
                ic->i_data_op = &rm->data;
 
                /* Finalize the header */
@@ -649,7 +651,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
        send = &ic->i_sends[pos];
        first = send;
        prev = NULL;
-       scat = &ic->i_data_op->op_sg[sg];
+       scat = &ic->i_data_op->op_sg[rm->data.op_dmasg];
        i = 0;
        do {
                unsigned int len = 0;
@@ -671,17 +673,20 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
                /* Set up the data, if present */
                if (i < work_alloc
                    && scat != &rm->data.op_sg[rm->data.op_count]) {
-                       len = min(RDS_FRAG_SIZE, ib_sg_dma_len(dev, scat) - off);
+                       len = min(RDS_FRAG_SIZE,
+                               ib_sg_dma_len(dev, scat) - rm->data.op_dmaoff);
                        send->s_wr.num_sge = 2;
 
-                       send->s_sge[1].addr = ib_sg_dma_address(dev, scat) + off;
+                       send->s_sge[1].addr = ib_sg_dma_address(dev, scat);
+                       send->s_sge[1].addr += rm->data.op_dmaoff;
                        send->s_sge[1].length = len;
 
                        bytes_sent += len;
-                       off += len;
-                       if (off == ib_sg_dma_len(dev, scat)) {
+                       rm->data.op_dmaoff += len;
+                       if (rm->data.op_dmaoff == ib_sg_dma_len(dev, scat)) {
                                scat++;
-                               off = 0;
+                               rm->data.op_dmasg++;
+                               rm->data.op_dmaoff = 0;
                        }
                }
 
index 0055c26056d37c925dc4326caa50deb35704c5c7..33106547e4a639420663e03b64e6f946fb05468d 100644 (file)
@@ -582,6 +582,8 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm,
                ic->i_unsignaled_wrs = rds_iw_sysctl_max_unsig_wrs;
                ic->i_unsignaled_bytes = rds_iw_sysctl_max_unsig_bytes;
                rds_message_addref(rm);
+               rm->data.op_dmasg = 0;
+               rm->data.op_dmaoff = 0;
                ic->i_rm = rm;
 
                /* Finalize the header */
@@ -623,7 +625,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm,
        send = &ic->i_sends[pos];
        first = send;
        prev = NULL;
-       scat = &rm->data.op_sg[sg];
+       scat = &rm->data.op_sg[rm->data.op_dmasg];
        sent = 0;
        i = 0;
 
@@ -657,10 +659,11 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm,
 
                send = &ic->i_sends[pos];
 
-               len = min(RDS_FRAG_SIZE, ib_sg_dma_len(dev, scat) - off);
+               len = min(RDS_FRAG_SIZE,
+                         ib_sg_dma_len(dev, scat) - rm->data.op_dmaoff);
                rds_iw_xmit_populate_wr(ic, send, pos,
-                               ib_sg_dma_address(dev, scat) + off, len,
-                               send_flags);
+                       ib_sg_dma_address(dev, scat) + rm->data.op_dmaoff, len,
+                       send_flags);
 
                /*
                 * We want to delay signaling completions just enough to get
@@ -688,10 +691,11 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm,
                         &send->s_wr, send->s_wr.num_sge, send->s_wr.next);
 
                sent += len;
-               off += len;
-               if (off == ib_sg_dma_len(dev, scat)) {
+               rm->data.op_dmaoff += len;
+               if (rm->data.op_dmaoff == ib_sg_dma_len(dev, scat)) {
                        scat++;
-                       off = 0;
+                       rm->data.op_dmaoff = 0;
+                       rm->data.op_dmasg++;
                }
 
 add_header:
index 63a65cddc7c4930d9ec4c683a2e5b622afbf2c72..a80dfdb3ee4b7000fe23bff0e08db4897b6855b3 100644 (file)
@@ -421,6 +421,8 @@ struct rds_message {
                        struct rds_notifier     *op_notifier;
                        unsigned int            op_nents;
                        unsigned int            op_count;
+                       unsigned int            op_dmasg;
+                       unsigned int            op_dmaoff;
                        struct scatterlist      *op_sg;
                } data;
        };