]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: Make message size limit compliant with spec
authorAvinash Repaka <avinash.repaka@oracle.com>
Mon, 29 Feb 2016 23:30:57 +0000 (15:30 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 12 Dec 2016 03:37:11 +0000 (19:37 -0800)
This patch limits RDS messages(both RDMA & non-RDMA) and RDS MR size
to RDS_MAX_MSG_SIZE(1MB) irrespective of underlying transport layer.

Orabug: 24455231

This patch also takes care of adding rdma payload to total payload
before QoS check is done.

Orabug: 22303625

Signed-off-by: Avinash Repaka <avinash.repaka@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
net/rds/rdma.c
net/rds/rds.h
net/rds/send.c

index 37b99465ab77bea19ade0a1ad35adffad69a873a..9fe3bc342ef58573f1ccf336ef65f11fa9ec18cd 100644 (file)
@@ -39,7 +39,6 @@
 /*
  * XXX
  *  - build with sparse
- *  - should we limit the size of a mr region?  let transport return failure?
  *  - should we detect duplicate keys on a socket?  hmm.
  *  - an rdma is an mlock, apply rlimit?
  */
@@ -200,6 +199,15 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
                goto out;
        }
 
+       /*
+        * we restrict the size of mr irrespective of underlying transport
+        * To account for unaligned mr regions, we subtract one from nr_pages
+        */
+       if ((nr_pages - 1) > (RDS_MAX_MSG_SIZE >> PAGE_SHIFT)) {
+               ret = -EMSGSIZE;
+               goto out;
+       }
+
        rdsdebug("RDS: get_mr addr %llx len %llu nr_pages %u\n",
                args->vec.addr, args->vec.bytes, nr_pages);
 
index abfa291c0296c6dc91f4d63df9c957aa63625c51..4f1012c893633ec815569a5ad7ac22844e5a2c67 100644 (file)
@@ -99,6 +99,9 @@ enum {
 #define RDS_FRAG_SIZE  ((unsigned int)(1 << RDS_FRAG_SHIFT))
 #define RDS_MAX_FRAG_SIZE      SZ_16K
 
+/* Used to limit both RDMA and non-RDMA RDS message to 1MB */
+#define RDS_MAX_MSG_SIZE       ((unsigned int)(1 << 20))
+
 #define RDS_CONG_MAP_BYTES     (65536 / 8)
 #define RDS_CONG_PAGE_SIZE     (1UL << 12)
 #define RDS_CONG_MAP_LONGS     (RDS_CONG_MAP_BYTES / sizeof(unsigned long))
index 2b0888511c2edaa4f4820976301d678e1fb7350e..a15759099650194f425f74b238560a505656b4c9 100644 (file)
@@ -1171,20 +1171,25 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
        return ret;
 }
 
-static inline unsigned int rds_rdma_bytes(struct msghdr *msg)
+static inline int rds_rdma_bytes(struct msghdr *msg, size_t *rdma_bytes)
 {
        struct rds_rdma_args *args;
        struct cmsghdr *cmsg;
-       unsigned int rdma_bytes = 0;
 
        for_each_cmsghdr(cmsg, msg) {
+               if (!CMSG_OK(msg, cmsg))
+                       return -EINVAL;
+
+               if (cmsg->cmsg_level != SOL_RDS)
+                       continue;
+
                if (cmsg->cmsg_type == RDS_CMSG_RDMA_ARGS) {
                        args = CMSG_DATA(cmsg);
-                       rdma_bytes += args->remote_vec.bytes;
+                       *rdma_bytes += args->remote_vec.bytes;
                }
        }
 
-       return rdma_bytes;
+       return 0;
 }
 
 int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
@@ -1200,7 +1205,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        int queued = 0, allocated_mr = 0;
        int nonblock = msg->msg_flags & MSG_DONTWAIT;
        long timeo = sock_sndtimeo(sk, nonblock);
-       size_t total_payload_len = payload_len;
+       size_t total_payload_len = payload_len, rdma_payload_len = 0;
        bool large_page;
 
        /* Mirror Linux UDP mirror of BSD error message compatibility */
@@ -1236,6 +1241,15 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        }
        release_sock(sk);
 
+       ret = rds_rdma_bytes(msg, &rdma_payload_len);
+       if (ret)
+               goto out;
+
+       if (max_t(size_t, payload_len, rdma_payload_len) > RDS_MAX_MSG_SIZE) {
+               ret = -EMSGSIZE;
+               goto out;
+       }
+
        if (payload_len > rds_sk_sndbuf(rs)) {
                ret = -EMSGSIZE;
                goto out;
@@ -1267,8 +1281,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        /* For RDMA operation(s), add up rmda bytes to payload to make
         * sure its within system QoS threshold limits.
         */
-       if (rm->rdma.op_active)
-               total_payload_len += rds_rdma_bytes(msg);
+       total_payload_len += rdma_payload_len;
 
        if (rds_check_qos_threshold(rs->rs_tos, total_payload_len)) {
                ret = -EINVAL;