diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 112 | 
1 files changed, 73 insertions, 39 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 375f0fae2c6a..f9254fb0c9d0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c  | |||
| @@ -281,6 +281,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
| 281 | } | 281 | } | 
| 282 | case -NFS4ERR_GRACE: | 282 | case -NFS4ERR_GRACE: | 
| 283 | case -NFS4ERR_DELAY: | 283 | case -NFS4ERR_DELAY: | 
| 284 | case -EKEYEXPIRED: | ||
| 284 | ret = nfs4_delay(server->client, &exception->timeout); | 285 | ret = nfs4_delay(server->client, &exception->timeout); | 
| 285 | if (ret != 0) | 286 | if (ret != 0) | 
| 286 | break; | 287 | break; | 
| @@ -418,7 +419,8 @@ static void nfs41_sequence_done(struct nfs_client *clp, | |||
| 418 | clp->cl_last_renewal = timestamp; | 419 | clp->cl_last_renewal = timestamp; | 
| 419 | spin_unlock(&clp->cl_lock); | 420 | spin_unlock(&clp->cl_lock); | 
| 420 | /* Check sequence flags */ | 421 | /* Check sequence flags */ | 
| 421 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | 422 | if (atomic_read(&clp->cl_count) > 1) | 
| 423 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | ||
| 422 | } | 424 | } | 
| 423 | out: | 425 | out: | 
| 424 | /* The session may be reset by one of the error handlers. */ | 426 | /* The session may be reset by one of the error handlers. */ | 
| @@ -724,8 +726,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | |||
| 724 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | 726 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | 
| 725 | if (p->o_arg.seqid == NULL) | 727 | if (p->o_arg.seqid == NULL) | 
| 726 | goto err_free; | 728 | goto err_free; | 
| 727 | p->path.mnt = mntget(path->mnt); | 729 | path_get(path); | 
| 728 | p->path.dentry = dget(path->dentry); | 730 | p->path = *path; | 
| 729 | p->dir = parent; | 731 | p->dir = parent; | 
| 730 | p->owner = sp; | 732 | p->owner = sp; | 
| 731 | atomic_inc(&sp->so_count); | 733 | atomic_inc(&sp->so_count); | 
| @@ -1163,7 +1165,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
| 1163 | int err; | 1165 | int err; | 
| 1164 | do { | 1166 | do { | 
| 1165 | err = _nfs4_do_open_reclaim(ctx, state); | 1167 | err = _nfs4_do_open_reclaim(ctx, state); | 
| 1166 | if (err != -NFS4ERR_DELAY) | 1168 | if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED) | 
| 1167 | break; | 1169 | break; | 
| 1168 | nfs4_handle_exception(server, err, &exception); | 1170 | nfs4_handle_exception(server, err, &exception); | 
| 1169 | } while (exception.retry); | 1171 | } while (exception.retry); | 
| @@ -1582,6 +1584,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state | |||
| 1582 | goto out; | 1584 | goto out; | 
| 1583 | case -NFS4ERR_GRACE: | 1585 | case -NFS4ERR_GRACE: | 
| 1584 | case -NFS4ERR_DELAY: | 1586 | case -NFS4ERR_DELAY: | 
| 1587 | case -EKEYEXPIRED: | ||
| 1585 | nfs4_handle_exception(server, err, &exception); | 1588 | nfs4_handle_exception(server, err, &exception); | 
| 1586 | err = 0; | 1589 | err = 0; | 
| 1587 | } | 1590 | } | 
| @@ -1944,8 +1947,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
| 1944 | calldata->res.seqid = calldata->arg.seqid; | 1947 | calldata->res.seqid = calldata->arg.seqid; | 
| 1945 | calldata->res.server = server; | 1948 | calldata->res.server = server; | 
| 1946 | calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | 1949 | calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | 
| 1947 | calldata->path.mnt = mntget(path->mnt); | 1950 | path_get(path); | 
| 1948 | calldata->path.dentry = dget(path->dentry); | 1951 | calldata->path = *path; | 
| 1949 | 1952 | ||
| 1950 | msg.rpc_argp = &calldata->arg, | 1953 | msg.rpc_argp = &calldata->arg, | 
| 1951 | msg.rpc_resp = &calldata->res, | 1954 | msg.rpc_resp = &calldata->res, | 
| @@ -3145,10 +3148,19 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa | |||
| 3145 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special | 3148 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special | 
| 3146 | * standalone procedure for queueing an asynchronous RENEW. | 3149 | * standalone procedure for queueing an asynchronous RENEW. | 
| 3147 | */ | 3150 | */ | 
| 3151 | static void nfs4_renew_release(void *data) | ||
| 3152 | { | ||
| 3153 | struct nfs_client *clp = data; | ||
| 3154 | |||
| 3155 | if (atomic_read(&clp->cl_count) > 1) | ||
| 3156 | nfs4_schedule_state_renewal(clp); | ||
| 3157 | nfs_put_client(clp); | ||
| 3158 | } | ||
| 3159 | |||
| 3148 | static void nfs4_renew_done(struct rpc_task *task, void *data) | 3160 | static void nfs4_renew_done(struct rpc_task *task, void *data) | 
| 3149 | { | 3161 | { | 
| 3150 | struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp; | 3162 | struct nfs_client *clp = data; | 
| 3151 | unsigned long timestamp = (unsigned long)data; | 3163 | unsigned long timestamp = task->tk_start; | 
| 3152 | 3164 | ||
| 3153 | if (task->tk_status < 0) { | 3165 | if (task->tk_status < 0) { | 
| 3154 | /* Unless we're shutting down, schedule state recovery! */ | 3166 | /* Unless we're shutting down, schedule state recovery! */ | 
| @@ -3164,6 +3176,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *data) | |||
| 3164 | 3176 | ||
| 3165 | static const struct rpc_call_ops nfs4_renew_ops = { | 3177 | static const struct rpc_call_ops nfs4_renew_ops = { | 
| 3166 | .rpc_call_done = nfs4_renew_done, | 3178 | .rpc_call_done = nfs4_renew_done, | 
| 3179 | .rpc_release = nfs4_renew_release, | ||
| 3167 | }; | 3180 | }; | 
| 3168 | 3181 | ||
| 3169 | int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | 3182 | int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | 
| @@ -3174,8 +3187,10 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 3174 | .rpc_cred = cred, | 3187 | .rpc_cred = cred, | 
| 3175 | }; | 3188 | }; | 
| 3176 | 3189 | ||
| 3190 | if (!atomic_inc_not_zero(&clp->cl_count)) | ||
| 3191 | return -EIO; | ||
| 3177 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | 3192 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | 
| 3178 | &nfs4_renew_ops, (void *)jiffies); | 3193 | &nfs4_renew_ops, clp); | 
| 3179 | } | 3194 | } | 
| 3180 | 3195 | ||
| 3181 | int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | 3196 | int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | 
| @@ -3452,6 +3467,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
| 3452 | if (server) | 3467 | if (server) | 
| 3453 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 3468 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 
| 3454 | case -NFS4ERR_GRACE: | 3469 | case -NFS4ERR_GRACE: | 
| 3470 | case -EKEYEXPIRED: | ||
| 3455 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3471 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 
| 3456 | task->tk_status = 0; | 3472 | task->tk_status = 0; | 
| 3457 | return -EAGAIN; | 3473 | return -EAGAIN; | 
| @@ -3564,6 +3580,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 3564 | case -NFS4ERR_RESOURCE: | 3580 | case -NFS4ERR_RESOURCE: | 
| 3565 | /* The IBM lawyers misread another document! */ | 3581 | /* The IBM lawyers misread another document! */ | 
| 3566 | case -NFS4ERR_DELAY: | 3582 | case -NFS4ERR_DELAY: | 
| 3583 | case -EKEYEXPIRED: | ||
| 3567 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | 3584 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | 
| 3568 | } | 3585 | } | 
| 3569 | } while (err == 0); | 3586 | } while (err == 0); | 
| @@ -4179,7 +4196,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
| 4179 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 4196 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 
| 4180 | return 0; | 4197 | return 0; | 
| 4181 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); | 4198 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); | 
| 4182 | if (err != -NFS4ERR_DELAY) | 4199 | if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED) | 
| 4183 | break; | 4200 | break; | 
| 4184 | nfs4_handle_exception(server, err, &exception); | 4201 | nfs4_handle_exception(server, err, &exception); | 
| 4185 | } while (exception.retry); | 4202 | } while (exception.retry); | 
| @@ -4204,6 +4221,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
| 4204 | goto out; | 4221 | goto out; | 
| 4205 | case -NFS4ERR_GRACE: | 4222 | case -NFS4ERR_GRACE: | 
| 4206 | case -NFS4ERR_DELAY: | 4223 | case -NFS4ERR_DELAY: | 
| 4224 | case -EKEYEXPIRED: | ||
| 4207 | nfs4_handle_exception(server, err, &exception); | 4225 | nfs4_handle_exception(server, err, &exception); | 
| 4208 | err = 0; | 4226 | err = 0; | 
| 4209 | } | 4227 | } | 
| @@ -4355,6 +4373,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
| 4355 | err = 0; | 4373 | err = 0; | 
| 4356 | goto out; | 4374 | goto out; | 
| 4357 | case -NFS4ERR_DELAY: | 4375 | case -NFS4ERR_DELAY: | 
| 4376 | case -EKEYEXPIRED: | ||
| 4358 | break; | 4377 | break; | 
| 4359 | } | 4378 | } | 
| 4360 | err = nfs4_handle_exception(server, err, &exception); | 4379 | err = nfs4_handle_exception(server, err, &exception); | 
| @@ -4500,7 +4519,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 4500 | 4519 | ||
| 4501 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 4520 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 
| 4502 | 4521 | ||
| 4503 | if (status != NFS4ERR_CLID_INUSE) | 4522 | if (status != -NFS4ERR_CLID_INUSE) | 
| 4504 | break; | 4523 | break; | 
| 4505 | 4524 | ||
| 4506 | if (signalled()) | 4525 | if (signalled()) | 
| @@ -4554,6 +4573,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
| 4554 | switch (task->tk_status) { | 4573 | switch (task->tk_status) { | 
| 4555 | case -NFS4ERR_DELAY: | 4574 | case -NFS4ERR_DELAY: | 
| 4556 | case -NFS4ERR_GRACE: | 4575 | case -NFS4ERR_GRACE: | 
| 4576 | case -EKEYEXPIRED: | ||
| 4557 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4577 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 
| 4558 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4578 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 
| 4559 | task->tk_status = 0; | 4579 | task->tk_status = 0; | 
| @@ -4611,26 +4631,32 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
| 4611 | /* | 4631 | /* | 
| 4612 | * Reset a slot table | 4632 | * Reset a slot table | 
| 4613 | */ | 4633 | */ | 
| 4614 | static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, | 4634 | static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | 
| 4615 | int old_max_slots, int ivalue) | 4635 | int ivalue) | 
| 4616 | { | 4636 | { | 
| 4637 | struct nfs4_slot *new = NULL; | ||
| 4617 | int i; | 4638 | int i; | 
| 4618 | int ret = 0; | 4639 | int ret = 0; | 
| 4619 | 4640 | ||
| 4620 | dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl); | 4641 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | 
| 4642 | max_reqs, tbl->max_slots); | ||
| 4621 | 4643 | ||
| 4622 | /* | 4644 | /* Does the newly negotiated max_reqs match the existing slot table? */ | 
| 4623 | * Until we have dynamic slot table adjustment, insist | 4645 | if (max_reqs != tbl->max_slots) { | 
| 4624 | * upon the same slot table size | 4646 | ret = -ENOMEM; | 
| 4625 | */ | 4647 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), | 
| 4626 | if (max_slots != old_max_slots) { | 4648 | GFP_KERNEL); | 
| 4627 | dprintk("%s reset slot table does't match old\n", | 4649 | if (!new) | 
| 4628 | __func__); | 4650 | goto out; | 
| 4629 | ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */ | 4651 | ret = 0; | 
| 4630 | goto out; | 4652 | kfree(tbl->slots); | 
| 4631 | } | 4653 | } | 
| 4632 | spin_lock(&tbl->slot_tbl_lock); | 4654 | spin_lock(&tbl->slot_tbl_lock); | 
| 4633 | for (i = 0; i < max_slots; ++i) | 4655 | if (new) { | 
| 4656 | tbl->slots = new; | ||
| 4657 | tbl->max_slots = max_reqs; | ||
| 4658 | } | ||
| 4659 | for (i = 0; i < tbl->max_slots; ++i) | ||
| 4634 | tbl->slots[i].seq_nr = ivalue; | 4660 | tbl->slots[i].seq_nr = ivalue; | 
| 4635 | spin_unlock(&tbl->slot_tbl_lock); | 4661 | spin_unlock(&tbl->slot_tbl_lock); | 
| 4636 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | 4662 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | 
| @@ -4648,16 +4674,12 @@ static int nfs4_reset_slot_tables(struct nfs4_session *session) | |||
| 4648 | int status; | 4674 | int status; | 
| 4649 | 4675 | ||
| 4650 | status = nfs4_reset_slot_table(&session->fc_slot_table, | 4676 | status = nfs4_reset_slot_table(&session->fc_slot_table, | 
| 4651 | session->fc_attrs.max_reqs, | 4677 | session->fc_attrs.max_reqs, 1); | 
| 4652 | session->fc_slot_table.max_slots, | ||
| 4653 | 1); | ||
| 4654 | if (status) | 4678 | if (status) | 
| 4655 | return status; | 4679 | return status; | 
| 4656 | 4680 | ||
| 4657 | status = nfs4_reset_slot_table(&session->bc_slot_table, | 4681 | status = nfs4_reset_slot_table(&session->bc_slot_table, | 
| 4658 | session->bc_attrs.max_reqs, | 4682 | session->bc_attrs.max_reqs, 0); | 
| 4659 | session->bc_slot_table.max_slots, | ||
| 4660 | 0); | ||
| 4661 | return status; | 4683 | return status; | 
| 4662 | } | 4684 | } | 
| 4663 | 4685 | ||
| @@ -4798,16 +4820,14 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
| 4798 | args->fc_attrs.headerpadsz = 0; | 4820 | args->fc_attrs.headerpadsz = 0; | 
| 4799 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 4821 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 
| 4800 | args->fc_attrs.max_resp_sz = mxresp_sz; | 4822 | args->fc_attrs.max_resp_sz = mxresp_sz; | 
| 4801 | args->fc_attrs.max_resp_sz_cached = mxresp_sz; | ||
| 4802 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 4823 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 
| 4803 | args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; | 4824 | args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; | 
| 4804 | 4825 | ||
| 4805 | dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " | 4826 | dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " | 
| 4806 | "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", | 4827 | "max_ops=%u max_reqs=%u\n", | 
| 4807 | __func__, | 4828 | __func__, | 
| 4808 | args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz, | 4829 | args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz, | 
| 4809 | args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops, | 4830 | args->fc_attrs.max_ops, args->fc_attrs.max_reqs); | 
| 4810 | args->fc_attrs.max_reqs); | ||
| 4811 | 4831 | ||
| 4812 | /* Back channel attributes */ | 4832 | /* Back channel attributes */ | 
| 4813 | args->bc_attrs.headerpadsz = 0; | 4833 | args->bc_attrs.headerpadsz = 0; | 
| @@ -5016,7 +5036,16 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 5016 | &res, args.sa_cache_this, 1); | 5036 | &res, args.sa_cache_this, 1); | 
| 5017 | } | 5037 | } | 
| 5018 | 5038 | ||
| 5019 | void nfs41_sequence_call_done(struct rpc_task *task, void *data) | 5039 | static void nfs41_sequence_release(void *data) | 
| 5040 | { | ||
| 5041 | struct nfs_client *clp = (struct nfs_client *)data; | ||
| 5042 | |||
| 5043 | if (atomic_read(&clp->cl_count) > 1) | ||
| 5044 | nfs4_schedule_state_renewal(clp); | ||
| 5045 | nfs_put_client(clp); | ||
| 5046 | } | ||
| 5047 | |||
| 5048 | static void nfs41_sequence_call_done(struct rpc_task *task, void *data) | ||
| 5020 | { | 5049 | { | 
| 5021 | struct nfs_client *clp = (struct nfs_client *)data; | 5050 | struct nfs_client *clp = (struct nfs_client *)data; | 
| 5022 | 5051 | ||
| @@ -5024,6 +5053,8 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data) | |||
| 5024 | 5053 | ||
| 5025 | if (task->tk_status < 0) { | 5054 | if (task->tk_status < 0) { | 
| 5026 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | 5055 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | 
| 5056 | if (atomic_read(&clp->cl_count) == 1) | ||
| 5057 | goto out; | ||
| 5027 | 5058 | ||
| 5028 | if (_nfs4_async_handle_error(task, NULL, clp, NULL) | 5059 | if (_nfs4_async_handle_error(task, NULL, clp, NULL) | 
| 5029 | == -EAGAIN) { | 5060 | == -EAGAIN) { | 
| @@ -5032,7 +5063,7 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data) | |||
| 5032 | } | 5063 | } | 
| 5033 | } | 5064 | } | 
| 5034 | dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); | 5065 | dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); | 
| 5035 | 5066 | out: | |
| 5036 | kfree(task->tk_msg.rpc_argp); | 5067 | kfree(task->tk_msg.rpc_argp); | 
| 5037 | kfree(task->tk_msg.rpc_resp); | 5068 | kfree(task->tk_msg.rpc_resp); | 
| 5038 | 5069 | ||
| @@ -5057,6 +5088,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | |||
| 5057 | static const struct rpc_call_ops nfs41_sequence_ops = { | 5088 | static const struct rpc_call_ops nfs41_sequence_ops = { | 
| 5058 | .rpc_call_done = nfs41_sequence_call_done, | 5089 | .rpc_call_done = nfs41_sequence_call_done, | 
| 5059 | .rpc_call_prepare = nfs41_sequence_prepare, | 5090 | .rpc_call_prepare = nfs41_sequence_prepare, | 
| 5091 | .rpc_release = nfs41_sequence_release, | ||
| 5060 | }; | 5092 | }; | 
| 5061 | 5093 | ||
| 5062 | static int nfs41_proc_async_sequence(struct nfs_client *clp, | 5094 | static int nfs41_proc_async_sequence(struct nfs_client *clp, | 
| @@ -5069,12 +5101,14 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, | |||
| 5069 | .rpc_cred = cred, | 5101 | .rpc_cred = cred, | 
| 5070 | }; | 5102 | }; | 
| 5071 | 5103 | ||
| 5104 | if (!atomic_inc_not_zero(&clp->cl_count)) | ||
| 5105 | return -EIO; | ||
| 5072 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 5106 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 
| 5073 | if (!args) | ||
| 5074 | return -ENOMEM; | ||
| 5075 | res = kzalloc(sizeof(*res), GFP_KERNEL); | 5107 | res = kzalloc(sizeof(*res), GFP_KERNEL); | 
| 5076 | if (!res) { | 5108 | if (!args || !res) { | 
| 5077 | kfree(args); | 5109 | kfree(args); | 
| 5110 | kfree(res); | ||
| 5111 | nfs_put_client(clp); | ||
| 5078 | return -ENOMEM; | 5112 | return -ENOMEM; | 
| 5079 | } | 5113 | } | 
| 5080 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 5114 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 
