LIST_HEAD(msg_list);
        char *desc_buf;
        int credits_needed;
-       unsigned int desc_buf_len;
-       size_t total_length = 0;
+       unsigned int desc_buf_len, desc_num = 0;
 
        if (t->status != SMB_DIRECT_CS_CONNECTED)
                return -ENOTCONN;
 
+       if (buf_len > t->max_rdma_rw_size)
+               return -EINVAL;
+
        /* calculate needed credits */
        credits_needed = 0;
        desc_buf = buf;
        for (i = 0; i < desc_len / sizeof(*desc); i++) {
+               if (!buf_len)
+                       break;
+
                desc_buf_len = le32_to_cpu(desc[i].length);
+               if (!desc_buf_len)
+                       return -EINVAL;
+
+               if (desc_buf_len > buf_len) {
+                       desc_buf_len = buf_len;
+                       desc[i].length = cpu_to_le32(desc_buf_len);
+                       buf_len = 0;
+               }
 
                credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
                desc_buf += desc_buf_len;
-               total_length += desc_buf_len;
-               if (desc_buf_len == 0 || total_length > buf_len ||
-                   total_length > t->max_rdma_rw_size)
-                       return -EINVAL;
+               buf_len -= desc_buf_len;
+               desc_num++;
        }
 
        ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
 
        /* build rdma_rw_ctx for each descriptor */
        desc_buf = buf;
-       for (i = 0; i < desc_len / sizeof(*desc); i++) {
+       for (i = 0; i < desc_num; i++) {
                msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
                              sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
                if (!msg) {