]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net/rds: use multiple sge than buddy allocation in congestion code
authorWei Lin Guay <wei.lin.guay@oracle.com>
Wed, 4 Oct 2017 09:45:19 +0000 (11:45 +0200)
committerDhaval Giani <dhaval.giani@oracle.com>
Wed, 15 Nov 2017 06:18:12 +0000 (01:18 -0500)
When commit ea6e04f14569 ("RDS: make congestion code independent of
PAGE_SIZE") was introduced, it used the buddy allocation with one
sge. Thus, this commit uses multiple sge to make congestion code
independent of PAGE_SIZE.

Orabug: 26770234

Signed-off-by: Wei Lin Guay <wei.lin.guay@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
Tested-by: Shih-Yu Huang <shih-yu.huang@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: Dhaval Giani <dhaval.giani@oracle.com>
net/rds/cong.c
net/rds/ib_recv.c
net/rds/rds.h

index 653707e56de95ddfd7dc643b31aebeb2c890b5c0..e2540be3deb03fac2e867ef0e42100544231ad4d 100644 (file)
@@ -138,7 +138,6 @@ static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
        unsigned long zp;
        unsigned long i;
        unsigned long flags;
-       gfp_t mask = GFP_KERNEL | __GFP_ZERO;
 
        map = kzalloc(sizeof(struct rds_cong_map), GFP_KERNEL);
        if (!map)
@@ -148,12 +147,12 @@ static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
        init_waitqueue_head(&map->m_waitq);
        INIT_LIST_HEAD(&map->m_conn_list);
 
-       zp = __get_free_pages(mask, get_order(RDS_CONG_MAP_BYTES));
-       if (zp == 0)
-               goto out;
-
-       for (i = 0; i < RDS_CONG_MAP_PAGES; i++)
-               map->m_page_addrs[i] = zp + i * RDS_CONG_PAGE_SIZE;
+       for (i = 0; i < RDS_CONG_MAP_PAGES; i++) {
+               zp = get_zeroed_page(GFP_KERNEL);
+               if (zp == 0)
+                       goto out;
+               map->m_page_addrs[i] = zp;
+       }
 
        spin_lock_irqsave(&rds_cong_lock, flags);
        ret = rds_cong_tree_walk(addr, map);
@@ -166,9 +165,8 @@ static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
 
 out:
        if (map) {
-               if (zp)
-                       __free_pages(virt_to_page(map->m_page_addrs[0]),
-                                    get_order(RDS_CONG_MAP_BYTES));
+               for (i = 0; i < RDS_CONG_MAP_PAGES && map->m_page_addrs[i]; i++)
+                       free_page(map->m_page_addrs[i]);
                kfree(map);
        }
 
@@ -180,7 +178,8 @@ out:
 static struct rds_message *rds_cong_map_pages(unsigned long *page_addrs, unsigned int total_len)
 {
        struct rds_message *rm;
-       int num_sgs = RDS_CONG_MAP_SGE;
+       unsigned int i;
+       int num_sgs = ceil(total_len, RDS_CONG_PAGE_SIZE);
        int extra_bytes = num_sgs * sizeof(struct scatterlist);
 
        rm = rds_message_alloc(extra_bytes, GFP_NOWAIT);
@@ -189,11 +188,15 @@ static struct rds_message *rds_cong_map_pages(unsigned long *page_addrs, unsigne
 
        set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
        rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
-       rm->data.op_nents = RDS_CONG_MAP_SGE;
+       rm->data.op_nents = num_sgs;
        rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
 
-       sg_set_page(&rm->data.op_sg[0], virt_to_page(page_addrs[0]),
-                   total_len, 0);
+       for (i = 0; i < rm->data.op_nents; i++) {
+               sg_set_page(&rm->data.op_sg[i],
+                           virt_to_page(page_addrs[i]),
+                           RDS_CONG_PAGE_SIZE, 0);
+       }
+
        return rm;
 }
 
@@ -400,14 +403,14 @@ void rds_cong_exit(void)
 {
        struct rb_node *node;
        struct rds_cong_map *map;
+       unsigned long i;
 
        while ((node = rb_first(&rds_cong_tree))) {
                map = rb_entry(node, struct rds_cong_map, m_rb_node);
                rdsdebug("freeing map %p\n", map);
                rb_erase(&map->m_rb_node, &rds_cong_tree);
-               if (map->m_page_addrs[0])
-                       __free_pages(virt_to_page(map->m_page_addrs[0]),
-                                    get_order(RDS_CONG_MAP_BYTES));
+               for (i = 0; i < RDS_CONG_MAP_PAGES && map->m_page_addrs[i]; i++)
+                       free_page(map->m_page_addrs[i]);
                kfree(map);
        }
 }
index ded40962c7766502c01d5a1f4cf26877bf207778..59f2047edbda13c38a1e8a069257cc32a34b1a9e 100644 (file)
@@ -1101,6 +1101,7 @@ static void rds_ib_cong_recv(struct rds_connection *conn,
        unsigned int map_off;
        unsigned int map_page;
        struct rds_page_frag *frag;
+       struct scatterlist *sg;
        unsigned long frag_off;
        unsigned long to_copy;
        unsigned long copied;
@@ -1119,17 +1120,18 @@ static void rds_ib_cong_recv(struct rds_connection *conn,
        frag_off = 0;
 
        copied = 0;
+       sg = frag->f_sg;
 
        while (copied < RDS_CONG_MAP_BYTES) {
                uint64_t *src, *dst;
                unsigned int k;
 
-               to_copy = min(ic->i_frag_sz - frag_off, RDS_CONG_PAGE_SIZE - map_off);
+               to_copy = min(sg->length - frag_off, RDS_CONG_PAGE_SIZE - map_off);
                BUG_ON(to_copy & 7); /* Must be 64bit aligned. */
 
-               addr = kmap_atomic(sg_page(frag->f_sg));
+               addr = kmap_atomic(sg_page(sg));
 
-               src = addr + frag->f_sg[0].offset + frag_off;
+               src = addr + sg->offset + frag_off;
                dst = (void *)map->m_page_addrs[map_page] + map_off;
                for (k = 0; k < to_copy; k += 8) {
                        /* Record ports that became uncongested, ie
@@ -1152,6 +1154,12 @@ static void rds_ib_cong_recv(struct rds_connection *conn,
                        frag = list_entry(frag->f_item.next,
                                          struct rds_page_frag, f_item);
                        frag_off = 0;
+                       sg = frag->f_sg;
+               }
+
+               if (frag_off == sg->length) {
+                       frag_off = 0;
+                       sg = sg_next(sg);
                }
        }
 
index 26c017c61c6c10e0bf314c64b773a3f1102e8b80..6fdbcac20d6aad72fa7388dbf9deb958cdda7612 100644 (file)
@@ -105,7 +105,6 @@ enum {
 #define RDS_CONG_MAP_LONGS     (RDS_CONG_MAP_BYTES / sizeof(unsigned long))
 #define RDS_CONG_MAP_PAGES     (PAGE_ALIGN(RDS_CONG_MAP_BYTES) / RDS_CONG_PAGE_SIZE)
 #define RDS_CONG_MAP_PAGE_BITS (RDS_CONG_PAGE_SIZE * 8)
-#define RDS_CONG_MAP_SGE       1
 
 struct rds_cong_map {
        struct rb_node          m_rb_node;