]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/rds/rdma.c
RDS: Clean up error handling in rds_cmsg_rdma_args
[net-next-2.6.git] / net / rds / rdma.c
index 48064673fc76dc7b19792fe3d5a7bcb49592ef98..334acdd32ab676552e48ab23006f5b75c136f970 100644 (file)
@@ -502,6 +502,13 @@ static int rds_rdma_pages(struct rds_rdma_args *args)
                        return -EINVAL;
 
                tot_pages += nr_pages;
+
+               /*
+                * nr_pages for one entry is limited to (UINT_MAX>>PAGE_SHIFT)+1,
+                * so tot_pages cannot overflow without first going negative.
+                */
+               if ((int)tot_pages < 0)
+                       return -EINVAL;
        }
 
        return tot_pages;
@@ -522,7 +529,7 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
        struct rds_rdma_args *args;
        struct rds_iovec vec;
        struct rm_rdma_op *op = &rm->rdma;
-       unsigned int nr_pages;
+       int nr_pages;
        unsigned int nr_bytes;
        struct page **pages = NULL;
        struct rds_iovec __user *local_vec;
@@ -547,8 +554,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
        }
 
        nr_pages = rds_rdma_pages(args);
-       if (nr_pages < 0)
+       if (nr_pages < 0) {
+               ret = -EINVAL;
                goto out;
+       }
 
        pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
        if (!pages) {
@@ -655,13 +664,12 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
        }
        op->op_bytes = nr_bytes;
 
-       ret = 0;
 out:
        kfree(pages);
        if (ret)
                rds_rdma_free_op(op);
-
-       rds_stats_inc(s_send_rdma);
+       else
+               rds_stats_inc(s_send_rdma);
 
        return ret;
 }