Skip to content

Commit 91d2f14

Browse files
committed
Merge branch 'net/rds/4.3-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux
Santosh Shilimkar says: ==================== RDS: connection scalability and performance improvements [v4] Re-sending the same patches from v3 again since my repost of patch 05/14 from v3 was whitespace damaged. [v3] Updated patch "[PATCH v2 05/14] RDS: defer the over_batch work to send worker" as per David Miller's comment [4] to avoid the magic value usage. Patch now makes use of already available but unused send_batch_count module parameter. Rest of the patches are same as earlier version v2 [3] [v2]: Dropped "[PATCH 05/15] RDS: increase size of hash-table to 8K" from earlier version [1]. I plan to address the hash table scalability using re-sizable hash tables as suggested by David Laight and David Miller [2] This series addresses RDS connection bottlenecks on massive workloads and improve the RDMA performance almost by 3X. RDS TCP also gets a small gain of about 12%. RDS is being used in massive systems with high scalability where several hundred thousand end points and tens of thousands of local processes are operating in tens of thousand sockets. Being RC(reliable connection), socket bind and release happens very often and any inefficiencies in bind hash look ups hurts the overall system performance. RDS bin hash-table uses global spin-lock which is the biggest bottleneck. To make matter worst, it uses rcu inside global lock for hash buckets. This is being addressed by simply using per bucket rw lock which makes the locking simple and very efficient. The hash table size is still an issue and I plan to address it by using re-sizable hash tables as suggested on the list. For RDS RDMA improvement, the completion handling is revamped so that we can do batch completions. Both send and receive completion handlers are split logically to achieve the same. RDS 8K messages being one of the key usecase, mr pool is adapted to have the 8K mrs along with default 1M mrs. And while doing this, few fixes and couple of bottlenecks seen with rds_sendmsg() are addressed. Series applies against 4.3-rc1 as well net-next. Its tested on Oracle hardware with IB fabric for both bcopy as well as RDMA mode. RDS TCP is tested with iXGB NIC. Like last time, iWARP transport is untested with these changes. The patchset is also available at below git repo: git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux.git net/rds/4.3-v3 As a side note, the IB HCA driver I used for testing misses at least 3 important patches in upstream to see the full blown IB performance and am hoping to get that in mainline with help of them. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 6b92d0c + 0676651 commit 91d2f14

File tree

12 files changed

+448
-282
lines changed

12 files changed

+448
-282
lines changed

net/rds/af_rds.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,7 @@ static int rds_release(struct socket *sock)
7272
rds_clear_recv_queue(rs);
7373
rds_cong_remove_socket(rs);
7474

75-
/*
76-
* the binding lookup hash uses rcu, we need to
77-
* make sure we synchronize_rcu before we free our
78-
* entry
79-
*/
8075
rds_remove_bound(rs);
81-
synchronize_rcu();
8276

