diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 21:28:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 21:28:14 -0400 |
commit | 75ff24fa52f0cc512ceee4c377632b91a3a80811 (patch) | |
tree | 1b4a7a17c203221afb12027834c62679017655bb | |
parent | 0f386a7074aa758720a4fc1fa26123044849bcc6 (diff) | |
parent | 06f9cc12caa862f5bc86ebdb4f77568a4bef0167 (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.c | 1 | ||||
-rw-r--r-- | fs/nfsd/acl.h | 10 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 13 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 19 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 39 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 28 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 30 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 5 | ||||
-rw-r--r-- | fs/nfsd/nfsd.h | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.h | 14 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 15 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/clnt.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/svcsock.h | 1 | ||||
-rw-r--r-- | include/linux/sunrpc/xprt.h | 13 | ||||
-rw-r--r-- | net/sunrpc/Kconfig | 39 | ||||
-rw-r--r-- | net/sunrpc/Makefile | 3 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 58 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 16 | ||||
-rw-r--r-- | net/sunrpc/xdr.c | 22 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 12 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/Makefile | 4 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 12 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_sendto.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 34 |
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; | |||
39 | struct svc_fh; | 39 | struct svc_fh; |
40 | struct svc_rqst; | 40 | struct 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 | ||
46 | struct nfs4_acl *nfs4_acl_new(int); | 50 | struct nfs4_acl *nfs4_acl_new(int); |
47 | int nfs4_acl_get_whotype(char *, u32); | 51 | int 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 | ||
639 | static 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 | |||
638 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) | 655 | static 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 | ||
1383 | encode_op: | 1393 | encode_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); |
1418 | out: | 1428 | out: |
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 | ||
1524 | static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1534 | static 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 | ||
1529 | static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1540 | static 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 | */ |
1543 | void | 1543 | void |
1544 | nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) | 1544 | nfsd4_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 | 1599 | static __be32 |
1600 | nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | 1600 | nfsd4_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; |
2289 | out_no_session: | 2288 | out_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; |
2293 | out_put_session: | 2293 | out_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; |
2505 | out_nfserr: | 2508 | out_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) | |||
3691 | int | 3703 | int |
3692 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) | 3704 | nfs4svc_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 | */ | ||
139 | static inline void | ||
140 | fh_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 | */ |
138 | static inline void | 149 | static inline void |
@@ -152,7 +163,8 @@ fill_pre_wcc(struct svc_fh *fhp) | |||
152 | 163 | ||
153 | extern void fill_post_wcc(struct svc_fh *); | 164 | extern 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); |
576 | extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); | 576 | extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); |
577 | extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | ||
578 | struct nfsd4_sequence *seq); | ||
579 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, | 577 | extern __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 *); |
581 | extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *); | 579 | extern __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 | ||
132 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); | 132 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); |
133 | struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, | ||
134 | struct rpc_xprt *xprt); | ||
133 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | 135 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, |
134 | const struct rpc_program *, u32); | 136 | const struct rpc_program *, u32); |
135 | void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt); | 137 | void 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); | |||
56 | int svc_send(struct svc_rqst *); | 56 | int svc_send(struct svc_rqst *); |
57 | void svc_drop(struct svc_rqst *); | 57 | void svc_drop(struct svc_rqst *); |
58 | void svc_sock_update_bufs(struct svc_serv *serv); | 58 | void svc_sock_update_bufs(struct svc_serv *serv); |
59 | bool svc_alien_sock(struct net *net, int fd); | ||
59 | int svc_addsock(struct svc_serv *serv, const int fd, | 60 | int 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); |
61 | void svc_init_xprt_sock(void); | 62 | void 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); | |||
295 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 295 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
296 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 296 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
297 | void xprt_release(struct rpc_task *task); | 297 | void xprt_release(struct rpc_task *task); |
298 | struct rpc_xprt * xprt_get(struct rpc_xprt *xprt); | ||
299 | void xprt_put(struct rpc_xprt *xprt); | 298 | void xprt_put(struct rpc_xprt *xprt); |
300 | struct rpc_xprt * xprt_alloc(struct net *net, size_t size, | 299 | struct 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); |
303 | void xprt_free(struct rpc_xprt *); | 302 | void 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 | */ | ||
309 | static 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 | |||
305 | static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p) | 316 | static 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 | ||
12 | config 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 | |||
25 | config SUNRPC_SWAP | 12 | config 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 | |||
48 | config 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 | |||
61 | config 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 | ||
6 | obj-$(CONFIG_SUNRPC) += sunrpc.o | 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o |
7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ | 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ |
8 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/ | 8 | |
9 | obj-y += xprtrdma/ | ||
9 | 10 | ||
10 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ | 11 | sunrpc-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 | ||
441 | struct 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 | } | ||
471 | EXPORT_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: | |||
451 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) | 483 | struct 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 | } |
543 | EXPORT_SYMBOL_GPL(rpc_create); | 551 | EXPORT_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 | ||
1400 | bool 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); | ||
1411 | out: | ||
1412 | return ret; | ||
1413 | } | ||
1414 | EXPORT_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 | } |
834 | EXPORT_SYMBOL_GPL(xdr_buf_from_iov); | 834 | EXPORT_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 | */ | ||
838 | int | 850 | int |
839 | xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | 851 | xdr_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 | */ | ||
1392 | struct 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 @@ | |||
1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma.o | 1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA_CLIENT) += xprtrdma.o |
2 | 2 | ||
3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o | 3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o |
4 | 4 | ||
5 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += svcrdma.o | 5 | obj-$(CONFIG_SUNRPC_XPRT_RDMA_SERVER) += svcrdma.o |
6 | 6 | ||
7 | svcrdma-y := svc_rdma.o svc_rdma_transport.o \ | 7 | svcrdma-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 | ||
912 | static 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 | ||
2533 | static void bc_destroy(struct rpc_xprt *xprt) | 2538 | static 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 | ||
2537 | static struct rpc_xprt_ops xs_local_ops = { | 2546 | static 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); |
2734 | out_err: | 2743 | out_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); |
2812 | out_err: | 2821 | out_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); |
2892 | out_err: | 2900 | out_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); |
2981 | out_err: | 2981 | out_err: |
2982 | xprt_free(xprt); | 2982 | xs_xprt_free(xprt); |
2983 | return ret; | 2983 | return ret; |
2984 | } | 2984 | } |
2985 | 2985 | ||