aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c103
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 }
423out: 425out:
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 */
3151static 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
3148static void nfs4_renew_done(struct rpc_task *task, void *data) 3160static 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
3165static const struct rpc_call_ops nfs4_renew_ops = { 3177static 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
3169int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) 3182int 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
3181int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) 3196int 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 */
4614static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, 4634static 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
5019void nfs41_sequence_call_done(struct rpc_task *task, void *data) 5039static 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
5048static 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 5066out:
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)
5057static const struct rpc_call_ops nfs41_sequence_ops = { 5088static 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
5062static int nfs41_proc_async_sequence(struct nfs_client *clp, 5094static 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;