aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-09 17:31:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-09 17:31:18 -0400
commit0d10c2c170e3384dd63f40216d7af4673d5ebb50 (patch)
tree2ce6760501b92ab279677edc3c8d981183ad97f6 /net
parent023f78b02c729070116fa3a7ebd4107a032d3f5c (diff)
parentd1e458fe671baf1e60afafc88bda090202a412f1 (diff)
Merge branch 'for-3.17' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: "This includes a major rewrite of the NFSv4 state code, which has always depended on a single mutex. As an example, open creates are no longer serialized, fixing a performance regression on NFSv3->NFSv4 upgrades. Thanks to Jeff, Trond, and Benny, and to Christoph for review. Also some RDMA fixes from Chuck Lever and Steve Wise, and miscellaneous fixes from Kinglong Mee and others" * 'for-3.17' of git://linux-nfs.org/~bfields/linux: (167 commits) svcrdma: remove rdma_create_qp() failure recovery logic nfsd: add some comments to the nfsd4 object definitions nfsd: remove the client_mutex and the nfs4_lock/unlock_state wrappers nfsd: remove nfs4_lock_state: nfs4_state_shutdown_net nfsd: remove nfs4_lock_state: nfs4_laundromat nfsd: Remove nfs4_lock_state(): reclaim_complete() nfsd: Remove nfs4_lock_state(): setclientid, setclientid_confirm, renew nfsd: Remove nfs4_lock_state(): exchange_id, create/destroy_session() nfsd: Remove nfs4_lock_state(): nfsd4_open and nfsd4_open_confirm nfsd: Remove nfs4_lock_state(): nfsd4_delegreturn() nfsd: Remove nfs4_lock_state(): nfsd4_open_downgrade + nfsd4_close nfsd: Remove nfs4_lock_state(): nfsd4_lock/locku/lockt() nfsd: Remove nfs4_lock_state(): nfsd4_release_lockowner nfsd: Remove nfs4_lock_state(): nfsd4_test_stateid/nfsd4_free_stateid nfsd: Remove nfs4_lock_state(): nfs4_preprocess_stateid_op() nfsd: remove old fault injection infrastructure nfsd: add more granular locking to *_delegations fault injectors nfsd: add more granular locking to forget_openowners fault injector nfsd: add more granular locking to forget_locks fault injector nfsd: add a list_head arg to nfsd_foreach_client_lock ...
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c2
-rw-r--r--net/sunrpc/svc.c4
-rw-r--r--net/sunrpc/svc_xprt.c27
-rw-r--r--net/sunrpc/svcsock.c50
-rw-r--r--net/sunrpc/xdr.c3
-rw-r--r--net/sunrpc/xprt.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c28
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c39
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c20
9 files changed, 103 insertions, 72 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 4ce5eccec1f6..c548ab213f76 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -886,7 +886,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
886 u32 priv_len, maj_stat; 886 u32 priv_len, maj_stat;
887 int pad, saved_len, remaining_len, offset; 887 int pad, saved_len, remaining_len, offset;
888 888
889 rqstp->rq_splice_ok = 0; 889 rqstp->rq_splice_ok = false;
890 890
891 priv_len = svc_getnl(&buf->head[0]); 891 priv_len = svc_getnl(&buf->head[0]);
892 if (rqstp->rq_deferred) { 892 if (rqstp->rq_deferred) {
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 5de6801cd924..1db5007ddbce 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1086,9 +1086,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
1086 goto err_short_len; 1086 goto err_short_len;
1087 1087
1088 /* Will be turned off only in gss privacy case: */ 1088 /* Will be turned off only in gss privacy case: */
1089 rqstp->rq_splice_ok = 1; 1089 rqstp->rq_splice_ok = true;
1090 /* Will be turned off only when NFSv4 Sessions are used */ 1090 /* Will be turned off only when NFSv4 Sessions are used */
1091 rqstp->rq_usedeferral = 1; 1091 rqstp->rq_usedeferral = true;
1092 rqstp->rq_dropme = false; 1092 rqstp->rq_dropme = false;
1093 1093
1094 /* Setup reply header */ 1094 /* Setup reply header */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index b4737fbdec13..6666c6745858 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -23,6 +23,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp);
23static struct cache_deferred_req *svc_defer(struct cache_req *req); 23static struct cache_deferred_req *svc_defer(struct cache_req *req);
24static void svc_age_temp_xprts(unsigned long closure); 24static void svc_age_temp_xprts(unsigned long closure);
25static void svc_delete_xprt(struct svc_xprt *xprt); 25static void svc_delete_xprt(struct svc_xprt *xprt);
26static void svc_xprt_do_enqueue(struct svc_xprt *xprt);
26 27
27/* apparently the "standard" is that clients close 28/* apparently the "standard" is that clients close
28 * idle connections after 5 minutes, servers after 29 * idle connections after 5 minutes, servers after
@@ -222,11 +223,12 @@ static void svc_xprt_received(struct svc_xprt *xprt)
222 if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) 223 if (!test_bit(XPT_BUSY, &xprt->xpt_flags))
223 return; 224 return;
224 /* As soon as we clear busy, the xprt could be closed and 225 /* As soon as we clear busy, the xprt could be closed and
225 * 'put', so we need a reference to call svc_xprt_enqueue with: 226 * 'put', so we need a reference to call svc_xprt_do_enqueue with:
226 */ 227 */
227 svc_xprt_get(xprt); 228 svc_xprt_get(xprt);
229 smp_mb__before_atomic();
228 clear_bit(XPT_BUSY, &xprt->xpt_flags); 230 clear_bit(XPT_BUSY, &xprt->xpt_flags);
229 svc_xprt_enqueue(xprt); 231 svc_xprt_do_enqueue(xprt);
230 svc_xprt_put(xprt); 232 svc_xprt_put(xprt);
231} 233}
232 234
@@ -335,12 +337,7 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
335 return false; 337 return false;
336} 338}
337 339
338/* 340static void svc_xprt_do_enqueue(struct svc_xprt *xprt)
339 * Queue up a transport with data pending. If there are idle nfsd
340 * processes, wake 'em up.
341 *
342 */
343void svc_xprt_enqueue(struct svc_xprt *xprt)
344{ 341{
345 struct svc_pool *pool; 342 struct svc_pool *pool;
346 struct svc_rqst *rqstp; 343 struct svc_rqst *rqstp;
@@ -398,6 +395,18 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
398out_unlock: 395out_unlock:
399 spin_unlock_bh(&pool->sp_lock); 396 spin_unlock_bh(&pool->sp_lock);
400} 397}
398
399/*
400 * Queue up a transport with data pending. If there are idle nfsd
401 * processes, wake 'em up.
402 *
403 */
404void svc_xprt_enqueue(struct svc_xprt *xprt)
405{
406 if (test_bit(XPT_BUSY, &xprt->xpt_flags))
407 return;
408 svc_xprt_do_enqueue(xprt);
409}
401EXPORT_SYMBOL_GPL(svc_xprt_enqueue); 410EXPORT_SYMBOL_GPL(svc_xprt_enqueue);
402 411
403/* 412/*
@@ -439,6 +448,8 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
439 atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); 448 atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved);
440 rqstp->rq_reserved = space; 449 rqstp->rq_reserved = space;
441 450
451 if (xprt->xpt_ops->xpo_adjust_wspace)
452 xprt->xpt_ops->xpo_adjust_wspace(xprt);
442 svc_xprt_enqueue(xprt); 453 svc_xprt_enqueue(xprt);
443 } 454 }
444} 455}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index b507cd327d9b..c24a8ff33f8f 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -446,15 +446,43 @@ static void svc_write_space(struct sock *sk)
446 } 446 }
447} 447}
448 448
449static int svc_tcp_has_wspace(struct svc_xprt *xprt)
450{
451 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
452 struct svc_serv *serv = svsk->sk_xprt.xpt_server;
453 int required;
454
455 if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
456 return 1;
457 required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
458 if (sk_stream_wspace(svsk->sk_sk) >= required ||
459 (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
460 atomic_read(&xprt->xpt_reserved) == 0))
461 return 1;
462 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
463 return 0;
464}
465
449static void svc_tcp_write_space(struct sock *sk) 466static void svc_tcp_write_space(struct sock *sk)
450{ 467{
468 struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
451 struct socket *sock = sk->sk_socket; 469 struct socket *sock = sk->sk_socket;
452 470
453 if (sk_stream_is_writeable(sk) && sock) 471 if (!sk_stream_is_writeable(sk) || !sock)
472 return;
473 if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt))
454 clear_bit(SOCK_NOSPACE, &sock->flags); 474 clear_bit(SOCK_NOSPACE, &sock->flags);
455 svc_write_space(sk); 475 svc_write_space(sk);
456} 476}
457 477
478static void svc_tcp_adjust_wspace(struct svc_xprt *xprt)
479{
480 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
481
482 if (svc_tcp_has_wspace(xprt))
483 clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
484}
485
458/* 486/*
459 * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo 487 * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo
460 */ 488 */
@@ -692,6 +720,7 @@ static struct svc_xprt_class svc_udp_class = {
692 .xcl_owner = THIS_MODULE, 720 .xcl_owner = THIS_MODULE,
693 .xcl_ops = &svc_udp_ops, 721 .xcl_ops = &svc_udp_ops,
694 .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, 722 .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP,
723 .xcl_ident = XPRT_TRANSPORT_UDP,
695}; 724};
696 725
697static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) 726static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
@@ -1197,23 +1226,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
1197 svc_putnl(resv, 0); 1226 svc_putnl(resv, 0);
1198} 1227}
1199 1228
1200static int svc_tcp_has_wspace(struct svc_xprt *xprt)
1201{
1202 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1203 struct svc_serv *serv = svsk->sk_xprt.xpt_server;
1204 int required;
1205
1206 if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
1207 return 1;
1208 required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
1209 if (sk_stream_wspace(svsk->sk_sk) >= required ||
1210 (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
1211 atomic_read(&xprt->xpt_reserved) == 0))
1212 return 1;
1213 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
1214 return 0;
1215}
1216
1217static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, 1229static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
1218 struct net *net, 1230 struct net *net,
1219 struct sockaddr *sa, int salen, 1231 struct sockaddr *sa, int salen,
@@ -1285,6 +1297,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
1285 .xpo_has_wspace = svc_tcp_has_wspace, 1297 .xpo_has_wspace = svc_tcp_has_wspace,
1286 .xpo_accept = svc_tcp_accept, 1298 .xpo_accept = svc_tcp_accept,
1287 .xpo_secure_port = svc_sock_secure_port, 1299 .xpo_secure_port = svc_sock_secure_port,
1300 .xpo_adjust_wspace = svc_tcp_adjust_wspace,
1288}; 1301};
1289 1302
1290static struct svc_xprt_class svc_tcp_class = { 1303static struct svc_xprt_class svc_tcp_class = {
@@ -1292,6 +1305,7 @@ static struct svc_xprt_class svc_tcp_class = {
1292 .xcl_owner = THIS_MODULE, 1305 .xcl_owner = THIS_MODULE,
1293 .xcl_ops = &svc_tcp_ops, 1306 .xcl_ops = &svc_tcp_ops,
1294 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, 1307 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
1308 .xcl_ident = XPRT_TRANSPORT_TCP,
1295}; 1309};
1296 1310
1297void svc_init_xprt_sock(void) 1311void svc_init_xprt_sock(void)
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 23fb4e75e245..290af97bf6f9 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -509,7 +509,8 @@ void xdr_commit_encode(struct xdr_stream *xdr)
509} 509}
510EXPORT_SYMBOL_GPL(xdr_commit_encode); 510EXPORT_SYMBOL_GPL(xdr_commit_encode);
511 511
512__be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, size_t nbytes) 512static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
513 size_t nbytes)
513{ 514{
514 static __be32 *p; 515 static __be32 *p;
515 int space_left; 516 int space_left;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index c3b2b3369e52..51c63165073c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1306,7 +1306,7 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
1306 } 1306 }
1307 } 1307 }
1308 spin_unlock(&xprt_list_lock); 1308 spin_unlock(&xprt_list_lock);
1309 printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); 1309 dprintk("RPC: transport (%d) not supported\n", args->ident);
1310 return ERR_PTR(-EIO); 1310 return ERR_PTR(-EIO);
1311 1311
1312found: 1312found:
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 8f92a61ee2df..e0110270d650 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -43,6 +43,7 @@
43#include <linux/sunrpc/debug.h> 43#include <linux/sunrpc/debug.h>
44#include <linux/sunrpc/rpc_rdma.h> 44#include <linux/sunrpc/rpc_rdma.h>
45#include <linux/spinlock.h> 45#include <linux/spinlock.h>
46#include <linux/highmem.h>
46#include <asm/unaligned.h> 47#include <asm/unaligned.h>
47#include <rdma/ib_verbs.h> 48#include <rdma/ib_verbs.h>
48#include <rdma/rdma_cm.h> 49#include <rdma/rdma_cm.h>
@@ -435,6 +436,32 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
435 return ret; 436 return ret;
436} 437}
437 438
439/*
440 * To avoid a separate RDMA READ just for a handful of zero bytes,
441 * RFC 5666 section 3.7 allows the client to omit the XDR zero pad
442 * in chunk lists.
443 */
444static void
445rdma_fix_xdr_pad(struct xdr_buf *buf)
446{
447 unsigned int page_len = buf->page_len;
448 unsigned int size = (XDR_QUADLEN(page_len) << 2) - page_len;
449 unsigned int offset, pg_no;
450 char *p;
451
452 if (size == 0)
453 return;
454
455 pg_no = page_len >> PAGE_SHIFT;
456 offset = page_len & ~PAGE_MASK;
457 p = page_address(buf->pages[pg_no]);
458 memset(p + offset, 0, size);
459
460 buf->page_len += size;
461 buf->buflen += size;
462 buf->len += size;
463}
464
438static int rdma_read_complete(struct svc_rqst *rqstp, 465static int rdma_read_complete(struct svc_rqst *rqstp,
439 struct svc_rdma_op_ctxt *head) 466 struct svc_rdma_op_ctxt *head)
440{ 467{
@@ -449,6 +476,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
449 rqstp->rq_pages[page_no] = head->pages[page_no]; 476 rqstp->rq_pages[page_no] = head->pages[page_no];
450 } 477 }
451 /* Point rq_arg.pages past header */ 478 /* Point rq_arg.pages past header */
479 rdma_fix_xdr_pad(&head->arg);
452 rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; 480 rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count];
453 rqstp->rq_arg.page_len = head->arg.page_len; 481 rqstp->rq_arg.page_len = head->arg.page_len;
454 rqstp->rq_arg.page_base = head->arg.page_base; 482 rqstp->rq_arg.page_base = head->arg.page_base;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 49fd21a5c215..9f1b50689c0f 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -192,6 +192,8 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
192 xdr_sge_no++; 192 xdr_sge_no++;
193 BUG_ON(xdr_sge_no > vec->count); 193 BUG_ON(xdr_sge_no > vec->count);
194 bc -= sge_bytes; 194 bc -= sge_bytes;
195 if (sge_no == xprt->sc_max_sge)
196 break;
195 } 197 }
196 198
197 /* Prepare WRITE WR */ 199 /* Prepare WRITE WR */
@@ -209,7 +211,7 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
209 atomic_inc(&rdma_stat_write); 211 atomic_inc(&rdma_stat_write);
210 if (svc_rdma_send(xprt, &write_wr)) 212 if (svc_rdma_send(xprt, &write_wr))
211 goto err; 213 goto err;
212 return 0; 214 return write_len - bc;
213 err: 215 err:
214 svc_rdma_unmap_dma(ctxt); 216 svc_rdma_unmap_dma(ctxt);
215 svc_rdma_put_context(ctxt, 0); 217 svc_rdma_put_context(ctxt, 0);
@@ -225,7 +227,6 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
225{ 227{
226 u32 xfer_len = rqstp->rq_res.page_len + rqstp->rq_res.tail[0].iov_len; 228 u32 xfer_len = rqstp->rq_res.page_len + rqstp->rq_res.tail[0].iov_len;
227 int write_len; 229 int write_len;
228 int max_write;
229 u32 xdr_off; 230 u32 xdr_off;
230 int chunk_off; 231 int chunk_off;
231 int chunk_no; 232 int chunk_no;
@@ -239,8 +240,6 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
239 res_ary = (struct rpcrdma_write_array *) 240 res_ary = (struct rpcrdma_write_array *)
240 &rdma_resp->rm_body.rm_chunks[1]; 241 &rdma_resp->rm_body.rm_chunks[1];
241 242
242 max_write = xprt->sc_max_sge * PAGE_SIZE;
243
244 /* Write chunks start at the pagelist */ 243 /* Write chunks start at the pagelist */
245 for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0; 244 for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0;
246 xfer_len && chunk_no < arg_ary->wc_nchunks; 245 xfer_len && chunk_no < arg_ary->wc_nchunks;
@@ -260,23 +259,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
260 write_len); 259 write_len);
261 chunk_off = 0; 260 chunk_off = 0;
262 while (write_len) { 261 while (write_len) {
263 int this_write;
264 this_write = min(write_len, max_write);
265 ret = send_write(xprt, rqstp, 262 ret = send_write(xprt, rqstp,
266 ntohl(arg_ch->rs_handle), 263 ntohl(arg_ch->rs_handle),
267 rs_offset + chunk_off, 264 rs_offset + chunk_off,
268 xdr_off, 265 xdr_off,
269 this_write, 266 write_len,
270 vec); 267 vec);
271 if (ret) { 268 if (ret <= 0) {
272 dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", 269 dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n",
273 ret); 270 ret);
274 return -EIO; 271 return -EIO;
275 } 272 }
276 chunk_off += this_write; 273 chunk_off += ret;
277 xdr_off += this_write; 274 xdr_off += ret;
278 xfer_len -= this_write; 275 xfer_len -= ret;
279 write_len -= this_write; 276 write_len -= ret;
280 } 277 }
281 } 278 }
282 /* Update the req with the number of chunks actually used */ 279 /* Update the req with the number of chunks actually used */
@@ -293,7 +290,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
293{ 290{
294 u32 xfer_len = rqstp->rq_res.len; 291 u32 xfer_len = rqstp->rq_res.len;
295 int write_len; 292 int write_len;
296 int max_write;
297 u32 xdr_off; 293 u32 xdr_off;
298 int chunk_no; 294 int chunk_no;
299 int chunk_off; 295 int chunk_off;
@@ -311,8 +307,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
311 res_ary = (struct rpcrdma_write_array *) 307 res_ary = (struct rpcrdma_write_array *)
312 &rdma_resp->rm_body.rm_chunks[2]; 308 &rdma_resp->rm_body.rm_chunks[2];
313 309
314 max_write = xprt->sc_max_sge * PAGE_SIZE;
315
316 /* xdr offset starts at RPC message */ 310 /* xdr offset starts at RPC message */
317 nchunks = ntohl(arg_ary->wc_nchunks); 311 nchunks = ntohl(arg_ary->wc_nchunks);
318 for (xdr_off = 0, chunk_no = 0; 312 for (xdr_off = 0, chunk_no = 0;
@@ -330,24 +324,21 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
330 write_len); 324 write_len);
331 chunk_off = 0; 325 chunk_off = 0;
332 while (write_len) { 326 while (write_len) {
333 int this_write;
334
335 this_write = min(write_len, max_write);
336 ret = send_write(xprt, rqstp, 327 ret = send_write(xprt, rqstp,
337 ntohl(ch->rs_handle), 328 ntohl(ch->rs_handle),
338 rs_offset + chunk_off, 329 rs_offset + chunk_off,
339 xdr_off, 330 xdr_off,
340 this_write, 331 write_len,
341 vec); 332 vec);
342 if (ret) { 333 if (ret <= 0) {
343 dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", 334 dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n",
344 ret); 335 ret);
345 return -EIO; 336 return -EIO;
346 } 337 }
347 chunk_off += this_write; 338 chunk_off += ret;
348 xdr_off += this_write; 339 xdr_off += ret;
349 xfer_len -= this_write; 340 xfer_len -= ret;
350 write_len -= this_write; 341 write_len -= ret;
351 } 342 }
352 } 343 }
353 /* Update the req with the number of chunks actually used */ 344 /* Update the req with the number of chunks actually used */
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index e7323fbbd348..374feb44afea 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -92,6 +92,7 @@ struct svc_xprt_class svc_rdma_class = {
92 .xcl_owner = THIS_MODULE, 92 .xcl_owner = THIS_MODULE,
93 .xcl_ops = &svc_rdma_ops, 93 .xcl_ops = &svc_rdma_ops,
94 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, 94 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
95 .xcl_ident = XPRT_TRANSPORT_RDMA,
95}; 96};
96 97
97struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) 98struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
@@ -942,23 +943,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
942 943
943 ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, &qp_attr); 944 ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, &qp_attr);
944 if (ret) { 945 if (ret) {
945 /* 946 dprintk("svcrdma: failed to create QP, ret=%d\n", ret);
946 * XXX: This is a hack. We need a xx_request_qp interface 947 goto errout;
947 * that will adjust the qp_attr's with a best-effort
948 * number
949 */
950 qp_attr.cap.max_send_sge -= 2;
951 qp_attr.cap.max_recv_sge -= 2;
952 ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd,
953 &qp_attr);
954 if (ret) {
955 dprintk("svcrdma: failed to create QP, ret=%d\n", ret);
956 goto errout;
957 }
958 newxprt->sc_max_sge = qp_attr.cap.max_send_sge;
959 newxprt->sc_max_sge = qp_attr.cap.max_recv_sge;
960 newxprt->sc_sq_depth = qp_attr.cap.max_send_wr;
961 newxprt->sc_max_requests = qp_attr.cap.max_recv_wr;
962 } 948 }
963 newxprt->sc_qp = newxprt->sc_cm_id->qp; 949 newxprt->sc_qp = newxprt->sc_cm_id->qp;
964 950