diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 84d83be25a98..eda74c42d552 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. */ |
@@ -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 | } |
@@ -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,13 @@ 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 | nfs_put_client(clp); | ||
5078 | return -ENOMEM; | 5111 | return -ENOMEM; |
5079 | } | 5112 | } |
5080 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 5113 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; |