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.c196
1 files changed, 135 insertions, 61 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 198d51d17c13..638067007c65 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -39,6 +39,7 @@
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/errno.h> 40#include <linux/errno.h>
41#include <linux/string.h> 41#include <linux/string.h>
42#include <linux/slab.h>
42#include <linux/sunrpc/clnt.h> 43#include <linux/sunrpc/clnt.h>
43#include <linux/nfs.h> 44#include <linux/nfs.h>
44#include <linux/nfs4.h> 45#include <linux/nfs4.h>
@@ -249,19 +250,15 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
249 if (state == NULL) 250 if (state == NULL)
250 break; 251 break;
251 nfs4_state_mark_reclaim_nograce(clp, state); 252 nfs4_state_mark_reclaim_nograce(clp, state);
252 case -NFS4ERR_STALE_CLIENTID: 253 goto do_state_recovery;
253 case -NFS4ERR_STALE_STATEID: 254 case -NFS4ERR_STALE_STATEID:
254 case -NFS4ERR_EXPIRED: 255 if (state == NULL)
255 nfs4_schedule_state_recovery(clp);
256 ret = nfs4_wait_clnt_recover(clp);
257 if (ret == 0)
258 exception->retry = 1;
259#if !defined(CONFIG_NFS_V4_1)
260 break;
261#else /* !defined(CONFIG_NFS_V4_1) */
262 if (!nfs4_has_session(server->nfs_client))
263 break; 256 break;
264 /* FALLTHROUGH */ 257 nfs4_state_mark_reclaim_reboot(clp, state);
258 case -NFS4ERR_STALE_CLIENTID:
259 case -NFS4ERR_EXPIRED:
260 goto do_state_recovery;
261#if defined(CONFIG_NFS_V4_1)
265 case -NFS4ERR_BADSESSION: 262 case -NFS4ERR_BADSESSION:
266 case -NFS4ERR_BADSLOT: 263 case -NFS4ERR_BADSLOT:
267 case -NFS4ERR_BAD_HIGH_SLOT: 264 case -NFS4ERR_BAD_HIGH_SLOT:
@@ -274,7 +271,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
274 nfs4_schedule_state_recovery(clp); 271 nfs4_schedule_state_recovery(clp);
275 exception->retry = 1; 272 exception->retry = 1;
276 break; 273 break;
277#endif /* !defined(CONFIG_NFS_V4_1) */ 274#endif /* defined(CONFIG_NFS_V4_1) */
278 case -NFS4ERR_FILE_OPEN: 275 case -NFS4ERR_FILE_OPEN:
279 if (exception->timeout > HZ) { 276 if (exception->timeout > HZ) {
280 /* We have retried a decent amount, time to 277 /* We have retried a decent amount, time to
@@ -285,6 +282,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
285 } 282 }
286 case -NFS4ERR_GRACE: 283 case -NFS4ERR_GRACE:
287 case -NFS4ERR_DELAY: 284 case -NFS4ERR_DELAY:
285 case -EKEYEXPIRED:
288 ret = nfs4_delay(server->client, &exception->timeout); 286 ret = nfs4_delay(server->client, &exception->timeout);
289 if (ret != 0) 287 if (ret != 0)
290 break; 288 break;
@@ -293,6 +291,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
293 } 291 }
294 /* We failed to handle the error */ 292 /* We failed to handle the error */
295 return nfs4_map_errors(ret); 293 return nfs4_map_errors(ret);
294do_state_recovery:
295 nfs4_schedule_state_recovery(clp);
296 ret = nfs4_wait_clnt_recover(clp);
297 if (ret == 0)
298 exception->retry = 1;
299 return ret;
296} 300}
297 301
298 302
@@ -416,7 +420,8 @@ static void nfs41_sequence_done(struct nfs_client *clp,
416 clp->cl_last_renewal = timestamp; 420 clp->cl_last_renewal = timestamp;
417 spin_unlock(&clp->cl_lock); 421 spin_unlock(&clp->cl_lock);
418 /* Check sequence flags */ 422 /* Check sequence flags */
419 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 423 if (atomic_read(&clp->cl_count) > 1)
424 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
420 } 425 }
421out: 426out:
422 /* The session may be reset by one of the error handlers. */ 427 /* The session may be reset by one of the error handlers. */
@@ -722,8 +727,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
722 p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); 727 p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
723 if (p->o_arg.seqid == NULL) 728 if (p->o_arg.seqid == NULL)
724 goto err_free; 729 goto err_free;
725 p->path.mnt = mntget(path->mnt); 730 path_get(path);
726 p->path.dentry = dget(path->dentry); 731 p->path = *path;
727 p->dir = parent; 732 p->dir = parent;
728 p->owner = sp; 733 p->owner = sp;
729 atomic_inc(&sp->so_count); 734 atomic_inc(&sp->so_count);
@@ -1161,7 +1166,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
1161 int err; 1166 int err;
1162 do { 1167 do {
1163 err = _nfs4_do_open_reclaim(ctx, state); 1168 err = _nfs4_do_open_reclaim(ctx, state);
1164 if (err != -NFS4ERR_DELAY) 1169 if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
1165 break; 1170 break;
1166 nfs4_handle_exception(server, err, &exception); 1171 nfs4_handle_exception(server, err, &exception);
1167 } while (exception.retry); 1172 } while (exception.retry);
@@ -1518,6 +1523,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
1518 nfs_post_op_update_inode(dir, o_res->dir_attr); 1523 nfs_post_op_update_inode(dir, o_res->dir_attr);
1519 } else 1524 } else
1520 nfs_refresh_inode(dir, o_res->dir_attr); 1525 nfs_refresh_inode(dir, o_res->dir_attr);
1526 if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
1527 server->caps &= ~NFS_CAP_POSIX_LOCK;
1521 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { 1528 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
1522 status = _nfs4_proc_open_confirm(data); 1529 status = _nfs4_proc_open_confirm(data);
1523 if (status != 0) 1530 if (status != 0)
@@ -1580,6 +1587,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
1580 goto out; 1587 goto out;
1581 case -NFS4ERR_GRACE: 1588 case -NFS4ERR_GRACE:
1582 case -NFS4ERR_DELAY: 1589 case -NFS4ERR_DELAY:
1590 case -EKEYEXPIRED:
1583 nfs4_handle_exception(server, err, &exception); 1591 nfs4_handle_exception(server, err, &exception);
1584 err = 0; 1592 err = 0;
1585 } 1593 }
@@ -1658,6 +1666,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
1658 status = PTR_ERR(state); 1666 status = PTR_ERR(state);
1659 if (IS_ERR(state)) 1667 if (IS_ERR(state))
1660 goto err_opendata_put; 1668 goto err_opendata_put;
1669 if (server->caps & NFS_CAP_POSIX_LOCK)
1670 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
1661 nfs4_opendata_put(opendata); 1671 nfs4_opendata_put(opendata);
1662 nfs4_put_state_owner(sp); 1672 nfs4_put_state_owner(sp);
1663 *res = state; 1673 *res = state;
@@ -1940,8 +1950,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
1940 calldata->res.seqid = calldata->arg.seqid; 1950 calldata->res.seqid = calldata->arg.seqid;
1941 calldata->res.server = server; 1951 calldata->res.server = server;
1942 calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; 1952 calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
1943 calldata->path.mnt = mntget(path->mnt); 1953 path_get(path);
1944 calldata->path.dentry = dget(path->dentry); 1954 calldata->path = *path;
1945 1955
1946 msg.rpc_argp = &calldata->arg, 1956 msg.rpc_argp = &calldata->arg,
1947 msg.rpc_resp = &calldata->res, 1957 msg.rpc_resp = &calldata->res,
@@ -2060,8 +2070,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
2060 case -EDQUOT: 2070 case -EDQUOT:
2061 case -ENOSPC: 2071 case -ENOSPC:
2062 case -EROFS: 2072 case -EROFS:
2063 lookup_instantiate_filp(nd, (struct dentry *)state, NULL); 2073 return PTR_ERR(state);
2064 return 1;
2065 default: 2074 default:
2066 goto out_drop; 2075 goto out_drop;
2067 } 2076 }
@@ -3141,10 +3150,19 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
3141 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special 3150 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
3142 * standalone procedure for queueing an asynchronous RENEW. 3151 * standalone procedure for queueing an asynchronous RENEW.
3143 */ 3152 */
3153static void nfs4_renew_release(void *data)
3154{
3155 struct nfs_client *clp = data;
3156
3157 if (atomic_read(&clp->cl_count) > 1)
3158 nfs4_schedule_state_renewal(clp);
3159 nfs_put_client(clp);
3160}
3161
3144static void nfs4_renew_done(struct rpc_task *task, void *data) 3162static void nfs4_renew_done(struct rpc_task *task, void *data)
3145{ 3163{
3146 struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp; 3164 struct nfs_client *clp = data;
3147 unsigned long timestamp = (unsigned long)data; 3165 unsigned long timestamp = task->tk_start;
3148 3166
3149 if (task->tk_status < 0) { 3167 if (task->tk_status < 0) {
3150 /* Unless we're shutting down, schedule state recovery! */ 3168 /* Unless we're shutting down, schedule state recovery! */
@@ -3160,6 +3178,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
3160 3178
3161static const struct rpc_call_ops nfs4_renew_ops = { 3179static const struct rpc_call_ops nfs4_renew_ops = {
3162 .rpc_call_done = nfs4_renew_done, 3180 .rpc_call_done = nfs4_renew_done,
3181 .rpc_release = nfs4_renew_release,
3163}; 3182};
3164 3183
3165int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) 3184int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3170,8 +3189,10 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
3170 .rpc_cred = cred, 3189 .rpc_cred = cred,
3171 }; 3190 };
3172 3191
3192 if (!atomic_inc_not_zero(&clp->cl_count))
3193 return -EIO;
3173 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, 3194 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
3174 &nfs4_renew_ops, (void *)jiffies); 3195 &nfs4_renew_ops, clp);
3175} 3196}
3176 3197
3177int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) 3198int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3422,15 +3443,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3422 if (state == NULL) 3443 if (state == NULL)
3423 break; 3444 break;
3424 nfs4_state_mark_reclaim_nograce(clp, state); 3445 nfs4_state_mark_reclaim_nograce(clp, state);
3425 case -NFS4ERR_STALE_CLIENTID: 3446 goto do_state_recovery;
3426 case -NFS4ERR_STALE_STATEID: 3447 case -NFS4ERR_STALE_STATEID:
3448 if (state == NULL)
3449 break;
3450 nfs4_state_mark_reclaim_reboot(clp, state);
3451 case -NFS4ERR_STALE_CLIENTID:
3427 case -NFS4ERR_EXPIRED: 3452 case -NFS4ERR_EXPIRED:
3428 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3453 goto do_state_recovery;
3429 nfs4_schedule_state_recovery(clp);
3430 if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
3431 rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
3432 task->tk_status = 0;
3433 return -EAGAIN;
3434#if defined(CONFIG_NFS_V4_1) 3454#if defined(CONFIG_NFS_V4_1)
3435 case -NFS4ERR_BADSESSION: 3455 case -NFS4ERR_BADSESSION:
3436 case -NFS4ERR_BADSLOT: 3456 case -NFS4ERR_BADSLOT:
@@ -3449,6 +3469,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3449 if (server) 3469 if (server)
3450 nfs_inc_server_stats(server, NFSIOS_DELAY); 3470 nfs_inc_server_stats(server, NFSIOS_DELAY);
3451 case -NFS4ERR_GRACE: 3471 case -NFS4ERR_GRACE:
3472 case -EKEYEXPIRED:
3452 rpc_delay(task, NFS4_POLL_RETRY_MAX); 3473 rpc_delay(task, NFS4_POLL_RETRY_MAX);
3453 task->tk_status = 0; 3474 task->tk_status = 0;
3454 return -EAGAIN; 3475 return -EAGAIN;
@@ -3458,6 +3479,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3458 } 3479 }
3459 task->tk_status = nfs4_map_errors(task->tk_status); 3480 task->tk_status = nfs4_map_errors(task->tk_status);
3460 return 0; 3481 return 0;
3482do_state_recovery:
3483 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
3484 nfs4_schedule_state_recovery(clp);
3485 if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
3486 rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
3487 task->tk_status = 0;
3488 return -EAGAIN;
3461} 3489}
3462 3490
3463static int 3491static int
@@ -3554,6 +3582,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
3554 case -NFS4ERR_RESOURCE: 3582 case -NFS4ERR_RESOURCE:
3555 /* The IBM lawyers misread another document! */ 3583 /* The IBM lawyers misread another document! */
3556 case -NFS4ERR_DELAY: 3584 case -NFS4ERR_DELAY:
3585 case -EKEYEXPIRED:
3557 err = nfs4_delay(clp->cl_rpcclient, &timeout); 3586 err = nfs4_delay(clp->cl_rpcclient, &timeout);
3558 } 3587 }
3559 } while (err == 0); 3588 } while (err == 0);
@@ -4088,6 +4117,28 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {
4088 .rpc_release = nfs4_lock_release, 4117 .rpc_release = nfs4_lock_release,
4089}; 4118};
4090 4119
4120static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
4121{
4122 struct nfs_client *clp = server->nfs_client;
4123 struct nfs4_state *state = lsp->ls_state;
4124
4125 switch (error) {
4126 case -NFS4ERR_ADMIN_REVOKED:
4127 case -NFS4ERR_BAD_STATEID:
4128 case -NFS4ERR_EXPIRED:
4129 if (new_lock_owner != 0 ||
4130 (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
4131 nfs4_state_mark_reclaim_nograce(clp, state);
4132 lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
4133 break;
4134 case -NFS4ERR_STALE_STATEID:
4135 if (new_lock_owner != 0 ||
4136 (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
4137 nfs4_state_mark_reclaim_reboot(clp, state);
4138 lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
4139 };
4140}
4141
4091static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) 4142static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
4092{ 4143{
4093 struct nfs4_lockdata *data; 4144 struct nfs4_lockdata *data;
@@ -4126,6 +4177,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
4126 ret = nfs4_wait_for_completion_rpc_task(task); 4177 ret = nfs4_wait_for_completion_rpc_task(task);
4127 if (ret == 0) { 4178 if (ret == 0) {
4128 ret = data->rpc_status; 4179 ret = data->rpc_status;
4180 if (ret)
4181 nfs4_handle_setlk_error(data->server, data->lsp,
4182 data->arg.new_lock_owner, ret);
4129 } else 4183 } else
4130 data->cancelled = 1; 4184 data->cancelled = 1;
4131 rpc_put_task(task); 4185 rpc_put_task(task);
@@ -4144,7 +4198,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
4144 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) 4198 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
4145 return 0; 4199 return 0;
4146 err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); 4200 err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
4147 if (err != -NFS4ERR_DELAY) 4201 if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
4148 break; 4202 break;
4149 nfs4_handle_exception(server, err, &exception); 4203 nfs4_handle_exception(server, err, &exception);
4150 } while (exception.retry); 4204 } while (exception.retry);
@@ -4169,6 +4223,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
4169 goto out; 4223 goto out;
4170 case -NFS4ERR_GRACE: 4224 case -NFS4ERR_GRACE:
4171 case -NFS4ERR_DELAY: 4225 case -NFS4ERR_DELAY:
4226 case -EKEYEXPIRED:
4172 nfs4_handle_exception(server, err, &exception); 4227 nfs4_handle_exception(server, err, &exception);
4173 err = 0; 4228 err = 0;
4174 } 4229 }
@@ -4181,8 +4236,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
4181{ 4236{
4182 struct nfs_inode *nfsi = NFS_I(state->inode); 4237 struct nfs_inode *nfsi = NFS_I(state->inode);
4183 unsigned char fl_flags = request->fl_flags; 4238 unsigned char fl_flags = request->fl_flags;
4184 int status; 4239 int status = -ENOLCK;
4185 4240
4241 if ((fl_flags & FL_POSIX) &&
4242 !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
4243 goto out;
4186 /* Is this a delegated open? */ 4244 /* Is this a delegated open? */
4187 status = nfs4_set_lock_state(state, request); 4245 status = nfs4_set_lock_state(state, request);
4188 if (status != 0) 4246 if (status != 0)
@@ -4317,6 +4375,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
4317 err = 0; 4375 err = 0;
4318 goto out; 4376 goto out;
4319 case -NFS4ERR_DELAY: 4377 case -NFS4ERR_DELAY:
4378 case -EKEYEXPIRED:
4320 break; 4379 break;
4321 } 4380 }
4322 err = nfs4_handle_exception(server, err, &exception); 4381 err = nfs4_handle_exception(server, err, &exception);
@@ -4462,7 +4521,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4462 4521
4463 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); 4522 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4464 4523
4465 if (status != NFS4ERR_CLID_INUSE) 4524 if (status != -NFS4ERR_CLID_INUSE)
4466 break; 4525 break;
4467 4526
4468 if (signalled()) 4527 if (signalled())
@@ -4516,6 +4575,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
4516 switch (task->tk_status) { 4575 switch (task->tk_status) {
4517 case -NFS4ERR_DELAY: 4576 case -NFS4ERR_DELAY:
4518 case -NFS4ERR_GRACE: 4577 case -NFS4ERR_GRACE:
4578 case -EKEYEXPIRED:
4519 dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); 4579 dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
4520 rpc_delay(task, NFS4_POLL_RETRY_MIN); 4580 rpc_delay(task, NFS4_POLL_RETRY_MIN);
4521 task->tk_status = 0; 4581 task->tk_status = 0;
@@ -4573,26 +4633,32 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4573/* 4633/*
4574 * Reset a slot table 4634 * Reset a slot table
4575 */ 4635 */
4576static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, 4636static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
4577 int old_max_slots, int ivalue) 4637 int ivalue)
4578{ 4638{
4639 struct nfs4_slot *new = NULL;
4579 int i; 4640 int i;
4580 int ret = 0; 4641 int ret = 0;
4581 4642
4582 dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl); 4643 dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
4644 max_reqs, tbl->max_slots);
4583 4645
4584 /* 4646 /* Does the newly negotiated max_reqs match the existing slot table? */
4585 * Until we have dynamic slot table adjustment, insist 4647 if (max_reqs != tbl->max_slots) {
4586 * upon the same slot table size 4648 ret = -ENOMEM;
4587 */ 4649 new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
4588 if (max_slots != old_max_slots) { 4650 GFP_KERNEL);
4589 dprintk("%s reset slot table does't match old\n", 4651 if (!new)
4590 __func__); 4652 goto out;
4591 ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */ 4653 ret = 0;
4592 goto out; 4654 kfree(tbl->slots);
4593 } 4655 }
4594 spin_lock(&tbl->slot_tbl_lock); 4656 spin_lock(&tbl->slot_tbl_lock);
4595 for (i = 0; i < max_slots; ++i) 4657 if (new) {
4658 tbl->slots = new;
4659 tbl->max_slots = max_reqs;
4660 }
4661 for (i = 0; i < tbl->max_slots; ++i)
4596 tbl->slots[i].seq_nr = ivalue; 4662 tbl->slots[i].seq_nr = ivalue;
4597 spin_unlock(&tbl->slot_tbl_lock); 4663 spin_unlock(&tbl->slot_tbl_lock);
4598 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, 4664 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
@@ -4610,16 +4676,12 @@ static int nfs4_reset_slot_tables(struct nfs4_session *session)
4610 int status; 4676 int status;
4611 4677
4612 status = nfs4_reset_slot_table(&session->fc_slot_table, 4678 status = nfs4_reset_slot_table(&session->fc_slot_table,
4613 session->fc_attrs.max_reqs, 4679 session->fc_attrs.max_reqs, 1);
4614 session->fc_slot_table.max_slots,
4615 1);
4616 if (status) 4680 if (status)
4617 return status; 4681 return status;
4618 4682
4619 status = nfs4_reset_slot_table(&session->bc_slot_table, 4683 status = nfs4_reset_slot_table(&session->bc_slot_table,
4620 session->bc_attrs.max_reqs, 4684 session->bc_attrs.max_reqs, 0);
4621 session->bc_slot_table.max_slots,
4622 0);
4623 return status; 4685 return status;
4624} 4686}
4625 4687
@@ -4760,16 +4822,14 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
4760 args->fc_attrs.headerpadsz = 0; 4822 args->fc_attrs.headerpadsz = 0;
4761 args->fc_attrs.max_rqst_sz = mxrqst_sz; 4823 args->fc_attrs.max_rqst_sz = mxrqst_sz;
4762 args->fc_attrs.max_resp_sz = mxresp_sz; 4824 args->fc_attrs.max_resp_sz = mxresp_sz;
4763 args->fc_attrs.max_resp_sz_cached = mxresp_sz;
4764 args->fc_attrs.max_ops = NFS4_MAX_OPS; 4825 args->fc_attrs.max_ops = NFS4_MAX_OPS;
4765 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; 4826 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
4766 4827
4767 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " 4828 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
4768 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", 4829 "max_ops=%u max_reqs=%u\n",
4769 __func__, 4830 __func__,
4770 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz, 4831 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
4771 args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops, 4832 args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
4772 args->fc_attrs.max_reqs);
4773 4833
4774 /* Back channel attributes */ 4834 /* Back channel attributes */
4775 args->bc_attrs.headerpadsz = 0; 4835 args->bc_attrs.headerpadsz = 0;
@@ -4978,7 +5038,16 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
4978 &res, args.sa_cache_this, 1); 5038 &res, args.sa_cache_this, 1);
4979} 5039}
4980 5040
4981void nfs41_sequence_call_done(struct rpc_task *task, void *data) 5041static void nfs41_sequence_release(void *data)
5042{
5043 struct nfs_client *clp = (struct nfs_client *)data;
5044
5045 if (atomic_read(&clp->cl_count) > 1)
5046 nfs4_schedule_state_renewal(clp);
5047 nfs_put_client(clp);
5048}
5049
5050static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
4982{ 5051{
4983 struct nfs_client *clp = (struct nfs_client *)data; 5052 struct nfs_client *clp = (struct nfs_client *)data;
4984 5053
@@ -4986,6 +5055,8 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
4986 5055
4987 if (task->tk_status < 0) { 5056 if (task->tk_status < 0) {
4988 dprintk("%s ERROR %d\n", __func__, task->tk_status); 5057 dprintk("%s ERROR %d\n", __func__, task->tk_status);
5058 if (atomic_read(&clp->cl_count) == 1)
5059 goto out;
4989 5060
4990 if (_nfs4_async_handle_error(task, NULL, clp, NULL) 5061 if (_nfs4_async_handle_error(task, NULL, clp, NULL)
4991 == -EAGAIN) { 5062 == -EAGAIN) {
@@ -4994,7 +5065,7 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
4994 } 5065 }
4995 } 5066 }
4996 dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); 5067 dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
4997 5068out:
4998 kfree(task->tk_msg.rpc_argp); 5069 kfree(task->tk_msg.rpc_argp);
4999 kfree(task->tk_msg.rpc_resp); 5070 kfree(task->tk_msg.rpc_resp);
5000 5071
@@ -5019,6 +5090,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
5019static const struct rpc_call_ops nfs41_sequence_ops = { 5090static const struct rpc_call_ops nfs41_sequence_ops = {
5020 .rpc_call_done = nfs41_sequence_call_done, 5091 .rpc_call_done = nfs41_sequence_call_done,
5021 .rpc_call_prepare = nfs41_sequence_prepare, 5092 .rpc_call_prepare = nfs41_sequence_prepare,
5093 .rpc_release = nfs41_sequence_release,
5022}; 5094};
5023 5095
5024static int nfs41_proc_async_sequence(struct nfs_client *clp, 5096static int nfs41_proc_async_sequence(struct nfs_client *clp,
@@ -5031,12 +5103,14 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
5031 .rpc_cred = cred, 5103 .rpc_cred = cred,
5032 }; 5104 };
5033 5105
5106 if (!atomic_inc_not_zero(&clp->cl_count))
5107 return -EIO;
5034 args = kzalloc(sizeof(*args), GFP_KERNEL); 5108 args = kzalloc(sizeof(*args), GFP_KERNEL);
5035 if (!args)
5036 return -ENOMEM;
5037 res = kzalloc(sizeof(*res), GFP_KERNEL); 5109 res = kzalloc(sizeof(*res), GFP_KERNEL);
5038 if (!res) { 5110 if (!args || !res) {
5039 kfree(args); 5111 kfree(args);
5112 kfree(res);
5113 nfs_put_client(clp);
5040 return -ENOMEM; 5114 return -ENOMEM;
5041 } 5115 }
5042 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 5116 res->sr_slotid = NFS4_MAX_SLOT_TABLE;