diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
commit | df632d3ce7eacf92ad9b642301c7b53a1d95b8d8 (patch) | |
tree | 848c39ed4f7cfdb582bf2e0a0a03147efaa5198d /net | |
parent | 2474542f64432398f503373f53bdf620491bcfa8 (diff) | |
parent | af283885b70248268617955a5ea5476647bd556b (diff) |
Merge tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Features include:
- Remove CONFIG_EXPERIMENTAL dependency from NFSv4.1
Aside from the issues discussed at the LKS, distros are shipping
NFSv4.1 with all the trimmings.
- Fix fdatasync()/fsync() for the corner case of a server reboot.
- NFSv4 OPEN access fix: finally distinguish correctly between
open-for-read and open-for-execute permissions in all situations.
- Ensure that the TCP socket is closed when we're in CLOSE_WAIT
- More idmapper bugfixes
- Lots of pNFS bugfixes and cleanups to remove unnecessary state and
make the code easier to read.
- In cases where a pNFS read or write fails, allow the client to
resume trying layoutgets after two minutes of read/write-
through-mds.
- More net namespace fixes to the NFSv4 callback code.
- More net namespace fixes to the NFSv3 locking code.
- More NFSv4 migration preparatory patches.
Including patches to detect network trunking in both NFSv4 and
NFSv4.1
- pNFS block updates to optimise LAYOUTGET calls."
* tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (113 commits)
pnfsblock: cleanup nfs4_blkdev_get
NFS41: send real read size in layoutget
NFS41: send real write size in layoutget
NFS: track direct IO left bytes
NFSv4.1: Cleanup ugliness in pnfs_layoutgets_blocked()
NFSv4.1: Ensure that the layout sequence id stays 'close' to the current
NFSv4.1: Deal with seqid wraparound in the pNFS return-on-close code
NFSv4 set open access operation call flag in nfs4_init_opendata_res
NFSv4.1: Remove the dependency on CONFIG_EXPERIMENTAL
NFSv4 reduce attribute requests for open reclaim
NFSv4: nfs4_open_done first must check that GETATTR decoded a file type
NFSv4.1: Deal with wraparound when updating the layout "barrier" seqid
NFSv4.1: Deal with wraparound issues when updating the layout stateid
NFSv4.1: Always set the layout stateid if this is the first layoutget
NFSv4.1: Fix another refcount issue in pnfs_find_alloc_layout
NFSv4: don't put ACCESS in OPEN compound if O_EXCL
NFSv4: don't check MAY_WRITE access bit in OPEN
NFS: Set key construction data for the legacy upcall
NFSv4.1: don't do two EXCHANGE_IDs on mount
NFS: nfs41_walk_client_list(): re-lock before iterating
...
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 58 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 105 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 8 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xdr.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 8 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/transport.c | 22 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 40 |
8 files changed, 139 insertions, 125 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 34c522021004..909dc0c31aab 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -239,7 +239,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
239 | } | 239 | } |
240 | return q; | 240 | return q; |
241 | err: | 241 | err: |
242 | dprintk("RPC: gss_fill_context returning %ld\n", -PTR_ERR(p)); | 242 | dprintk("RPC: %s returning %ld\n", __func__, -PTR_ERR(p)); |
243 | return p; | 243 | return p; |
244 | } | 244 | } |
245 | 245 | ||
@@ -301,10 +301,10 @@ __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) | |||
301 | if (pos->uid != uid) | 301 | if (pos->uid != uid) |
302 | continue; | 302 | continue; |
303 | atomic_inc(&pos->count); | 303 | atomic_inc(&pos->count); |
304 | dprintk("RPC: gss_find_upcall found msg %p\n", pos); | 304 | dprintk("RPC: %s found msg %p\n", __func__, pos); |
305 | return pos; | 305 | return pos; |
306 | } | 306 | } |
307 | dprintk("RPC: gss_find_upcall found nothing\n"); | 307 | dprintk("RPC: %s found nothing\n", __func__); |
308 | return NULL; | 308 | return NULL; |
309 | } | 309 | } |
310 | 310 | ||
@@ -507,8 +507,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
507 | struct rpc_pipe *pipe; | 507 | struct rpc_pipe *pipe; |
508 | int err = 0; | 508 | int err = 0; |
509 | 509 | ||
510 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, | 510 | dprintk("RPC: %5u %s for uid %u\n", |
511 | cred->cr_uid); | 511 | task->tk_pid, __func__, cred->cr_uid); |
512 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); | 512 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); |
513 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 513 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
514 | /* XXX: warning on the first, under the assumption we | 514 | /* XXX: warning on the first, under the assumption we |
@@ -539,8 +539,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
539 | spin_unlock(&pipe->lock); | 539 | spin_unlock(&pipe->lock); |
540 | gss_release_msg(gss_msg); | 540 | gss_release_msg(gss_msg); |
541 | out: | 541 | out: |
542 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", | 542 | dprintk("RPC: %5u %s for uid %u result %d\n", |
543 | task->tk_pid, cred->cr_uid, err); | 543 | task->tk_pid, __func__, cred->cr_uid, err); |
544 | return err; | 544 | return err; |
545 | } | 545 | } |
546 | 546 | ||
@@ -553,7 +553,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | |||
553 | DEFINE_WAIT(wait); | 553 | DEFINE_WAIT(wait); |
554 | int err = 0; | 554 | int err = 0; |
555 | 555 | ||
556 | dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid); | 556 | dprintk("RPC: %s for uid %u\n", __func__, cred->cr_uid); |
557 | retry: | 557 | retry: |
558 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 558 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); |
559 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 559 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
@@ -594,8 +594,8 @@ out_intr: | |||
594 | finish_wait(&gss_msg->waitqueue, &wait); | 594 | finish_wait(&gss_msg->waitqueue, &wait); |
595 | gss_release_msg(gss_msg); | 595 | gss_release_msg(gss_msg); |
596 | out: | 596 | out: |
597 | dprintk("RPC: gss_create_upcall for uid %u result %d\n", | 597 | dprintk("RPC: %s for uid %u result %d\n", |
598 | cred->cr_uid, err); | 598 | __func__, cred->cr_uid, err); |
599 | return err; | 599 | return err; |
600 | } | 600 | } |
601 | 601 | ||
@@ -681,7 +681,7 @@ err_put_ctx: | |||
681 | err: | 681 | err: |
682 | kfree(buf); | 682 | kfree(buf); |
683 | out: | 683 | out: |
684 | dprintk("RPC: gss_pipe_downcall returning %Zd\n", err); | 684 | dprintk("RPC: %s returning %Zd\n", __func__, err); |
685 | return err; | 685 | return err; |
686 | } | 686 | } |
687 | 687 | ||
@@ -747,8 +747,8 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
747 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); | 747 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); |
748 | 748 | ||
749 | if (msg->errno < 0) { | 749 | if (msg->errno < 0) { |
750 | dprintk("RPC: gss_pipe_destroy_msg releasing msg %p\n", | 750 | dprintk("RPC: %s releasing msg %p\n", |
751 | gss_msg); | 751 | __func__, gss_msg); |
752 | atomic_inc(&gss_msg->count); | 752 | atomic_inc(&gss_msg->count); |
753 | gss_unhash_msg(gss_msg); | 753 | gss_unhash_msg(gss_msg); |
754 | if (msg->errno == -ETIMEDOUT) | 754 | if (msg->errno == -ETIMEDOUT) |
@@ -976,7 +976,7 @@ gss_destroying_context(struct rpc_cred *cred) | |||
976 | static void | 976 | static void |
977 | gss_do_free_ctx(struct gss_cl_ctx *ctx) | 977 | gss_do_free_ctx(struct gss_cl_ctx *ctx) |
978 | { | 978 | { |
979 | dprintk("RPC: gss_free_ctx\n"); | 979 | dprintk("RPC: %s\n", __func__); |
980 | 980 | ||
981 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 981 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
982 | kfree(ctx->gc_wire_ctx.data); | 982 | kfree(ctx->gc_wire_ctx.data); |
@@ -999,7 +999,7 @@ gss_free_ctx(struct gss_cl_ctx *ctx) | |||
999 | static void | 999 | static void |
1000 | gss_free_cred(struct gss_cred *gss_cred) | 1000 | gss_free_cred(struct gss_cred *gss_cred) |
1001 | { | 1001 | { |
1002 | dprintk("RPC: gss_free_cred %p\n", gss_cred); | 1002 | dprintk("RPC: %s cred=%p\n", __func__, gss_cred); |
1003 | kfree(gss_cred); | 1003 | kfree(gss_cred); |
1004 | } | 1004 | } |
1005 | 1005 | ||
@@ -1049,8 +1049,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
1049 | struct gss_cred *cred = NULL; | 1049 | struct gss_cred *cred = NULL; |
1050 | int err = -ENOMEM; | 1050 | int err = -ENOMEM; |
1051 | 1051 | ||
1052 | dprintk("RPC: gss_create_cred for uid %d, flavor %d\n", | 1052 | dprintk("RPC: %s for uid %d, flavor %d\n", |
1053 | acred->uid, auth->au_flavor); | 1053 | __func__, acred->uid, auth->au_flavor); |
1054 | 1054 | ||
1055 | if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) | 1055 | if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) |
1056 | goto out_err; | 1056 | goto out_err; |
@@ -1069,7 +1069,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
1069 | return &cred->gc_base; | 1069 | return &cred->gc_base; |
1070 | 1070 | ||
1071 | out_err: | 1071 | out_err: |
1072 | dprintk("RPC: gss_create_cred failed with error %d\n", err); | 1072 | dprintk("RPC: %s failed with error %d\n", __func__, err); |
1073 | return ERR_PTR(err); | 1073 | return ERR_PTR(err); |
1074 | } | 1074 | } |
1075 | 1075 | ||
@@ -1127,7 +1127,7 @@ gss_marshal(struct rpc_task *task, __be32 *p) | |||
1127 | struct kvec iov; | 1127 | struct kvec iov; |
1128 | struct xdr_buf verf_buf; | 1128 | struct xdr_buf verf_buf; |
1129 | 1129 | ||
1130 | dprintk("RPC: %5u gss_marshal\n", task->tk_pid); | 1130 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); |
1131 | 1131 | ||
1132 | *p++ = htonl(RPC_AUTH_GSS); | 1132 | *p++ = htonl(RPC_AUTH_GSS); |
1133 | cred_len = p++; | 1133 | cred_len = p++; |
@@ -1253,7 +1253,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1253 | u32 flav,len; | 1253 | u32 flav,len; |
1254 | u32 maj_stat; | 1254 | u32 maj_stat; |
1255 | 1255 | ||
1256 | dprintk("RPC: %5u gss_validate\n", task->tk_pid); | 1256 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); |
1257 | 1257 | ||
1258 | flav = ntohl(*p++); | 1258 | flav = ntohl(*p++); |
1259 | if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) | 1259 | if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) |
@@ -1271,20 +1271,20 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1271 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1271 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1272 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1272 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1273 | if (maj_stat) { | 1273 | if (maj_stat) { |
1274 | dprintk("RPC: %5u gss_validate: gss_verify_mic returned " | 1274 | dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n", |
1275 | "error 0x%08x\n", task->tk_pid, maj_stat); | 1275 | task->tk_pid, __func__, maj_stat); |
1276 | goto out_bad; | 1276 | goto out_bad; |
1277 | } | 1277 | } |
1278 | /* We leave it to unwrap to calculate au_rslack. For now we just | 1278 | /* We leave it to unwrap to calculate au_rslack. For now we just |
1279 | * calculate the length of the verifier: */ | 1279 | * calculate the length of the verifier: */ |
1280 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; | 1280 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; |
1281 | gss_put_ctx(ctx); | 1281 | gss_put_ctx(ctx); |
1282 | dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n", | 1282 | dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n", |
1283 | task->tk_pid); | 1283 | task->tk_pid, __func__); |
1284 | return p + XDR_QUADLEN(len); | 1284 | return p + XDR_QUADLEN(len); |
1285 | out_bad: | 1285 | out_bad: |
1286 | gss_put_ctx(ctx); | 1286 | gss_put_ctx(ctx); |
1287 | dprintk("RPC: %5u gss_validate failed.\n", task->tk_pid); | 1287 | dprintk("RPC: %5u %s failed.\n", task->tk_pid, __func__); |
1288 | return NULL; | 1288 | return NULL; |
1289 | } | 1289 | } |
1290 | 1290 | ||
@@ -1466,7 +1466,7 @@ gss_wrap_req(struct rpc_task *task, | |||
1466 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1466 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1467 | int status = -EIO; | 1467 | int status = -EIO; |
1468 | 1468 | ||
1469 | dprintk("RPC: %5u gss_wrap_req\n", task->tk_pid); | 1469 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); |
1470 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { | 1470 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { |
1471 | /* The spec seems a little ambiguous here, but I think that not | 1471 | /* The spec seems a little ambiguous here, but I think that not |
1472 | * wrapping context destruction requests makes the most sense. | 1472 | * wrapping context destruction requests makes the most sense. |
@@ -1489,7 +1489,7 @@ gss_wrap_req(struct rpc_task *task, | |||
1489 | } | 1489 | } |
1490 | out: | 1490 | out: |
1491 | gss_put_ctx(ctx); | 1491 | gss_put_ctx(ctx); |
1492 | dprintk("RPC: %5u gss_wrap_req returning %d\n", task->tk_pid, status); | 1492 | dprintk("RPC: %5u %s returning %d\n", task->tk_pid, __func__, status); |
1493 | return status; | 1493 | return status; |
1494 | } | 1494 | } |
1495 | 1495 | ||
@@ -1604,8 +1604,8 @@ out_decode: | |||
1604 | status = gss_unwrap_req_decode(decode, rqstp, p, obj); | 1604 | status = gss_unwrap_req_decode(decode, rqstp, p, obj); |
1605 | out: | 1605 | out: |
1606 | gss_put_ctx(ctx); | 1606 | gss_put_ctx(ctx); |
1607 | dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid, | 1607 | dprintk("RPC: %5u %s returning %d\n", |
1608 | status); | 1608 | task->tk_pid, __func__, status); |
1609 | return status; | 1609 | return status; |
1610 | } | 1610 | } |
1611 | 1611 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index fa48c60aef23..cdc7564b4512 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -490,61 +490,86 @@ EXPORT_SYMBOL_GPL(rpc_create); | |||
490 | * same transport while varying parameters such as the authentication | 490 | * same transport while varying parameters such as the authentication |
491 | * flavour. | 491 | * flavour. |
492 | */ | 492 | */ |
493 | struct rpc_clnt * | 493 | static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, |
494 | rpc_clone_client(struct rpc_clnt *clnt) | 494 | struct rpc_clnt *clnt) |
495 | { | 495 | { |
496 | struct rpc_clnt *new; | ||
497 | struct rpc_xprt *xprt; | 496 | struct rpc_xprt *xprt; |
498 | int err = -ENOMEM; | 497 | struct rpc_clnt *new; |
498 | int err; | ||
499 | 499 | ||
500 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 500 | err = -ENOMEM; |
501 | if (!new) | ||
502 | goto out_no_clnt; | ||
503 | new->cl_parent = clnt; | ||
504 | /* Turn off autobind on clones */ | ||
505 | new->cl_autobind = 0; | ||
506 | INIT_LIST_HEAD(&new->cl_tasks); | ||
507 | spin_lock_init(&new->cl_lock); | ||
508 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); | ||
509 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
510 | if (new->cl_metrics == NULL) | ||
511 | goto out_no_stats; | ||
512 | if (clnt->cl_principal) { | ||
513 | new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL); | ||
514 | if (new->cl_principal == NULL) | ||
515 | goto out_no_principal; | ||
516 | } | ||
517 | rcu_read_lock(); | 501 | rcu_read_lock(); |
518 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | 502 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); |
519 | rcu_read_unlock(); | 503 | rcu_read_unlock(); |
520 | if (xprt == NULL) | 504 | if (xprt == NULL) |
521 | goto out_no_transport; | 505 | goto out_err; |
522 | rcu_assign_pointer(new->cl_xprt, xprt); | 506 | args->servername = xprt->servername; |
523 | atomic_set(&new->cl_count, 1); | 507 | |
524 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 508 | new = rpc_new_client(args, xprt); |
525 | if (err != 0) | 509 | if (IS_ERR(new)) { |
526 | goto out_no_path; | 510 | err = PTR_ERR(new); |
527 | rpc_clnt_set_nodename(new, utsname()->nodename); | 511 | goto out_put; |
528 | if (new->cl_auth) | 512 | } |
529 | atomic_inc(&new->cl_auth->au_count); | 513 | |
530 | atomic_inc(&clnt->cl_count); | 514 | atomic_inc(&clnt->cl_count); |
531 | rpc_register_client(new); | 515 | new->cl_parent = clnt; |
532 | rpciod_up(); | 516 | |
517 | /* Turn off autobind on clones */ | ||
518 | new->cl_autobind = 0; | ||
519 | new->cl_softrtry = clnt->cl_softrtry; | ||
520 | new->cl_discrtry = clnt->cl_discrtry; | ||
521 | new->cl_chatty = clnt->cl_chatty; | ||
533 | return new; | 522 | return new; |
534 | out_no_path: | 523 | |
524 | out_put: | ||
535 | xprt_put(xprt); | 525 | xprt_put(xprt); |
536 | out_no_transport: | 526 | out_err: |
537 | kfree(new->cl_principal); | ||
538 | out_no_principal: | ||
539 | rpc_free_iostats(new->cl_metrics); | ||
540 | out_no_stats: | ||
541 | kfree(new); | ||
542 | out_no_clnt: | ||
543 | dprintk("RPC: %s: returned error %d\n", __func__, err); | 527 | dprintk("RPC: %s: returned error %d\n", __func__, err); |
544 | return ERR_PTR(err); | 528 | return ERR_PTR(err); |
545 | } | 529 | } |
530 | |||
531 | /** | ||
532 | * rpc_clone_client - Clone an RPC client structure | ||
533 | * | ||
534 | * @clnt: RPC client whose parameters are copied | ||
535 | * | ||
536 | * Returns a fresh RPC client or an ERR_PTR. | ||
537 | */ | ||
538 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) | ||
539 | { | ||
540 | struct rpc_create_args args = { | ||
541 | .program = clnt->cl_program, | ||
542 | .prognumber = clnt->cl_prog, | ||
543 | .version = clnt->cl_vers, | ||
544 | .authflavor = clnt->cl_auth->au_flavor, | ||
545 | .client_name = clnt->cl_principal, | ||
546 | }; | ||
547 | return __rpc_clone_client(&args, clnt); | ||
548 | } | ||
546 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 549 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
547 | 550 | ||
551 | /** | ||
552 | * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth | ||
553 | * | ||
554 | * @clnt: RPC client whose parameters are copied | ||
555 | * @auth: security flavor for new client | ||
556 | * | ||
557 | * Returns a fresh RPC client or an ERR_PTR. | ||
558 | */ | ||
559 | struct rpc_clnt * | ||
560 | rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | ||
561 | { | ||
562 | struct rpc_create_args args = { | ||
563 | .program = clnt->cl_program, | ||
564 | .prognumber = clnt->cl_prog, | ||
565 | .version = clnt->cl_vers, | ||
566 | .authflavor = flavor, | ||
567 | .client_name = clnt->cl_principal, | ||
568 | }; | ||
569 | return __rpc_clone_client(&args, clnt); | ||
570 | } | ||
571 | EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth); | ||
572 | |||
548 | /* | 573 | /* |
549 | * Kill all tasks for the given client. | 574 | * Kill all tasks for the given client. |
550 | * XXX: kill their descendants as well? | 575 | * XXX: kill their descendants as well? |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 21fde99e5c56..80f5dd23417d 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -1119,8 +1119,8 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1119 | return -ENOMEM; | 1119 | return -ENOMEM; |
1120 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1120 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
1121 | return -ENOMEM; | 1121 | return -ENOMEM; |
1122 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", net, | 1122 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", |
1123 | NET_NAME(net)); | 1123 | net, NET_NAME(net)); |
1124 | sn->pipefs_sb = sb; | 1124 | sn->pipefs_sb = sb; |
1125 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1125 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1126 | RPC_PIPEFS_MOUNT, | 1126 | RPC_PIPEFS_MOUNT, |
@@ -1155,8 +1155,8 @@ static void rpc_kill_sb(struct super_block *sb) | |||
1155 | sn->pipefs_sb = NULL; | 1155 | sn->pipefs_sb = NULL; |
1156 | mutex_unlock(&sn->pipefs_sb_lock); | 1156 | mutex_unlock(&sn->pipefs_sb_lock); |
1157 | put_net(net); | 1157 | put_net(net); |
1158 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, | 1158 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", |
1159 | NET_NAME(net)); | 1159 | net, NET_NAME(net)); |
1160 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1160 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1161 | RPC_PIPEFS_UMOUNT, | 1161 | RPC_PIPEFS_UMOUNT, |
1162 | sb); | 1162 | sb); |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 128494ec9a64..6357fcb00c7e 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -1022,7 +1022,7 @@ static int rpciod_start(void) | |||
1022 | * Create the rpciod thread and wait for it to start. | 1022 | * Create the rpciod thread and wait for it to start. |
1023 | */ | 1023 | */ |
1024 | dprintk("RPC: creating workqueue rpciod\n"); | 1024 | dprintk("RPC: creating workqueue rpciod\n"); |
1025 | wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0); | 1025 | wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 1); |
1026 | rpciod_workqueue = wq; | 1026 | rpciod_workqueue = wq; |
1027 | return rpciod_workqueue != NULL; | 1027 | return rpciod_workqueue != NULL; |
1028 | } | 1028 | } |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 0afba1b4b656..08f50afd5f2a 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -730,19 +730,24 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | |||
730 | 730 | ||
731 | if (xdr->nwords == 0) | 731 | if (xdr->nwords == 0) |
732 | return 0; | 732 | return 0; |
733 | if (nwords > xdr->nwords) { | ||
734 | nwords = xdr->nwords; | ||
735 | len = nwords << 2; | ||
736 | } | ||
737 | /* Realign pages to current pointer position */ | 733 | /* Realign pages to current pointer position */ |
738 | iov = buf->head; | 734 | iov = buf->head; |
739 | if (iov->iov_len > cur) | 735 | if (iov->iov_len > cur) { |
740 | xdr_shrink_bufhead(buf, iov->iov_len - cur); | 736 | xdr_shrink_bufhead(buf, iov->iov_len - cur); |
737 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | ||
738 | } | ||
741 | 739 | ||
742 | /* Truncate page data and move it into the tail */ | 740 | if (nwords > xdr->nwords) { |
743 | if (buf->page_len > len) | 741 | nwords = xdr->nwords; |
742 | len = nwords << 2; | ||
743 | } | ||
744 | if (buf->page_len <= len) | ||
745 | len = buf->page_len; | ||
746 | else if (nwords < xdr->nwords) { | ||
747 | /* Truncate page data and move it into the tail */ | ||
744 | xdr_shrink_pagelen(buf, buf->page_len - len); | 748 | xdr_shrink_pagelen(buf, buf->page_len - len); |
745 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | 749 | xdr->nwords = XDR_QUADLEN(buf->len - cur); |
750 | } | ||
746 | return len; | 751 | return len; |
747 | } | 752 | } |
748 | 753 | ||
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 5d7f61d7559c..bd462a532acf 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -231,7 +231,7 @@ EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | |||
231 | static void xprt_clear_locked(struct rpc_xprt *xprt) | 231 | static void xprt_clear_locked(struct rpc_xprt *xprt) |
232 | { | 232 | { |
233 | xprt->snd_task = NULL; | 233 | xprt->snd_task = NULL; |
234 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) { | 234 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state)) { |
235 | smp_mb__before_clear_bit(); | 235 | smp_mb__before_clear_bit(); |
236 | clear_bit(XPRT_LOCKED, &xprt->state); | 236 | clear_bit(XPRT_LOCKED, &xprt->state); |
237 | smp_mb__after_clear_bit(); | 237 | smp_mb__after_clear_bit(); |
@@ -504,9 +504,6 @@ EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | |||
504 | */ | 504 | */ |
505 | void xprt_write_space(struct rpc_xprt *xprt) | 505 | void xprt_write_space(struct rpc_xprt *xprt) |
506 | { | 506 | { |
507 | if (unlikely(xprt->shutdown)) | ||
508 | return; | ||
509 | |||
510 | spin_lock_bh(&xprt->transport_lock); | 507 | spin_lock_bh(&xprt->transport_lock); |
511 | if (xprt->snd_task) { | 508 | if (xprt->snd_task) { |
512 | dprintk("RPC: write space: waking waiting task on " | 509 | dprintk("RPC: write space: waking waiting task on " |
@@ -679,7 +676,7 @@ xprt_init_autodisconnect(unsigned long data) | |||
679 | struct rpc_xprt *xprt = (struct rpc_xprt *)data; | 676 | struct rpc_xprt *xprt = (struct rpc_xprt *)data; |
680 | 677 | ||
681 | spin_lock(&xprt->transport_lock); | 678 | spin_lock(&xprt->transport_lock); |
682 | if (!list_empty(&xprt->recv) || xprt->shutdown) | 679 | if (!list_empty(&xprt->recv)) |
683 | goto out_abort; | 680 | goto out_abort; |
684 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | 681 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) |
685 | goto out_abort; | 682 | goto out_abort; |
@@ -1262,7 +1259,6 @@ out: | |||
1262 | static void xprt_destroy(struct rpc_xprt *xprt) | 1259 | static void xprt_destroy(struct rpc_xprt *xprt) |
1263 | { | 1260 | { |
1264 | dprintk("RPC: destroying transport %p\n", xprt); | 1261 | dprintk("RPC: destroying transport %p\n", xprt); |
1265 | xprt->shutdown = 1; | ||
1266 | del_timer_sync(&xprt->timer); | 1262 | del_timer_sync(&xprt->timer); |
1267 | 1263 | ||
1268 | rpc_destroy_wait_queue(&xprt->binding); | 1264 | rpc_destroy_wait_queue(&xprt->binding); |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 5d9202dc7cb1..c9aa7a35f3bf 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -199,21 +199,15 @@ xprt_rdma_connect_worker(struct work_struct *work) | |||
199 | struct rpc_xprt *xprt = &r_xprt->xprt; | 199 | struct rpc_xprt *xprt = &r_xprt->xprt; |
200 | int rc = 0; | 200 | int rc = 0; |
201 | 201 | ||
202 | if (!xprt->shutdown) { | 202 | current->flags |= PF_FSTRANS; |
203 | current->flags |= PF_FSTRANS; | 203 | xprt_clear_connected(xprt); |
204 | xprt_clear_connected(xprt); | 204 | |
205 | 205 | dprintk("RPC: %s: %sconnect\n", __func__, | |
206 | dprintk("RPC: %s: %sconnect\n", __func__, | 206 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); |
207 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); | 207 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); |
208 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); | 208 | if (rc) |
209 | if (rc) | 209 | xprt_wake_pending_tasks(xprt, rc); |
210 | goto out; | ||
211 | } | ||
212 | goto out_clear; | ||
213 | 210 | ||
214 | out: | ||
215 | xprt_wake_pending_tasks(xprt, rc); | ||
216 | out_clear: | ||
217 | dprintk("RPC: %s: exit\n", __func__); | 211 | dprintk("RPC: %s: exit\n", __func__); |
218 | xprt_clear_connecting(xprt); | 212 | xprt_clear_connecting(xprt); |
219 | current->flags &= ~PF_FSTRANS; | 213 | current->flags &= ~PF_FSTRANS; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a35b8e52e551..aaaadfbe36e9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -917,9 +917,6 @@ static void xs_local_data_ready(struct sock *sk, int len) | |||
917 | if (skb == NULL) | 917 | if (skb == NULL) |
918 | goto out; | 918 | goto out; |
919 | 919 | ||
920 | if (xprt->shutdown) | ||
921 | goto dropit; | ||
922 | |||
923 | repsize = skb->len - sizeof(rpc_fraghdr); | 920 | repsize = skb->len - sizeof(rpc_fraghdr); |
924 | if (repsize < 4) { | 921 | if (repsize < 4) { |
925 | dprintk("RPC: impossible RPC reply size %d\n", repsize); | 922 | dprintk("RPC: impossible RPC reply size %d\n", repsize); |
@@ -981,9 +978,6 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
981 | if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) | 978 | if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) |
982 | goto out; | 979 | goto out; |
983 | 980 | ||
984 | if (xprt->shutdown) | ||
985 | goto dropit; | ||
986 | |||
987 | repsize = skb->len - sizeof(struct udphdr); | 981 | repsize = skb->len - sizeof(struct udphdr); |
988 | if (repsize < 4) { | 982 | if (repsize < 4) { |
989 | dprintk("RPC: impossible RPC reply size %d!\n", repsize); | 983 | dprintk("RPC: impossible RPC reply size %d!\n", repsize); |
@@ -1025,6 +1019,16 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
1025 | read_unlock_bh(&sk->sk_callback_lock); | 1019 | read_unlock_bh(&sk->sk_callback_lock); |
1026 | } | 1020 | } |
1027 | 1021 | ||
1022 | /* | ||
1023 | * Helper function to force a TCP close if the server is sending | ||
1024 | * junk and/or it has put us in CLOSE_WAIT | ||
1025 | */ | ||
1026 | static void xs_tcp_force_close(struct rpc_xprt *xprt) | ||
1027 | { | ||
1028 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
1029 | xprt_force_disconnect(xprt); | ||
1030 | } | ||
1031 | |||
1028 | static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) | 1032 | static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) |
1029 | { | 1033 | { |
1030 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1034 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
@@ -1051,7 +1055,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
1051 | /* Sanity check of the record length */ | 1055 | /* Sanity check of the record length */ |
1052 | if (unlikely(transport->tcp_reclen < 8)) { | 1056 | if (unlikely(transport->tcp_reclen < 8)) { |
1053 | dprintk("RPC: invalid TCP record fragment length\n"); | 1057 | dprintk("RPC: invalid TCP record fragment length\n"); |
1054 | xprt_force_disconnect(xprt); | 1058 | xs_tcp_force_close(xprt); |
1055 | return; | 1059 | return; |
1056 | } | 1060 | } |
1057 | dprintk("RPC: reading TCP record fragment of length %d\n", | 1061 | dprintk("RPC: reading TCP record fragment of length %d\n", |
@@ -1132,7 +1136,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, | |||
1132 | break; | 1136 | break; |
1133 | default: | 1137 | default: |
1134 | dprintk("RPC: invalid request message type\n"); | 1138 | dprintk("RPC: invalid request message type\n"); |
1135 | xprt_force_disconnect(&transport->xprt); | 1139 | xs_tcp_force_close(&transport->xprt); |
1136 | } | 1140 | } |
1137 | xs_tcp_check_fraghdr(transport); | 1141 | xs_tcp_check_fraghdr(transport); |
1138 | } | 1142 | } |
@@ -1402,9 +1406,6 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes) | |||
1402 | read_lock_bh(&sk->sk_callback_lock); | 1406 | read_lock_bh(&sk->sk_callback_lock); |
1403 | if (!(xprt = xprt_from_sock(sk))) | 1407 | if (!(xprt = xprt_from_sock(sk))) |
1404 | goto out; | 1408 | goto out; |
1405 | if (xprt->shutdown) | ||
1406 | goto out; | ||
1407 | |||
1408 | /* Any data means we had a useful conversation, so | 1409 | /* Any data means we had a useful conversation, so |
1409 | * the we don't need to delay the next reconnect | 1410 | * the we don't need to delay the next reconnect |
1410 | */ | 1411 | */ |
@@ -1455,6 +1456,8 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) | |||
1455 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | 1456 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) |
1456 | { | 1457 | { |
1457 | smp_mb__before_clear_bit(); | 1458 | smp_mb__before_clear_bit(); |
1459 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
1460 | clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
1458 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1461 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1459 | clear_bit(XPRT_CLOSING, &xprt->state); | 1462 | clear_bit(XPRT_CLOSING, &xprt->state); |
1460 | smp_mb__after_clear_bit(); | 1463 | smp_mb__after_clear_bit(); |
@@ -1512,8 +1515,8 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1512 | break; | 1515 | break; |
1513 | case TCP_CLOSE_WAIT: | 1516 | case TCP_CLOSE_WAIT: |
1514 | /* The server initiated a shutdown of the socket */ | 1517 | /* The server initiated a shutdown of the socket */ |
1515 | xprt_force_disconnect(xprt); | ||
1516 | xprt->connect_cookie++; | 1518 | xprt->connect_cookie++; |
1519 | xs_tcp_force_close(xprt); | ||
1517 | case TCP_CLOSING: | 1520 | case TCP_CLOSING: |
1518 | /* | 1521 | /* |
1519 | * If the server closed down the connection, make sure that | 1522 | * If the server closed down the connection, make sure that |
@@ -1889,9 +1892,6 @@ static void xs_local_setup_socket(struct work_struct *work) | |||
1889 | struct socket *sock; | 1892 | struct socket *sock; |
1890 | int status = -EIO; | 1893 | int status = -EIO; |
1891 | 1894 | ||
1892 | if (xprt->shutdown) | ||
1893 | goto out; | ||
1894 | |||
1895 | current->flags |= PF_FSTRANS; | 1895 | current->flags |= PF_FSTRANS; |
1896 | 1896 | ||
1897 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 1897 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
@@ -2008,9 +2008,6 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2008 | struct socket *sock = transport->sock; | 2008 | struct socket *sock = transport->sock; |
2009 | int status = -EIO; | 2009 | int status = -EIO; |
2010 | 2010 | ||
2011 | if (xprt->shutdown) | ||
2012 | goto out; | ||
2013 | |||
2014 | current->flags |= PF_FSTRANS; | 2011 | current->flags |= PF_FSTRANS; |
2015 | 2012 | ||
2016 | /* Start by resetting any existing state */ | 2013 | /* Start by resetting any existing state */ |
@@ -2156,9 +2153,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2156 | struct rpc_xprt *xprt = &transport->xprt; | 2153 | struct rpc_xprt *xprt = &transport->xprt; |
2157 | int status = -EIO; | 2154 | int status = -EIO; |
2158 | 2155 | ||
2159 | if (xprt->shutdown) | ||
2160 | goto out; | ||
2161 | |||
2162 | current->flags |= PF_FSTRANS; | 2156 | current->flags |= PF_FSTRANS; |
2163 | 2157 | ||
2164 | if (!sock) { | 2158 | if (!sock) { |
@@ -2199,8 +2193,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2199 | /* We're probably in TIME_WAIT. Get rid of existing socket, | 2193 | /* We're probably in TIME_WAIT. Get rid of existing socket, |
2200 | * and retry | 2194 | * and retry |
2201 | */ | 2195 | */ |
2202 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | 2196 | xs_tcp_force_close(xprt); |
2203 | xprt_force_disconnect(xprt); | ||
2204 | break; | 2197 | break; |
2205 | case -ECONNREFUSED: | 2198 | case -ECONNREFUSED: |
2206 | case -ECONNRESET: | 2199 | case -ECONNRESET: |
@@ -2528,6 +2521,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
2528 | static struct rpc_xprt_ops bc_tcp_ops = { | 2521 | static struct rpc_xprt_ops bc_tcp_ops = { |
2529 | .reserve_xprt = xprt_reserve_xprt, | 2522 | .reserve_xprt = xprt_reserve_xprt, |
2530 | .release_xprt = xprt_release_xprt, | 2523 | .release_xprt = xprt_release_xprt, |
2524 | .alloc_slot = xprt_alloc_slot, | ||
2531 | .rpcbind = xs_local_rpcbind, | 2525 | .rpcbind = xs_local_rpcbind, |
2532 | .buf_alloc = bc_malloc, | 2526 | .buf_alloc = bc_malloc, |
2533 | .buf_free = bc_free, | 2527 | .buf_free = bc_free, |