|
@@ -249,19 +249,15 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
|
if (state == NULL)
|
|
|
break;
|
|
|
nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
- case -NFS4ERR_STALE_CLIENTID:
|
|
|
+ goto do_state_recovery;
|
|
|
case -NFS4ERR_STALE_STATEID:
|
|
|
- case -NFS4ERR_EXPIRED:
|
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
- ret = nfs4_wait_clnt_recover(clp);
|
|
|
- if (ret == 0)
|
|
|
- exception->retry = 1;
|
|
|
-#if !defined(CONFIG_NFS_V4_1)
|
|
|
- break;
|
|
|
-#else /* !defined(CONFIG_NFS_V4_1) */
|
|
|
- if (!nfs4_has_session(server->nfs_client))
|
|
|
+ if (state == NULL)
|
|
|
break;
|
|
|
- /* FALLTHROUGH */
|
|
|
+ nfs4_state_mark_reclaim_reboot(clp, state);
|
|
|
+ case -NFS4ERR_STALE_CLIENTID:
|
|
|
+ case -NFS4ERR_EXPIRED:
|
|
|
+ goto do_state_recovery;
|
|
|
+#if defined(CONFIG_NFS_V4_1)
|
|
|
case -NFS4ERR_BADSESSION:
|
|
|
case -NFS4ERR_BADSLOT:
|
|
|
case -NFS4ERR_BAD_HIGH_SLOT:
|
|
@@ -274,7 +270,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
|
nfs4_schedule_state_recovery(clp);
|
|
|
exception->retry = 1;
|
|
|
break;
|
|
|
-#endif /* !defined(CONFIG_NFS_V4_1) */
|
|
|
+#endif /* defined(CONFIG_NFS_V4_1) */
|
|
|
case -NFS4ERR_FILE_OPEN:
|
|
|
if (exception->timeout > HZ) {
|
|
|
/* We have retried a decent amount, time to
|
|
@@ -293,6 +289,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
|
}
|
|
|
/* We failed to handle the error */
|
|
|
return nfs4_map_errors(ret);
|
|
|
+do_state_recovery:
|
|
|
+ nfs4_schedule_state_recovery(clp);
|
|
|
+ ret = nfs4_wait_clnt_recover(clp);
|
|
|
+ if (ret == 0)
|
|
|
+ exception->retry = 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1658,6 +1660,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
|
|
|
status = PTR_ERR(state);
|
|
|
if (IS_ERR(state))
|
|
|
goto err_opendata_put;
|
|
|
+ if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0)
|
|
|
+ set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
|
|
|
nfs4_opendata_put(opendata);
|
|
|
nfs4_put_state_owner(sp);
|
|
|
*res = state;
|
|
@@ -3422,15 +3426,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
|
if (state == NULL)
|
|
|
break;
|
|
|
nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
- case -NFS4ERR_STALE_CLIENTID:
|
|
|
+ goto do_state_recovery;
|
|
|
case -NFS4ERR_STALE_STATEID:
|
|
|
+ if (state == NULL)
|
|
|
+ break;
|
|
|
+ nfs4_state_mark_reclaim_reboot(clp, state);
|
|
|
+ case -NFS4ERR_STALE_CLIENTID:
|
|
|
case -NFS4ERR_EXPIRED:
|
|
|
- rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
|
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
- if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
|
|
|
- rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
|
|
|
- task->tk_status = 0;
|
|
|
- return -EAGAIN;
|
|
|
+ goto do_state_recovery;
|
|
|
#if defined(CONFIG_NFS_V4_1)
|
|
|
case -NFS4ERR_BADSESSION:
|
|
|
case -NFS4ERR_BADSLOT:
|
|
@@ -3458,6 +3461,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
|
}
|
|
|
task->tk_status = nfs4_map_errors(task->tk_status);
|
|
|
return 0;
|
|
|
+do_state_recovery:
|
|
|
+ rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
|
|
|
+ nfs4_schedule_state_recovery(clp);
|
|
|
+ if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
|
|
|
+ rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
|
|
|
+ task->tk_status = 0;
|
|
|
+ return -EAGAIN;
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -4088,6 +4098,28 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {
|
|
|
.rpc_release = nfs4_lock_release,
|
|
|
};
|
|
|
|
|
|
+static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
|
|
|
+{
|
|
|
+ struct nfs_client *clp = server->nfs_client;
|
|
|
+ struct nfs4_state *state = lsp->ls_state;
|
|
|
+
|
|
|
+ switch (error) {
|
|
|
+ case -NFS4ERR_ADMIN_REVOKED:
|
|
|
+ case -NFS4ERR_BAD_STATEID:
|
|
|
+ case -NFS4ERR_EXPIRED:
|
|
|
+ if (new_lock_owner != 0 ||
|
|
|
+ (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
|
|
|
+ nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
+ lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
|
|
|
+ break;
|
|
|
+ case -NFS4ERR_STALE_STATEID:
|
|
|
+ if (new_lock_owner != 0 ||
|
|
|
+ (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
|
|
|
+ nfs4_state_mark_reclaim_reboot(clp, state);
|
|
|
+ lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
|
|
|
{
|
|
|
struct nfs4_lockdata *data;
|
|
@@ -4126,6 +4158,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
|
|
|
ret = nfs4_wait_for_completion_rpc_task(task);
|
|
|
if (ret == 0) {
|
|
|
ret = data->rpc_status;
|
|
|
+ if (ret)
|
|
|
+ nfs4_handle_setlk_error(data->server, data->lsp,
|
|
|
+ data->arg.new_lock_owner, ret);
|
|
|
} else
|
|
|
data->cancelled = 1;
|
|
|
rpc_put_task(task);
|
|
@@ -4181,8 +4216,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
|
|
|
{
|
|
|
struct nfs_inode *nfsi = NFS_I(state->inode);
|
|
|
unsigned char fl_flags = request->fl_flags;
|
|
|
- int status;
|
|
|
+ int status = -ENOLCK;
|
|
|
|
|
|
+ if ((fl_flags & FL_POSIX) &&
|
|
|
+ !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
|
|
|
+ goto out;
|
|
|
/* Is this a delegated open? */
|
|
|
status = nfs4_set_lock_state(state, request);
|
|
|
if (status != 0)
|