aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-08 21:28:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-08 21:28:14 -0400
commit75ff24fa52f0cc512ceee4c377632b91a3a80811 (patch)
tree1b4a7a17c203221afb12027834c62679017655bb
parent0f386a7074aa758720a4fc1fa26123044849bcc6 (diff)
parent06f9cc12caa862f5bc86ebdb4f77568a4bef0167 (diff)
Merge branch 'for-3.15' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: "Highlights: - server-side nfs/rdma fixes from Jeff Layton and Tom Tucker - xdr fixes (a larger xdr rewrite has been posted but I decided it would be better to queue it up for 3.16). - miscellaneous fixes and cleanup from all over (thanks especially to Kinglong Mee)" * 'for-3.15' of git://linux-nfs.org/~bfields/linux: (36 commits) nfsd4: don't create unnecessary mask acl nfsd: revert v2 half of "nfsd: don't return high mode bits" nfsd4: fix memory leak in nfsd4_encode_fattr() nfsd: check passed socket's net matches NFSd superblock's one SUNRPC: Clear xpt_bc_xprt if xs_setup_bc_tcp failed NFSD/SUNRPC: Check rpc_xprt out of xs_setup_bc_tcp SUNRPC: New helper for creating client with rpc_xprt NFSD: Free backchannel xprt in bc_destroy NFSD: Clear wcc data between compound ops nfsd: Don't return NFS4ERR_STALE_STATEID for NFSv4.1+ nfsd4: fix nfs4err_resource in 4.1 case nfsd4: fix setclientid encode size nfsd4: remove redundant check from nfsd4_check_resp_size nfsd4: use more generous NFS4_ACL_MAX nfsd4: minor nfsd4_replay_cache_entry cleanup nfsd4: nfsd4_replay_cache_entry should be static nfsd4: update comments with obsolete function name rpc: Allow xdr_buf_subsegment to operate in-place NFSD: Using free_conn free connection SUNRPC: fix memory leak of peer addresses in XPRT ...
-rw-r--r--fs/lockd/svc.c1
-rw-r--r--fs/nfsd/acl.h10
-rw-r--r--fs/nfsd/nfs4acl.c13
-rw-r--r--fs/nfsd/nfs4callback.c19
-rw-r--r--fs/nfsd/nfs4proc.c39
-rw-r--r--fs/nfsd/nfs4state.c28
-rw-r--r--fs/nfsd/nfs4xdr.c30
-rw-r--r--fs/nfsd/nfsctl.c5
-rw-r--r--fs/nfsd/nfsd.h2
-rw-r--r--fs/nfsd/nfsfh.h14
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/vfs.c15
-rw-r--r--fs/nfsd/xdr4.h2
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/sunrpc/svcsock.h1
-rw-r--r--include/linux/sunrpc/xprt.h13
-rw-r--r--net/sunrpc/Kconfig39
-rw-r--r--net/sunrpc/Makefile3
-rw-r--r--net/sunrpc/clnt.c58
-rw-r--r--net/sunrpc/svcsock.c16
-rw-r--r--net/sunrpc/xdr.c22
-rw-r--r--net/sunrpc/xprt.c12
-rw-r--r--net/sunrpc/xprtrdma/Makefile4
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c12
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c3
-rw-r--r--net/sunrpc/xprtsock.c34
27 files changed, 264 insertions, 137 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 10d6c41aecad..6bf06a07f3e0 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -235,6 +235,7 @@ out_err:
235 if (warned++ == 0) 235 if (warned++ == 0)
236 printk(KERN_WARNING 236 printk(KERN_WARNING
237 "lockd_up: makesock failed, error=%d\n", err); 237 "lockd_up: makesock failed, error=%d\n", err);
238 svc_shutdown_net(serv, net);
238 return err; 239 return err;
239} 240}
240 241
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index a812fd1b92a4..b481e1f5eecc 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -39,9 +39,13 @@ struct nfs4_acl;
39struct svc_fh; 39struct svc_fh;
40struct svc_rqst; 40struct svc_rqst;
41 41
42/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to 42/*
43 * fit in a page: */ 43 * Maximum ACL we'll accept from a client; chosen (somewhat
44#define NFS4_ACL_MAX 170 44 * arbitrarily) so that kmalloc'ing the ACL shouldn't require a
45 * high-order allocation. This allows 204 ACEs on x86_64:
46 */
47#define NFS4_ACL_MAX ((PAGE_SIZE - sizeof(struct nfs4_acl)) \
48 / sizeof(struct nfs4_ace))
45 49
46struct nfs4_acl *nfs4_acl_new(int); 50struct nfs4_acl *nfs4_acl_new(int);
47int nfs4_acl_get_whotype(char *, u32); 51int nfs4_acl_get_whotype(char *, u32);
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index d190e33d0ec2..6f3f392d48af 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -542,7 +542,10 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
542 * up setting a 3-element effective posix ACL with all 542 * up setting a 3-element effective posix ACL with all
543 * permissions zero. 543 * permissions zero.
544 */ 544 */
545 nace = 4 + state->users->n + state->groups->n; 545 if (!state->users->n && !state->groups->n)
546 nace = 3;
547 else /* Note we also include a MASK ACE in this case: */
548 nace = 4 + state->users->n + state->groups->n;
546 pacl = posix_acl_alloc(nace, GFP_KERNEL); 549 pacl = posix_acl_alloc(nace, GFP_KERNEL);
547 if (!pacl) 550 if (!pacl)
548 return ERR_PTR(-ENOMEM); 551 return ERR_PTR(-ENOMEM);
@@ -586,9 +589,11 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
586 add_to_mask(state, &state->groups->aces[i].perms); 589 add_to_mask(state, &state->groups->aces[i].perms);
587 } 590 }
588 591
589 pace++; 592 if (!state->users->n && !state->groups->n) {
590 pace->e_tag = ACL_MASK; 593 pace++;
591 low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags); 594 pace->e_tag = ACL_MASK;
595 low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
596 }
592 597
593 pace++; 598 pace++;
594 pace->e_tag = ACL_OTHER; 599 pace->e_tag = ACL_OTHER;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 7f05cd140de3..39c8ef875f91 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -32,6 +32,7 @@
32 */ 32 */
33 33
34#include <linux/sunrpc/clnt.h> 34#include <linux/sunrpc/clnt.h>
35#include <linux/sunrpc/xprt.h>
35#include <linux/sunrpc/svc_xprt.h> 36#include <linux/sunrpc/svc_xprt.h>
36#include <linux/slab.h> 37#include <linux/slab.h>
37#include "nfsd.h" 38#include "nfsd.h"
@@ -635,6 +636,22 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
635 } 636 }
636} 637}
637 638
639static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
640{
641 struct rpc_xprt *xprt;
642
643 if (args->protocol != XPRT_TRANSPORT_BC_TCP)
644 return rpc_create(args);
645
646 xprt = args->bc_xprt->xpt_bc_xprt;
647 if (xprt) {
648 xprt_get(xprt);
649 return rpc_create_xprt(args, xprt);
650 }
651
652 return rpc_create(args);
653}
654
638static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) 655static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
639{ 656{
640 struct rpc_timeout timeparms = { 657 struct rpc_timeout timeparms = {
@@ -674,7 +691,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
674 args.authflavor = ses->se_cb_sec.flavor; 691 args.authflavor = ses->se_cb_sec.flavor;
675 } 692 }
676 /* Create RPC client */ 693 /* Create RPC client */
677 client = rpc_create(&args); 694 client = create_backchannel_client(&args);
678 if (IS_ERR(client)) { 695 if (IS_ERR(client)) {
679 dprintk("NFSD: couldn't create callback client: %ld\n", 696 dprintk("NFSD: couldn't create callback client: %ld\n",
680 PTR_ERR(client)); 697 PTR_ERR(client));
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 82189b208af3..d543222babf3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1273,6 +1273,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1273 struct nfsd4_op *op; 1273 struct nfsd4_op *op;
1274 struct nfsd4_operation *opdesc; 1274 struct nfsd4_operation *opdesc;
1275 struct nfsd4_compound_state *cstate = &resp->cstate; 1275 struct nfsd4_compound_state *cstate = &resp->cstate;
1276 struct svc_fh *current_fh = &cstate->current_fh;
1277 struct svc_fh *save_fh = &cstate->save_fh;
1276 int slack_bytes; 1278 int slack_bytes;
1277 u32 plen = 0; 1279 u32 plen = 0;
1278 __be32 status; 1280 __be32 status;
@@ -1288,11 +1290,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1288 resp->tag = args->tag; 1290 resp->tag = args->tag;
1289 resp->opcnt = 0; 1291 resp->opcnt = 0;
1290 resp->rqstp = rqstp; 1292 resp->rqstp = rqstp;
1291 resp->cstate.minorversion = args->minorversion; 1293 cstate->minorversion = args->minorversion;
1292 resp->cstate.replay_owner = NULL; 1294 cstate->replay_owner = NULL;
1293 resp->cstate.session = NULL; 1295 cstate->session = NULL;
1294 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); 1296 fh_init(current_fh, NFS4_FHSIZE);
1295 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); 1297 fh_init(save_fh, NFS4_FHSIZE);
1296 /* 1298 /*
1297 * Don't use the deferral mechanism for NFSv4; compounds make it 1299 * Don't use the deferral mechanism for NFSv4; compounds make it
1298 * too hard to avoid non-idempotency problems. 1300 * too hard to avoid non-idempotency problems.
@@ -1345,20 +1347,28 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1345 1347
1346 opdesc = OPDESC(op); 1348 opdesc = OPDESC(op);
1347 1349
1348 if (!cstate->current_fh.fh_dentry) { 1350 if (!current_fh->fh_dentry) {
1349 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { 1351 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
1350 op->status = nfserr_nofilehandle; 1352 op->status = nfserr_nofilehandle;
1351 goto encode_op; 1353 goto encode_op;
1352 } 1354 }
1353 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated && 1355 } else if (current_fh->fh_export->ex_fslocs.migrated &&
1354 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) { 1356 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
1355 op->status = nfserr_moved; 1357 op->status = nfserr_moved;
1356 goto encode_op; 1358 goto encode_op;
1357 } 1359 }
1358 1360
1361 fh_clear_wcc(current_fh);
1362
1359 /* If op is non-idempotent */ 1363 /* If op is non-idempotent */
1360 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { 1364 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) {
1361 plen = opdesc->op_rsize_bop(rqstp, op); 1365 plen = opdesc->op_rsize_bop(rqstp, op);
1366 /*
1367 * If there's still another operation, make sure
1368 * we'll have space to at least encode an error:
1369 */
1370 if (resp->opcnt < args->opcnt)
1371 plen += COMPOUND_ERR_SLACK_SPACE;
1362 op->status = nfsd4_check_resp_size(resp, plen); 1372 op->status = nfsd4_check_resp_size(resp, plen);
1363 } 1373 }
1364 1374
@@ -1377,12 +1387,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1377 clear_current_stateid(cstate); 1387 clear_current_stateid(cstate);
1378 1388
1379 if (need_wrongsec_check(rqstp)) 1389 if (need_wrongsec_check(rqstp))
1380 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); 1390 op->status = check_nfsd_access(current_fh->fh_export, rqstp);
1381 } 1391 }
1382 1392
1383encode_op: 1393encode_op:
1384 /* Only from SEQUENCE */ 1394 /* Only from SEQUENCE */
1385 if (resp->cstate.status == nfserr_replay_cache) { 1395 if (cstate->status == nfserr_replay_cache) {
1386 dprintk("%s NFS4.1 replay from cache\n", __func__); 1396 dprintk("%s NFS4.1 replay from cache\n", __func__);
1387 status = op->status; 1397 status = op->status;
1388 goto out; 1398 goto out;
@@ -1411,10 +1421,10 @@ encode_op:
1411 nfsd4_increment_op_stats(op->opnum); 1421 nfsd4_increment_op_stats(op->opnum);
1412 } 1422 }
1413 1423
1414 resp->cstate.status = status; 1424 cstate->status = status;
1415 fh_put(&resp->cstate.current_fh); 1425 fh_put(current_fh);
1416 fh_put(&resp->cstate.save_fh); 1426 fh_put(save_fh);
1417 BUG_ON(resp->cstate.replay_owner); 1427 BUG_ON(cstate->replay_owner);
1418out: 1428out:
1419 /* Reset deferral mechanism for RPC deferrals */ 1429 /* Reset deferral mechanism for RPC deferrals */
1420 rqstp->rq_usedeferral = 1; 1430 rqstp->rq_usedeferral = 1;
@@ -1523,7 +1533,8 @@ static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o
1523 1533
1524static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1534static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1525{ 1535{
1526 return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32); 1536 return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) *
1537 sizeof(__be32);
1527} 1538}
1528 1539
1529static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1540static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d5d070fbeb35..3ba65979a3cd 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1538,7 +1538,7 @@ out_err:
1538} 1538}
1539 1539
1540/* 1540/*
1541 * Cache a reply. nfsd4_check_drc_limit() has bounded the cache size. 1541 * Cache a reply. nfsd4_check_resp_size() has bounded the cache size.
1542 */ 1542 */
1543void 1543void
1544nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) 1544nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
@@ -1596,7 +1596,7 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
1596 * The sequence operation is not cached because we can use the slot and 1596 * The sequence operation is not cached because we can use the slot and
1597 * session values. 1597 * session values.
1598 */ 1598 */
1599__be32 1599static __be32
1600nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, 1600nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
1601 struct nfsd4_sequence *seq) 1601 struct nfsd4_sequence *seq)
1602{ 1602{
@@ -1605,9 +1605,8 @@ nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
1605 1605
1606 dprintk("--> %s slot %p\n", __func__, slot); 1606 dprintk("--> %s slot %p\n", __func__, slot);
1607 1607
1608 /* Either returns 0 or nfserr_retry_uncached */
1609 status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp); 1608 status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp);
1610 if (status == nfserr_retry_uncached_rep) 1609 if (status)
1611 return status; 1610 return status;
1612 1611
1613 /* The sequence operation has been encoded, cstate->datap set. */ 1612 /* The sequence operation has been encoded, cstate->datap set. */
@@ -2287,7 +2286,8 @@ out:
2287 if (!list_empty(&clp->cl_revoked)) 2286 if (!list_empty(&clp->cl_revoked))
2288 seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED; 2287 seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
2289out_no_session: 2288out_no_session:
2290 kfree(conn); 2289 if (conn)
2290 free_conn(conn);
2291 spin_unlock(&nn->client_lock); 2291 spin_unlock(&nn->client_lock);
2292 return status; 2292 return status;
2293out_put_session: 2293out_put_session:
@@ -3627,8 +3627,11 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
3627 return nfserr_bad_stateid; 3627 return nfserr_bad_stateid;
3628 status = lookup_clientid(&stateid->si_opaque.so_clid, sessions, 3628 status = lookup_clientid(&stateid->si_opaque.so_clid, sessions,
3629 nn, &cl); 3629 nn, &cl);
3630 if (status == nfserr_stale_clientid) 3630 if (status == nfserr_stale_clientid) {
3631 if (sessions)
3632 return nfserr_bad_stateid;
3631 return nfserr_stale_stateid; 3633 return nfserr_stale_stateid;
3634 }
3632 if (status) 3635 if (status)
3633 return status; 3636 return status;
3634 *s = find_stateid_by_type(cl, stateid, typemask); 3637 *s = find_stateid_by_type(cl, stateid, typemask);
@@ -5062,7 +5065,6 @@ nfs4_state_destroy_net(struct net *net)
5062 int i; 5065 int i;
5063 struct nfs4_client *clp = NULL; 5066 struct nfs4_client *clp = NULL;
5064 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 5067 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
5065 struct rb_node *node, *tmp;
5066 5068
5067 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 5069 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
5068 while (!list_empty(&nn->conf_id_hashtbl[i])) { 5070 while (!list_empty(&nn->conf_id_hashtbl[i])) {
@@ -5071,13 +5073,11 @@ nfs4_state_destroy_net(struct net *net)
5071 } 5073 }
5072 } 5074 }
5073 5075
5074 node = rb_first(&nn->unconf_name_tree); 5076 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
5075 while (node != NULL) { 5077 while (!list_empty(&nn->unconf_id_hashtbl[i])) {
5076 tmp = node; 5078 clp = list_entry(nn->unconf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
5077 node = rb_next(tmp); 5079 destroy_client(clp);
5078 clp = rb_entry(tmp, struct nfs4_client, cl_namenode); 5080 }
5079 rb_erase(tmp, &nn->unconf_name_tree);
5080 destroy_client(clp);
5081 } 5081 }
5082 5082
5083 kfree(nn->sessionid_hashtbl); 5083 kfree(nn->sessionid_hashtbl);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 63f2395c57ed..2723c1badd01 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -294,7 +294,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
294 READ32(nace); 294 READ32(nace);
295 295
296 if (nace > NFS4_ACL_MAX) 296 if (nace > NFS4_ACL_MAX)
297 return nfserr_resource; 297 return nfserr_fbig;
298 298
299 *acl = nfs4_acl_new(nace); 299 *acl = nfs4_acl_new(nace);
300 if (*acl == NULL) 300 if (*acl == NULL)
@@ -1222,7 +1222,6 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1222 } 1222 }
1223 write->wr_head.iov_base = p; 1223 write->wr_head.iov_base = p;
1224 write->wr_head.iov_len = avail; 1224 write->wr_head.iov_len = avail;
1225 WARN_ON(avail != (XDR_QUADLEN(avail) << 2));
1226 write->wr_pagelist = argp->pagelist; 1225 write->wr_pagelist = argp->pagelist;
1227 1226
1228 len = XDR_QUADLEN(write->wr_buflen) << 2; 1227 len = XDR_QUADLEN(write->wr_buflen) << 2;
@@ -2483,6 +2482,8 @@ out_acl:
2483 goto out; 2482 goto out;
2484 } 2483 }
2485 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2484 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2485 if ((buflen -= 16) < 0)
2486 goto out_resource;
2486 WRITE32(3); 2487 WRITE32(3);
2487 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2488 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
2488 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); 2489 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
@@ -2499,8 +2500,10 @@ out:
2499 security_release_secctx(context, contextlen); 2500 security_release_secctx(context, contextlen);
2500#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ 2501#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2501 kfree(acl); 2502 kfree(acl);
2502 if (tempfh) 2503 if (tempfh) {
2503 fh_put(tempfh); 2504 fh_put(tempfh);
2505 kfree(tempfh);
2506 }
2504 return status; 2507 return status;
2505out_nfserr: 2508out_nfserr:
2506 status = nfserrno(err); 2509 status = nfserrno(err);
@@ -3471,6 +3474,9 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
3471 struct nfsd4_test_stateid_id *stateid, *next; 3474 struct nfsd4_test_stateid_id *stateid, *next;
3472 __be32 *p; 3475 __be32 *p;
3473 3476
3477 if (nfserr)
3478 return nfserr;
3479
3474 RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); 3480 RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids));
3475 *p++ = htonl(test_stateid->ts_num_ids); 3481 *p++ = htonl(test_stateid->ts_num_ids);
3476 3482
@@ -3579,8 +3585,6 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
3579 return 0; 3585 return 0;
3580 3586
3581 session = resp->cstate.session; 3587 session = resp->cstate.session;
3582 if (session == NULL)
3583 return 0;
3584 3588
3585 if (xb->page_len == 0) { 3589 if (xb->page_len == 0) {
3586 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; 3590 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
@@ -3620,9 +3624,17 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3620 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || 3624 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
3621 !nfsd4_enc_ops[op->opnum]); 3625 !nfsd4_enc_ops[op->opnum]);
3622 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); 3626 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
3623 /* nfsd4_check_drc_limit guarantees enough room for error status */ 3627 /* nfsd4_check_resp_size guarantees enough room for error status */
3624 if (!op->status) 3628 if (!op->status)
3625 op->status = nfsd4_check_resp_size(resp, 0); 3629 op->status = nfsd4_check_resp_size(resp, 0);
3630 if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) {
3631 struct nfsd4_slot *slot = resp->cstate.slot;
3632
3633 if (slot->sl_flags & NFSD4_SLOT_CACHETHIS)
3634 op->status = nfserr_rep_too_big_to_cache;
3635 else
3636 op->status = nfserr_rep_too_big;
3637 }
3626 if (so) { 3638 if (so) {
3627 so->so_replay.rp_status = op->status; 3639 so->so_replay.rp_status = op->status;
3628 so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); 3640 so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1);
@@ -3691,6 +3703,12 @@ int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
3691int 3703int
3692nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) 3704nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
3693{ 3705{
3706 if (rqstp->rq_arg.head[0].iov_len % 4) {
3707 /* client is nuts */
3708 dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)",
3709 __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid));
3710 return 0;
3711 }
3694 args->p = p; 3712 args->p = p;
3695 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; 3713 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
3696 args->pagelist = rqstp->rq_arg.pages; 3714 args->pagelist = rqstp->rq_arg.pages;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 7f555179bf81..f34d9de802ab 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -699,6 +699,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net)
699 if (err != 0 || fd < 0) 699 if (err != 0 || fd < 0)
700 return -EINVAL; 700 return -EINVAL;
701 701
702 if (svc_alien_sock(net, fd)) {
703 printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
704 return -EINVAL;
705 }
706
702 err = nfsd_create_serv(net); 707 err = nfsd_create_serv(net);
703 if (err != 0) 708 if (err != 0)
704 return err; 709 return err;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 30f34ab02137..479eb681c27c 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -282,7 +282,7 @@ void nfsd_lockd_shutdown(void);
282 * reason. 282 * reason.
283 */ 283 */
284#define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ 284#define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */
285#define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ 285#define COMPOUND_ERR_SLACK_SPACE 16 /* OP_SETATTR */
286 286
287#define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */ 287#define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */
288 288
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index 4775bc4896c8..ad67964d0bb1 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -133,6 +133,17 @@ fh_init(struct svc_fh *fhp, int maxsize)
133 133
134#ifdef CONFIG_NFSD_V3 134#ifdef CONFIG_NFSD_V3
135/* 135/*
136 * The wcc data stored in current_fh should be cleared
137 * between compound ops.
138 */
139static inline void
140fh_clear_wcc(struct svc_fh *fhp)
141{
142 fhp->fh_post_saved = 0;
143 fhp->fh_pre_saved = 0;
144}
145
146/*
136 * Fill in the pre_op attr for the wcc data 147 * Fill in the pre_op attr for the wcc data
137 */ 148 */
138static inline void 149static inline void
@@ -152,7 +163,8 @@ fill_pre_wcc(struct svc_fh *fhp)
152 163
153extern void fill_post_wcc(struct svc_fh *); 164extern void fill_post_wcc(struct svc_fh *);
154#else 165#else
155#define fill_pre_wcc(ignored) 166#define fh_clear_wcc(ignored)
167#define fill_pre_wcc(ignored)
156#define fill_post_wcc(notused) 168#define fill_post_wcc(notused)
157#endif /* CONFIG_NFSD_V3 */ 169#endif /* CONFIG_NFSD_V3 */
158 170
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index b17d93214d01..9c769a47ac5a 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
152 type = (stat->mode & S_IFMT); 152 type = (stat->mode & S_IFMT);
153 153
154 *p++ = htonl(nfs_ftypes[type >> 12]); 154 *p++ = htonl(nfs_ftypes[type >> 12]);
155 *p++ = htonl((u32) (stat->mode & S_IALLUGO)); 155 *p++ = htonl((u32) stat->mode);
156 *p++ = htonl((u32) stat->nlink); 156 *p++ = htonl((u32) stat->nlink);
157 *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); 157 *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
158 *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); 158 *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 915808b36df7..16f0673a423c 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -404,6 +404,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
404 umode_t ftype = 0; 404 umode_t ftype = 0;
405 __be32 err; 405 __be32 err;
406 int host_err; 406 int host_err;
407 bool get_write_count;
407 int size_change = 0; 408 int size_change = 0;
408 409
409 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) 410 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
@@ -411,10 +412,18 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
411 if (iap->ia_valid & ATTR_SIZE) 412 if (iap->ia_valid & ATTR_SIZE)
412 ftype = S_IFREG; 413 ftype = S_IFREG;
413 414
415 /* Callers that do fh_verify should do the fh_want_write: */
416 get_write_count = !fhp->fh_dentry;
417
414 /* Get inode */ 418 /* Get inode */
415 err = fh_verify(rqstp, fhp, ftype, accmode); 419 err = fh_verify(rqstp, fhp, ftype, accmode);
416 if (err) 420 if (err)
417 goto out; 421 goto out;
422 if (get_write_count) {
423 host_err = fh_want_write(fhp);
424 if (host_err)
425 return nfserrno(host_err);
426 }
418 427
419 dentry = fhp->fh_dentry; 428 dentry = fhp->fh_dentry;
420 inode = dentry->d_inode; 429 inode = dentry->d_inode;
@@ -1706,10 +1715,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1706 dput(odentry); 1715 dput(odentry);
1707 out_nfserr: 1716 out_nfserr:
1708 err = nfserrno(host_err); 1717 err = nfserrno(host_err);
1709 1718 /*
1710 /* we cannot reply on fh_unlock on the two filehandles, 1719 * We cannot rely on fh_unlock on the two filehandles,
1711 * as that would do the wrong thing if the two directories 1720 * as that would do the wrong thing if the two directories
1712 * were the same, so again we do it by hand 1721 * were the same, so again we do it by hand.
1713 */ 1722 */
1714 fill_post_wcc(ffhp); 1723 fill_post_wcc(ffhp);
1715 fill_post_wcc(tfhp); 1724 fill_post_wcc(tfhp);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index d278a0d03496..5ea7df305083 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -574,8 +574,6 @@ extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
574 struct nfsd4_compound_state *, 574 struct nfsd4_compound_state *,
575 struct nfsd4_setclientid_confirm *setclientid_confirm); 575 struct nfsd4_setclientid_confirm *setclientid_confirm);
576extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); 576extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp);
577extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
578 struct nfsd4_sequence *seq);
579extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, 577extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
580 struct nfsd4_compound_state *, struct nfsd4_exchange_id *); 578 struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
581extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *); 579extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 8af2804bab16..70736b98c721 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -130,6 +130,8 @@ struct rpc_create_args {
130#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9) 130#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
131 131
132struct rpc_clnt *rpc_create(struct rpc_create_args *args); 132struct rpc_clnt *rpc_create(struct rpc_create_args *args);
133struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
134 struct rpc_xprt *xprt);
133struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, 135struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
134 const struct rpc_program *, u32); 136 const struct rpc_program *, u32);
135void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt); 137void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 62fd1b756e99..947009ed5996 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -56,6 +56,7 @@ int svc_recv(struct svc_rqst *, long);
56int svc_send(struct svc_rqst *); 56int svc_send(struct svc_rqst *);
57void svc_drop(struct svc_rqst *); 57void svc_drop(struct svc_rqst *);
58void svc_sock_update_bufs(struct svc_serv *serv); 58void svc_sock_update_bufs(struct svc_serv *serv);
59bool svc_alien_sock(struct net *net, int fd);
59int svc_addsock(struct svc_serv *serv, const int fd, 60int svc_addsock(struct svc_serv *serv, const int fd,
60 char *name_return, const size_t len); 61 char *name_return, const size_t len);
61void svc_init_xprt_sock(void); 62void svc_init_xprt_sock(void);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 8097b9df6773..3e5efb2b236e 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -295,13 +295,24 @@ int xprt_adjust_timeout(struct rpc_rqst *req);
295void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); 295void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
296void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); 296void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
297void xprt_release(struct rpc_task *task); 297void xprt_release(struct rpc_task *task);
298struct rpc_xprt * xprt_get(struct rpc_xprt *xprt);
299void xprt_put(struct rpc_xprt *xprt); 298void xprt_put(struct rpc_xprt *xprt);
300struct rpc_xprt * xprt_alloc(struct net *net, size_t size, 299struct rpc_xprt * xprt_alloc(struct net *net, size_t size,
301 unsigned int num_prealloc, 300 unsigned int num_prealloc,
302 unsigned int max_req); 301 unsigned int max_req);
303void xprt_free(struct rpc_xprt *); 302void xprt_free(struct rpc_xprt *);
304 303
304/**
305 * xprt_get - return a reference to an RPC transport.
306 * @xprt: pointer to the transport
307 *
308 */
309static inline struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
310{
311 if (atomic_inc_not_zero(&xprt->count))
312 return xprt;
313 return NULL;
314}
315
305static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p) 316static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
306{ 317{
307 return p + xprt->tsh_size; 318 return p + xprt->tsh_size;
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 241b54f30204..0754d0f466d2 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -9,19 +9,6 @@ config SUNRPC_BACKCHANNEL
9 bool 9 bool
10 depends on SUNRPC 10 depends on SUNRPC
11 11
12config SUNRPC_XPRT_RDMA
13 tristate
14 depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS
15 default SUNRPC && INFINIBAND
16 help
17 This option allows the NFS client and server to support
18 an RDMA-enabled transport.
19
20 To compile RPC client RDMA transport support as a module,
21 choose M here: the module will be called xprtrdma.
22
23 If unsure, say N.
24
25config SUNRPC_SWAP 12config SUNRPC_SWAP
26 bool 13 bool
27 depends on SUNRPC 14 depends on SUNRPC
@@ -57,3 +44,29 @@ config SUNRPC_DEBUG
57 but makes troubleshooting NFS issues significantly harder. 44 but makes troubleshooting NFS issues significantly harder.
58 45
59 If unsure, say Y. 46 If unsure, say Y.
47
48config SUNRPC_XPRT_RDMA_CLIENT
49 tristate "RPC over RDMA Client Support"
50 depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS
51 default SUNRPC && INFINIBAND
52 help
53 This option allows the NFS client to support an RDMA-enabled
54 transport.
55
56 To compile RPC client RDMA transport support as a module,
57 choose M here: the module will be called xprtrdma.
58
59 If unsure, say N.
60
61config SUNRPC_XPRT_RDMA_SERVER
62 tristate "RPC over RDMA Server Support"
63 depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS
64 default SUNRPC && INFINIBAND
65 help
66 This option allows the NFS server to support an RDMA-enabled
67 transport.
68
69 To compile RPC server RDMA transport support as a module,
70 choose M here: the module will be called svcrdma.
71
72 If unsure, say N.
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 8209a0411bca..e5a7a1cac8f3 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -5,7 +5,8 @@
5 5
6obj-$(CONFIG_SUNRPC) += sunrpc.o 6obj-$(CONFIG_SUNRPC) += sunrpc.o
7obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ 7obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
8obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/ 8
9obj-y += xprtrdma/
9 10
10sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ 11sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
11 auth.o auth_null.o auth_unix.o auth_generic.o \ 12 auth.o auth_null.o auth_unix.o auth_generic.o \
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f400445d1a44..2e6ab10734f6 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -438,6 +438,38 @@ out_no_rpciod:
438 return ERR_PTR(err); 438 return ERR_PTR(err);
439} 439}
440 440
441struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
442 struct rpc_xprt *xprt)
443{
444 struct rpc_clnt *clnt = NULL;
445
446 clnt = rpc_new_client(args, xprt, NULL);
447 if (IS_ERR(clnt))
448 return clnt;
449
450 if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
451 int err = rpc_ping(clnt);
452 if (err != 0) {
453 rpc_shutdown_client(clnt);
454 return ERR_PTR(err);
455 }
456 }
457
458 clnt->cl_softrtry = 1;
459 if (args->flags & RPC_CLNT_CREATE_HARDRTRY)
460 clnt->cl_softrtry = 0;
461
462 if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
463 clnt->cl_autobind = 1;
464 if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
465 clnt->cl_discrtry = 1;
466 if (!(args->flags & RPC_CLNT_CREATE_QUIET))
467 clnt->cl_chatty = 1;
468
469 return clnt;
470}
471EXPORT_SYMBOL_GPL(rpc_create_xprt);
472
441/** 473/**
442 * rpc_create - create an RPC client and transport with one call 474 * rpc_create - create an RPC client and transport with one call
443 * @args: rpc_clnt create argument structure 475 * @args: rpc_clnt create argument structure
@@ -451,7 +483,6 @@ out_no_rpciod:
451struct rpc_clnt *rpc_create(struct rpc_create_args *args) 483struct rpc_clnt *rpc_create(struct rpc_create_args *args)
452{ 484{
453 struct rpc_xprt *xprt; 485 struct rpc_xprt *xprt;
454 struct rpc_clnt *clnt;
455 struct xprt_create xprtargs = { 486 struct xprt_create xprtargs = {
456 .net = args->net, 487 .net = args->net,
457 .ident = args->protocol, 488 .ident = args->protocol,
@@ -515,30 +546,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
515 if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) 546 if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
516 xprt->resvport = 0; 547 xprt->resvport = 0;
517 548
518 clnt = rpc_new_client(args, xprt, NULL); 549 return rpc_create_xprt(args, xprt);
519 if (IS_ERR(clnt))
520 return clnt;
521
522 if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
523 int err = rpc_ping(clnt);
524 if (err != 0) {
525 rpc_shutdown_client(clnt);
526 return ERR_PTR(err);
527 }
528 }
529
530 clnt->cl_softrtry = 1;
531 if (args->flags & RPC_CLNT_CREATE_HARDRTRY)
532 clnt->cl_softrtry = 0;
533
534 if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
535 clnt->cl_autobind = 1;
536 if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
537 clnt->cl_discrtry = 1;
538 if (!(args->flags & RPC_CLNT_CREATE_QUIET))
539 clnt->cl_chatty = 1;
540
541 return clnt;
542} 550}
543EXPORT_SYMBOL_GPL(rpc_create); 551EXPORT_SYMBOL_GPL(rpc_create);
544 552
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index b6e59f0a9475..d06cb8752dcd 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1397,6 +1397,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
1397 return svsk; 1397 return svsk;
1398} 1398}
1399 1399
1400bool svc_alien_sock(struct net *net, int fd)
1401{
1402 int err;
1403 struct socket *sock = sockfd_lookup(fd, &err);
1404 bool ret = false;
1405
1406 if (!sock)
1407 goto out;
1408 if (sock_net(sock->sk) != net)
1409 ret = true;
1410 sockfd_put(sock);
1411out:
1412 return ret;
1413}
1414EXPORT_SYMBOL_GPL(svc_alien_sock);
1415
1400/** 1416/**
1401 * svc_addsock - add a listener socket to an RPC service 1417 * svc_addsock - add a listener socket to an RPC service
1402 * @serv: pointer to RPC service to which to add a new listener 1418 * @serv: pointer to RPC service to which to add a new listener
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 1504bb11e4f3..dd97ba3c4456 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -833,8 +833,20 @@ xdr_buf_from_iov(struct kvec *iov, struct xdr_buf *buf)
833} 833}
834EXPORT_SYMBOL_GPL(xdr_buf_from_iov); 834EXPORT_SYMBOL_GPL(xdr_buf_from_iov);
835 835
836/* Sets subbuf to the portion of buf of length len beginning base bytes 836/**
837 * from the start of buf. Returns -1 if base of length are out of bounds. */ 837 * xdr_buf_subsegment - set subbuf to a portion of buf
838 * @buf: an xdr buffer
839 * @subbuf: the result buffer
840 * @base: beginning of range in bytes
841 * @len: length of range in bytes
842 *
843 * sets @subbuf to an xdr buffer representing the portion of @buf of
844 * length @len starting at offset @base.
845 *
846 * @buf and @subbuf may be pointers to the same struct xdr_buf.
847 *
848 * Returns -1 if base of length are out of bounds.
849 */
838int 850int
839xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, 851xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
840 unsigned int base, unsigned int len) 852 unsigned int base, unsigned int len)
@@ -847,9 +859,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
847 len -= subbuf->head[0].iov_len; 859 len -= subbuf->head[0].iov_len;
848 base = 0; 860 base = 0;
849 } else { 861 } else {
850 subbuf->head[0].iov_base = NULL;
851 subbuf->head[0].iov_len = 0;
852 base -= buf->head[0].iov_len; 862 base -= buf->head[0].iov_len;
863 subbuf->head[0].iov_len = 0;
853 } 864 }
854 865
855 if (base < buf->page_len) { 866 if (base < buf->page_len) {
@@ -871,9 +882,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
871 len -= subbuf->tail[0].iov_len; 882 len -= subbuf->tail[0].iov_len;
872 base = 0; 883 base = 0;
873 } else { 884 } else {
874 subbuf->tail[0].iov_base = NULL;
875 subbuf->tail[0].iov_len = 0;
876 base -= buf->tail[0].iov_len; 885 base -= buf->tail[0].iov_len;
886 subbuf->tail[0].iov_len = 0;
877 } 887 }
878 888
879 if (base || len) 889 if (base || len)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 7d4df99f761f..d173f79947c6 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1383,15 +1383,3 @@ void xprt_put(struct rpc_xprt *xprt)
1383 if (atomic_dec_and_test(&xprt->count)) 1383 if (atomic_dec_and_test(&xprt->count))
1384 xprt_destroy(xprt); 1384 xprt_destroy(xprt);
1385} 1385}
1386
1387/**
1388 * xprt_get - return a reference to an RPC transport.
1389 * @xprt: pointer to the transport
1390 *
1391 */
1392struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
1393{
1394 if (atomic_inc_not_zero(&xprt->count))
1395 return xprt;
1396 return NULL;
1397}
diff --git a/net/sunrpc/xprtrdma/Makefile b/net/sunrpc/xprtrdma/Makefile
index 5a8f268bdd30..da5136fd5694 100644
--- a/net/sunrpc/xprtrdma/Makefile
+++ b/net/sunrpc/xprtrdma/Makefile
@@ -1,8 +1,8 @@
1obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma.o 1obj-$(CONFIG_SUNRPC_XPRT_RDMA_CLIENT) += xprtrdma.o
2 2
3xprtrdma-y := transport.o rpc_rdma.o verbs.o 3xprtrdma-y := transport.o rpc_rdma.o verbs.o
4 4
5obj-$(CONFIG_SUNRPC_XPRT_RDMA) += svcrdma.o 5obj-$(CONFIG_SUNRPC_XPRT_RDMA_SERVER) += svcrdma.o
6 6
7svcrdma-y := svc_rdma.o svc_rdma_transport.o \ 7svcrdma-y := svc_rdma.o svc_rdma_transport.o \
8 svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o 8 svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 0ce75524ed21..8d904e4eef15 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -90,6 +90,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp,
90 sge_no++; 90 sge_no++;
91 } 91 }
92 rqstp->rq_respages = &rqstp->rq_pages[sge_no]; 92 rqstp->rq_respages = &rqstp->rq_pages[sge_no];
93 rqstp->rq_next_page = rqstp->rq_respages + 1;
93 94
94 /* We should never run out of SGE because the limit is defined to 95 /* We should never run out of SGE because the limit is defined to
95 * support the max allowed RPC data length 96 * support the max allowed RPC data length
@@ -169,6 +170,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt,
169 */ 170 */
170 head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no]; 171 head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no];
171 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no+1]; 172 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no+1];
173 rqstp->rq_next_page = rqstp->rq_respages + 1;
172 174
173 byte_count -= sge_bytes; 175 byte_count -= sge_bytes;
174 ch_bytes -= sge_bytes; 176 ch_bytes -= sge_bytes;
@@ -276,6 +278,7 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
276 278
277 /* rq_respages points one past arg pages */ 279 /* rq_respages points one past arg pages */
278 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; 280 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
281 rqstp->rq_next_page = rqstp->rq_respages + 1;
279 282
280 /* Create the reply and chunk maps */ 283 /* Create the reply and chunk maps */
281 offset = 0; 284 offset = 0;
@@ -520,13 +523,6 @@ next_sge:
520 for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) 523 for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++)
521 rqstp->rq_pages[ch_no] = NULL; 524 rqstp->rq_pages[ch_no] = NULL;
522 525
523 /*
524 * Detach res pages. If svc_release sees any it will attempt to
525 * put them.
526 */
527 while (rqstp->rq_next_page != rqstp->rq_respages)
528 *(--rqstp->rq_next_page) = NULL;
529
530 return err; 526 return err;
531} 527}
532 528
@@ -550,7 +546,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
550 546
551 /* rq_respages starts after the last arg page */ 547 /* rq_respages starts after the last arg page */
552 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; 548 rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
553 rqstp->rq_next_page = &rqstp->rq_arg.pages[page_no]; 549 rqstp->rq_next_page = rqstp->rq_respages + 1;
554 550
555 /* Rebuild rq_arg head and tail. */ 551 /* Rebuild rq_arg head and tail. */
556 rqstp->rq_arg.head[0] = head->arg.head[0]; 552 rqstp->rq_arg.head[0] = head->arg.head[0];
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index c1d124dc772b..7e024a51617e 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -265,6 +265,7 @@ static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt,
265 xdr_off -= xdr->head[0].iov_len; 265 xdr_off -= xdr->head[0].iov_len;
266 if (xdr_off < xdr->page_len) { 266 if (xdr_off < xdr->page_len) {
267 /* This offset is in the page list */ 267 /* This offset is in the page list */
268 xdr_off += xdr->page_base;
268 page = xdr->pages[xdr_off >> PAGE_SHIFT]; 269 page = xdr->pages[xdr_off >> PAGE_SHIFT];
269 xdr_off &= ~PAGE_MASK; 270 xdr_off &= ~PAGE_MASK;
270 } else { 271 } else {
@@ -625,6 +626,7 @@ static int send_reply(struct svcxprt_rdma *rdma,
625 if (page_no+1 >= sge_no) 626 if (page_no+1 >= sge_no)
626 ctxt->sge[page_no+1].length = 0; 627 ctxt->sge[page_no+1].length = 0;
627 } 628 }
629 rqstp->rq_next_page = rqstp->rq_respages + 1;
628 BUG_ON(sge_no > rdma->sc_max_sge); 630 BUG_ON(sge_no > rdma->sc_max_sge);
629 memset(&send_wr, 0, sizeof send_wr); 631 memset(&send_wr, 0, sizeof send_wr);
630 ctxt->wr_op = IB_WR_SEND; 632 ctxt->wr_op = IB_WR_SEND;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 62e4f9bcc387..25688fa2207f 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -477,8 +477,7 @@ struct page *svc_rdma_get_page(void)
477 477
478 while ((page = alloc_page(GFP_KERNEL)) == NULL) { 478 while ((page = alloc_page(GFP_KERNEL)) == NULL) {
479 /* If we can't get memory, wait a bit and try again */ 479 /* If we can't get memory, wait a bit and try again */
480 printk(KERN_INFO "svcrdma: out of memory...retrying in 1000 " 480 printk(KERN_INFO "svcrdma: out of memory...retrying in 1s\n");
481 "jiffies.\n");
482 schedule_timeout_uninterruptible(msecs_to_jiffies(1000)); 481 schedule_timeout_uninterruptible(msecs_to_jiffies(1000));
483 } 482 }
484 return page; 483 return page;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 966763d735e9..6735e1d1e9bb 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -909,6 +909,12 @@ static void xs_tcp_close(struct rpc_xprt *xprt)
909 xs_tcp_shutdown(xprt); 909 xs_tcp_shutdown(xprt);
910} 910}
911 911
912static void xs_xprt_free(struct rpc_xprt *xprt)
913{
914 xs_free_peer_addresses(xprt);
915 xprt_free(xprt);
916}
917
912/** 918/**
913 * xs_destroy - prepare to shutdown a transport 919 * xs_destroy - prepare to shutdown a transport
914 * @xprt: doomed transport 920 * @xprt: doomed transport
@@ -919,8 +925,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
919 dprintk("RPC: xs_destroy xprt %p\n", xprt); 925 dprintk("RPC: xs_destroy xprt %p\n", xprt);
920 926
921 xs_close(xprt); 927 xs_close(xprt);
922 xs_free_peer_addresses(xprt); 928 xs_xprt_free(xprt);
923 xprt_free(xprt);
924 module_put(THIS_MODULE); 929 module_put(THIS_MODULE);
925} 930}
926 931
@@ -2532,6 +2537,10 @@ static void bc_close(struct rpc_xprt *xprt)
2532 2537
2533static void bc_destroy(struct rpc_xprt *xprt) 2538static void bc_destroy(struct rpc_xprt *xprt)
2534{ 2539{
2540 dprintk("RPC: bc_destroy xprt %p\n", xprt);
2541
2542 xs_xprt_free(xprt);
2543 module_put(THIS_MODULE);
2535} 2544}
2536 2545
2537static struct rpc_xprt_ops xs_local_ops = { 2546static struct rpc_xprt_ops xs_local_ops = {
@@ -2732,7 +2741,7 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
2732 return xprt; 2741 return xprt;
2733 ret = ERR_PTR(-EINVAL); 2742 ret = ERR_PTR(-EINVAL);
2734out_err: 2743out_err:
2735 xprt_free(xprt); 2744 xs_xprt_free(xprt);
2736 return ret; 2745 return ret;
2737} 2746}
2738 2747
@@ -2810,7 +2819,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
2810 return xprt; 2819 return xprt;
2811 ret = ERR_PTR(-EINVAL); 2820 ret = ERR_PTR(-EINVAL);
2812out_err: 2821out_err:
2813 xprt_free(xprt); 2822 xs_xprt_free(xprt);
2814 return ret; 2823 return ret;
2815} 2824}
2816 2825
@@ -2885,12 +2894,11 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
2885 xprt->address_strings[RPC_DISPLAY_ADDR], 2894 xprt->address_strings[RPC_DISPLAY_ADDR],
2886 xprt->address_strings[RPC_DISPLAY_PROTO]); 2895 xprt->address_strings[RPC_DISPLAY_PROTO]);
2887 2896
2888
2889 if (try_module_get(THIS_MODULE)) 2897 if (try_module_get(THIS_MODULE))
2890 return xprt; 2898 return xprt;
2891 ret = ERR_PTR(-EINVAL); 2899 ret = ERR_PTR(-EINVAL);
2892out_err: 2900out_err:
2893 xprt_free(xprt); 2901 xs_xprt_free(xprt);
2894 return ret; 2902 return ret;
2895} 2903}
2896 2904
@@ -2907,15 +2915,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
2907 struct svc_sock *bc_sock; 2915 struct svc_sock *bc_sock;
2908 struct rpc_xprt *ret; 2916 struct rpc_xprt *ret;
2909 2917
2910 if (args->bc_xprt->xpt_bc_xprt) {
2911 /*
2912 * This server connection already has a backchannel
2913 * transport; we can't create a new one, as we wouldn't
2914 * be able to match replies based on xid any more. So,
2915 * reuse the already-existing one:
2916 */
2917 return args->bc_xprt->xpt_bc_xprt;
2918 }
2919 xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries, 2918 xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
2920 xprt_tcp_slot_table_entries); 2919 xprt_tcp_slot_table_entries);
2921 if (IS_ERR(xprt)) 2920 if (IS_ERR(xprt))
@@ -2973,13 +2972,14 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
2973 */ 2972 */
2974 xprt_set_connected(xprt); 2973 xprt_set_connected(xprt);
2975 2974
2976
2977 if (try_module_get(THIS_MODULE)) 2975 if (try_module_get(THIS_MODULE))
2978 return xprt; 2976 return xprt;
2977
2978 args->bc_xprt->xpt_bc_xprt = NULL;
2979 xprt_put(xprt); 2979 xprt_put(xprt);
2980 ret = ERR_PTR(-EINVAL); 2980 ret = ERR_PTR(-EINVAL);
2981out_err: 2981out_err:
2982 xprt_free(xprt); 2982 xs_xprt_free(xprt);
2983 return ret; 2983 return ret;
2984} 2984}
2985 2985