8377
rds_send_drop_to(rs, NULL);
8478
rds_rdma_drop_keys(rs);
@@ -588,6 +582,8 @@ static int rds_init(void)
588582
{
589583
int ret;
590584

585+
rds_bind_lock_init();
586+
591587
ret = rds_conn_init();
592588
if (ret)
593589
goto out;

net/rds/bind.c

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,48 +38,50 @@
3838
#include <linux/ratelimit.h>
3939
#include "rds.h"
4040

41+
struct bind_bucket {
42+
rwlock_t lock;
43+
struct hlist_head head;
44+
};
45+
4146
#define BIND_HASH_SIZE 1024
42-
static struct hlist_head bind_hash_table[BIND_HASH_SIZE];
43-
static DEFINE_SPINLOCK(rds_bind_lock);
47+
static struct bind_bucket bind_hash_table[BIND_HASH_SIZE];
4448

45-
static struct hlist_head *hash_to_bucket(__be32 addr, __be16 port)
49+
static struct bind_bucket *hash_to_bucket(__be32 addr, __be16 port)
4650
{
4751
return bind_hash_table + (jhash_2words((u32)addr, (u32)port, 0) &
4852
(BIND_HASH_SIZE - 1));
4953
}
5054

51-
static struct rds_sock *rds_bind_lookup(__be32 addr, __be16 port,
55+
/* must hold either read or write lock (write lock for insert != NULL) */
56+
static struct rds_sock *rds_bind_lookup(struct bind_bucket *bucket,
57+
__be32 addr, __be16 port,
5258
struct rds_sock *insert)
5359
{
5460
struct rds_sock *rs;
55-
struct hlist_head *head = hash_to_bucket(addr, port);
61+
struct hlist_head *head = &bucket->head;
5662
u64 cmp;
5763
u64 needle = ((u64)be32_to_cpu(addr) << 32) | be16_to_cpu(port);
5864

59-
rcu_read_lock();
60-
hlist_for_each_entry_rcu(rs, head, rs_bound_node) {
65+
hlist_for_each_entry(rs, head, rs_bound_node) {
6166
cmp = ((u64)be32_to_cpu(rs->rs_bound_addr) << 32) |
6267
be16_to_cpu(rs->rs_bound_port);
6368

6469
if (cmp == needle) {
65-
rcu_read_unlock();
70+
rds_sock_addref(rs);
6671
return rs;
6772
}
6873
}
69-
rcu_read_unlock();
7074

7175
if (insert) {
7276
/*
7377
* make sure our addr and port are set before
74-
* we are added to the list, other people
75-
* in rcu will find us as soon as the
76-
* hlist_add_head_rcu is done
78+
* we are added to the list.
7779
*/
7880
insert->rs_bound_addr = addr;
7981
insert->rs_bound_port = port;
8082
rds_sock_addref(insert);
8183

82-
hlist_add_head_rcu(&insert->rs_bound_node, head);
84+
hlist_add_head(&insert->rs_bound_node, head);
8385
}
8486
return NULL;
8587
}
@@ -93,16 +95,21 @@ static struct rds_sock *rds_bind_lookup(__be32 addr, __be16 port,
9395
struct rds_sock *rds_find_bound(__be32 addr, __be16 port)
9496
{
9597
struct rds_sock *rs;
98+
unsigned long flags;
99+
struct bind_bucket *bucket = hash_to_bucket(addr, port);
96100

97-
rs = rds_bind_lookup(addr, port, NULL);
101+
read_lock_irqsave(&bucket->lock, flags);
102+
rs = rds_bind_lookup(bucket, addr, port, NULL);
103+
read_unlock_irqrestore(&bucket->lock, flags);
98104

99-
if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
100-
rds_sock_addref(rs);
101-
else
105+
if (rs && sock_flag(rds_rs_to_sk(rs), SOCK_DEAD)) {
106+
rds_sock_put(rs);
102107
rs = NULL;
108+
}
103109

104110
rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
105111
ntohs(port));
112+
106113
return rs;
107114
}
108115

@@ -112,6 +119,7 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
112119
unsigned long flags;
113120
int ret = -EADDRINUSE;
114121
u16 rover, last;
122+
struct bind_bucket *bucket;
115123

116124
if (*port != 0) {
117125
rover = be16_to_cpu(*port);
@@ -121,42 +129,48 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
121129
last = rover - 1;
122130
}
123131

124-
spin_lock_irqsave(&rds_bind_lock, flags);
125-
126132
do {
133+
struct rds_sock *rrs;
127134
if (rover == 0)
128135
rover++;
129-
if (!rds_bind_lookup(addr, cpu_to_be16(rover), rs)) {
136+
137+
bucket = hash_to_bucket(addr, cpu_to_be16(rover));
138+
write_lock_irqsave(&bucket->lock, flags);
139+
rrs = rds_bind_lookup(bucket, addr, cpu_to_be16(rover), rs);
140+
write_unlock_irqrestore(&bucket->lock, flags);
141+
if (!rrs) {
130142
*port = rs->rs_bound_port;
131143
ret = 0;
132144
rdsdebug("rs %p binding to %pI4:%d\n",
133145
rs, &addr, (int)ntohs(*port));
134146
break;
147+
} else {
148+
rds_sock_put(rrs);
135149
}
136150
} while (rover++ != last);
137151

138-
spin_unlock_irqrestore(&rds_bind_lock, flags);
139-
140152
return ret;
141153
}
142154

143155
void rds_remove_bound(struct rds_sock *rs)
144156
{
145157
unsigned long flags;
158+
struct bind_bucket *bucket =
159+
hash_to_bucket(rs->rs_bound_addr, rs->rs_bound_port);
146160

147-
spin_lock_irqsave(&rds_bind_lock, flags);
161+
write_lock_irqsave(&bucket->lock, flags);
148162

149163
if (rs->rs_bound_addr) {
150164
rdsdebug("rs %p unbinding from %pI4:%d\n",
151165
rs, &rs->rs_bound_addr,
152166
ntohs(rs->rs_bound_port));
153167

154-
hlist_del_init_rcu(&rs->rs_bound_node);
168+
hlist_del_init(&rs->rs_bound_node);
155169
rds_sock_put(rs);
156170
rs->rs_bound_addr = 0;
157171
}
158172

159-
spin_unlock_irqrestore(&rds_bind_lock, flags);
173+
write_unlock_irqrestore(&bucket->lock, flags);
160174
}
161175

162176
int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
@@ -200,9 +214,13 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
200214

201215
out:
202216
release_sock(sk);
203-
204-
/* we might have called rds_remove_bound on error */
205-
if (ret)
206-
synchronize_rcu();
207217
return ret;
208218
}
219+
220+
void rds_bind_lock_init(void)
221+
{
222+
int i;
223+
224+
for (i = 0; i < BIND_HASH_SIZE; i++)
225+
rwlock_init(&bind_hash_table[i].lock);
226+
}

net/rds/ib.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@
4343
#include "rds.h"
4444
#include "ib.h"
4545

46-
static unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
47-
unsigned int fmr_message_size = RDS_FMR_SIZE + 1; /* +1 allows for unaligned MRs */
46+
unsigned int rds_ib_fmr_1m_pool_size = RDS_FMR_1M_POOL_SIZE;
47+
unsigned int rds_ib_fmr_8k_pool_size = RDS_FMR_8K_POOL_SIZE;
4848
unsigned int rds_ib_retry_count = RDS_IB_DEFAULT_RETRY_COUNT;
4949

50-
module_param(fmr_pool_size, int, 0444);
51-
MODULE_PARM_DESC(fmr_pool_size, " Max number of fmr per HCA");
52-
module_param(fmr_message_size, int, 0444);
53-
MODULE_PARM_DESC(fmr_message_size, " Max size of a RDMA transfer");
50+
module_param(rds_ib_fmr_1m_pool_size, int, 0444);
51+
MODULE_PARM_DESC(rds_ib_fmr_1m_pool_size, " Max number of 1M fmr per HCA");
52+
module_param(rds_ib_fmr_8k_pool_size, int, 0444);
53+
MODULE_PARM_DESC(rds_ib_fmr_8k_pool_size, " Max number of 8K fmr per HCA");
5454
module_param(rds_ib_retry_count, int, 0444);
5555
MODULE_PARM_DESC(rds_ib_retry_count, " Number of hw retries before reporting an error");
5656

@@ -97,8 +97,10 @@ static void rds_ib_dev_free(struct work_struct *work)
9797
struct rds_ib_device *rds_ibdev = container_of(work,
9898
struct rds_ib_device, free_work);
9999

100-
if (rds_ibdev->mr_pool)
101-
rds_ib_destroy_mr_pool(rds_ibdev->mr_pool);
100+
if (rds_ibdev->mr_8k_pool)
101+
rds_ib_destroy_mr_pool(rds_ibdev->mr_8k_pool);
102+
if (rds_ibdev->mr_1m_pool)
103+
rds_ib_destroy_mr_pool(rds_ibdev->mr_1m_pool);
102104
if (rds_ibdev->pd)
103105
ib_dealloc_pd(rds_ibdev->pd);
104106

@@ -148,9 +150,13 @@ static void rds_ib_add_one(struct ib_device *device)
148150
rds_ibdev->max_sge = min(dev_attr->max_sge, RDS_IB_MAX_SGE);
149151

150152
rds_ibdev->fmr_max_remaps = dev_attr->max_map_per_fmr?: 32;
151-
rds_ibdev->max_fmrs = dev_attr->max_fmr ?
152-
min_t(unsigned int, dev_attr->max_fmr, fmr_pool_size) :
153-
fmr_pool_size;
153+
rds_ibdev->max_1m_fmrs = dev_attr->max_mr ?
154+
min_t(unsigned int, (dev_attr->max_mr / 2),
155+
rds_ib_fmr_1m_pool_size) : rds_ib_fmr_1m_pool_size;
156+
157+
rds_ibdev->max_8k_fmrs = dev_attr->max_mr ?
158+
min_t(unsigned int, ((dev_attr->max_mr / 2) * RDS_MR_8K_SCALE),
159+
rds_ib_fmr_8k_pool_size) : rds_ib_fmr_8k_pool_size;
154160

155161
rds_ibdev->max_initiator_depth = dev_attr->max_qp_init_rd_atom;
156162
rds_ibdev->max_responder_resources = dev_attr->max_qp_rd_atom;
@@ -162,12 +168,25 @@ static void rds_ib_add_one(struct ib_device *device)
162168
goto put_dev;
163169
}
164170

165-
rds_ibdev->mr_pool = rds_ib_create_mr_pool(rds_ibdev);
166-
if (IS_ERR(rds_ibdev->mr_pool)) {
167-
rds_ibdev->mr_pool = NULL;
171+
rds_ibdev->mr_1m_pool =
172+
rds_ib_create_mr_pool(rds_ibdev, RDS_IB_MR_1M_POOL);
173+
if (IS_ERR(rds_ibdev->mr_1m_pool)) {
174+
rds_ibdev->mr_1m_pool = NULL;
168175
goto put_dev;
169176
}
170177

178+
rds_ibdev->mr_8k_pool =
179+
rds_ib_create_mr_pool(rds_ibdev, RDS_IB_MR_8K_POOL);
180+
if (IS_ERR(rds_ibdev->mr_8k_pool)) {
181+
rds_ibdev->mr_8k_pool = NULL;
182+
goto put_dev;
183+
}
184+
185+
rdsdebug("RDS/IB: max_mr = %d, max_wrs = %d, max_sge = %d, fmr_max_remaps = %d, max_1m_fmrs = %d, max_8k_fmrs = %d\n",
186+
dev_attr->max_fmr, rds_ibdev->max_wrs, rds_ibdev->max_sge,
187+
rds_ibdev->fmr_max_remaps, rds_ibdev->max_1m_fmrs,
188+
rds_ibdev->max_8k_fmrs);
189+
171190
INIT_LIST_HEAD(&rds_ibdev->ipaddr_list);
172191
INIT_LIST_HEAD(&rds_ibdev->conn_list);
173192

0 commit comments

Comments
 (0)