|
@@ -51,7 +51,6 @@
|
|
#include <linux/sunrpc/bc_xprt.h>
|
|
#include <linux/sunrpc/bc_xprt.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/utsname.h>
|
|
#include <linux/utsname.h>
|
|
-#include <linux/mm.h>
|
|
|
|
|
|
|
|
#include "nfs4_fs.h"
|
|
#include "nfs4_fs.h"
|
|
#include "delegation.h"
|
|
#include "delegation.h"
|
|
@@ -257,12 +256,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
case -NFS4ERR_OPENMODE:
|
|
case -NFS4ERR_OPENMODE:
|
|
if (state == NULL)
|
|
if (state == NULL)
|
|
break;
|
|
break;
|
|
- nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
|
- goto do_state_recovery;
|
|
|
|
|
|
+ nfs4_schedule_stateid_recovery(server, state);
|
|
|
|
+ goto wait_on_recovery;
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_EXPIRED:
|
|
- goto do_state_recovery;
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
|
|
+ goto wait_on_recovery;
|
|
#if defined(CONFIG_NFS_V4_1)
|
|
#if defined(CONFIG_NFS_V4_1)
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSLOT:
|
|
case -NFS4ERR_BADSLOT:
|
|
@@ -273,7 +273,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
case -NFS4ERR_SEQ_MISORDERED:
|
|
case -NFS4ERR_SEQ_MISORDERED:
|
|
dprintk("%s ERROR: %d Reset session\n", __func__,
|
|
dprintk("%s ERROR: %d Reset session\n", __func__,
|
|
errorcode);
|
|
errorcode);
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_session_recovery(clp->cl_session);
|
|
exception->retry = 1;
|
|
exception->retry = 1;
|
|
break;
|
|
break;
|
|
#endif /* defined(CONFIG_NFS_V4_1) */
|
|
#endif /* defined(CONFIG_NFS_V4_1) */
|
|
@@ -296,8 +296,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
}
|
|
}
|
|
/* We failed to handle the error */
|
|
/* We failed to handle the error */
|
|
return nfs4_map_errors(ret);
|
|
return nfs4_map_errors(ret);
|
|
-do_state_recovery:
|
|
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+wait_on_recovery:
|
|
ret = nfs4_wait_clnt_recover(clp);
|
|
ret = nfs4_wait_clnt_recover(clp);
|
|
if (ret == 0)
|
|
if (ret == 0)
|
|
exception->retry = 1;
|
|
exception->retry = 1;
|
|
@@ -436,8 +435,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
|
|
clp = res->sr_session->clp;
|
|
clp = res->sr_session->clp;
|
|
do_renew_lease(clp, timestamp);
|
|
do_renew_lease(clp, timestamp);
|
|
/* Check sequence flags */
|
|
/* Check sequence flags */
|
|
- if (atomic_read(&clp->cl_count) > 1)
|
|
|
|
- nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
|
|
|
|
|
|
+ if (res->sr_status_flags != 0)
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
break;
|
|
break;
|
|
case -NFS4ERR_DELAY:
|
|
case -NFS4ERR_DELAY:
|
|
/* The server detected a resend of the RPC call and
|
|
/* The server detected a resend of the RPC call and
|
|
@@ -1256,14 +1255,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
|
|
case -NFS4ERR_BAD_HIGH_SLOT:
|
|
case -NFS4ERR_BAD_HIGH_SLOT:
|
|
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
|
|
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
|
|
case -NFS4ERR_DEADSESSION:
|
|
case -NFS4ERR_DEADSESSION:
|
|
- nfs4_schedule_state_recovery(
|
|
|
|
- server->nfs_client);
|
|
|
|
|
|
+ nfs4_schedule_session_recovery(server->nfs_client->cl_session);
|
|
goto out;
|
|
goto out;
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_EXPIRED:
|
|
/* Don't recall a delegation if it was lost */
|
|
/* Don't recall a delegation if it was lost */
|
|
- nfs4_schedule_state_recovery(server->nfs_client);
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(server->nfs_client);
|
|
goto out;
|
|
goto out;
|
|
case -ERESTARTSYS:
|
|
case -ERESTARTSYS:
|
|
/*
|
|
/*
|
|
@@ -1272,7 +1270,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
|
|
*/
|
|
*/
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
- nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
|
|
|
|
|
+ nfs4_schedule_stateid_recovery(server, state);
|
|
case -EKEYEXPIRED:
|
|
case -EKEYEXPIRED:
|
|
/*
|
|
/*
|
|
* User RPCSEC_GSS context has expired.
|
|
* User RPCSEC_GSS context has expired.
|
|
@@ -1588,7 +1586,7 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
|
|
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
|
|
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
|
|
!test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
|
|
!test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
|
|
break;
|
|
break;
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_state_manager(clp);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
return ret;
|
|
return ret;
|
|
@@ -3179,7 +3177,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)
|
|
if (task->tk_status < 0) {
|
|
if (task->tk_status < 0) {
|
|
/* Unless we're shutting down, schedule state recovery! */
|
|
/* Unless we're shutting down, schedule state recovery! */
|
|
if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0)
|
|
if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0)
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
do_renew_lease(clp, timestamp);
|
|
do_renew_lease(clp, timestamp);
|
|
@@ -3262,7 +3260,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,
|
|
spages = pages;
|
|
spages = pages;
|
|
|
|
|
|
do {
|
|
do {
|
|
- len = min(PAGE_CACHE_SIZE, buflen);
|
|
|
|
|
|
+ len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
|
|
newpage = alloc_page(GFP_KERNEL);
|
|
newpage = alloc_page(GFP_KERNEL);
|
|
|
|
|
|
if (newpage == NULL)
|
|
if (newpage == NULL)
|
|
@@ -3504,12 +3502,13 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
case -NFS4ERR_OPENMODE:
|
|
case -NFS4ERR_OPENMODE:
|
|
if (state == NULL)
|
|
if (state == NULL)
|
|
break;
|
|
break;
|
|
- nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
|
- goto do_state_recovery;
|
|
|
|
|
|
+ nfs4_schedule_stateid_recovery(server, state);
|
|
|
|
+ goto wait_on_recovery;
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_EXPIRED:
|
|
- goto do_state_recovery;
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
|
|
+ goto wait_on_recovery;
|
|
#if defined(CONFIG_NFS_V4_1)
|
|
#if defined(CONFIG_NFS_V4_1)
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSLOT:
|
|
case -NFS4ERR_BADSLOT:
|
|
@@ -3520,7 +3519,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
case -NFS4ERR_SEQ_MISORDERED:
|
|
case -NFS4ERR_SEQ_MISORDERED:
|
|
dprintk("%s ERROR %d, Reset session\n", __func__,
|
|
dprintk("%s ERROR %d, Reset session\n", __func__,
|
|
task->tk_status);
|
|
task->tk_status);
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_session_recovery(clp->cl_session);
|
|
task->tk_status = 0;
|
|
task->tk_status = 0;
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
@@ -3537,9 +3536,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
}
|
|
}
|
|
task->tk_status = nfs4_map_errors(task->tk_status);
|
|
task->tk_status = nfs4_map_errors(task->tk_status);
|
|
return 0;
|
|
return 0;
|
|
-do_state_recovery:
|
|
|
|
|
|
+wait_on_recovery:
|
|
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
|
|
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
|
|
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
|
|
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
|
|
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
|
|
task->tk_status = 0;
|
|
task->tk_status = 0;
|
|
@@ -4150,7 +4148,7 @@ static void nfs4_lock_release(void *calldata)
|
|
task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
|
|
task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
|
|
data->arg.lock_seqid);
|
|
data->arg.lock_seqid);
|
|
if (!IS_ERR(task))
|
|
if (!IS_ERR(task))
|
|
- rpc_put_task(task);
|
|
|
|
|
|
+ rpc_put_task_async(task);
|
|
dprintk("%s: cancelling lock!\n", __func__);
|
|
dprintk("%s: cancelling lock!\n", __func__);
|
|
} else
|
|
} else
|
|
nfs_free_seqid(data->arg.lock_seqid);
|
|
nfs_free_seqid(data->arg.lock_seqid);
|
|
@@ -4174,23 +4172,18 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {
|
|
|
|
|
|
static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
|
|
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) {
|
|
switch (error) {
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
- case -NFS4ERR_EXPIRED:
|
|
|
|
|
|
+ lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
|
|
if (new_lock_owner != 0 ||
|
|
if (new_lock_owner != 0 ||
|
|
(lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
|
|
(lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
|
|
- nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
|
- lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
|
|
|
|
|
|
+ nfs4_schedule_stateid_recovery(server, lsp->ls_state);
|
|
break;
|
|
break;
|
|
case -NFS4ERR_STALE_STATEID:
|
|
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;
|
|
lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
|
|
|
|
+ case -NFS4ERR_EXPIRED:
|
|
|
|
+ nfs4_schedule_lease_recovery(server->nfs_client);
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4406,12 +4399,14 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
case -NFS4ERR_STALE_STATEID:
|
|
|
|
+ nfs4_schedule_lease_recovery(server->nfs_client);
|
|
|
|
+ goto out;
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSESSION:
|
|
case -NFS4ERR_BADSLOT:
|
|
case -NFS4ERR_BADSLOT:
|
|
case -NFS4ERR_BAD_HIGH_SLOT:
|
|
case -NFS4ERR_BAD_HIGH_SLOT:
|
|
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
|
|
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
|
|
case -NFS4ERR_DEADSESSION:
|
|
case -NFS4ERR_DEADSESSION:
|
|
- nfs4_schedule_state_recovery(server->nfs_client);
|
|
|
|
|
|
+ nfs4_schedule_session_recovery(server->nfs_client->cl_session);
|
|
goto out;
|
|
goto out;
|
|
case -ERESTARTSYS:
|
|
case -ERESTARTSYS:
|
|
/*
|
|
/*
|
|
@@ -4421,7 +4416,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
case -NFS4ERR_BAD_STATEID:
|
|
case -NFS4ERR_OPENMODE:
|
|
case -NFS4ERR_OPENMODE:
|
|
- nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
|
|
|
|
|
+ nfs4_schedule_stateid_recovery(server, state);
|
|
err = 0;
|
|
err = 0;
|
|
goto out;
|
|
goto out;
|
|
case -EKEYEXPIRED:
|
|
case -EKEYEXPIRED:
|
|
@@ -5028,10 +5023,20 @@ int nfs4_proc_create_session(struct nfs_client *clp)
|
|
int status;
|
|
int status;
|
|
unsigned *ptr;
|
|
unsigned *ptr;
|
|
struct nfs4_session *session = clp->cl_session;
|
|
struct nfs4_session *session = clp->cl_session;
|
|
|
|
+ long timeout = 0;
|
|
|
|
+ int err;
|
|
|
|
|
|
dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
|
|
dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
|
|
|
|
|
|
- status = _nfs4_proc_create_session(clp);
|
|
|
|
|
|
+ do {
|
|
|
|
+ status = _nfs4_proc_create_session(clp);
|
|
|
|
+ if (status == -NFS4ERR_DELAY) {
|
|
|
|
+ err = nfs4_delay(clp->cl_rpcclient, &timeout);
|
|
|
|
+ if (err)
|
|
|
|
+ status = err;
|
|
|
|
+ }
|
|
|
|
+ } while (status == -NFS4ERR_DELAY);
|
|
|
|
+
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
@@ -5140,7 +5145,7 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
default:
|
|
default:
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -5227,7 +5232,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
|
|
if (IS_ERR(task))
|
|
if (IS_ERR(task))
|
|
ret = PTR_ERR(task);
|
|
ret = PTR_ERR(task);
|
|
else
|
|
else
|
|
- rpc_put_task(task);
|
|
|
|
|
|
+ rpc_put_task_async(task);
|
|
dprintk("<-- %s status=%d\n", __func__, ret);
|
|
dprintk("<-- %s status=%d\n", __func__, ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -5243,8 +5248,13 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
ret = rpc_wait_for_completion_task(task);
|
|
ret = rpc_wait_for_completion_task(task);
|
|
- if (!ret)
|
|
|
|
|
|
+ if (!ret) {
|
|
|
|
+ struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;
|
|
|
|
+
|
|
|
|
+ if (task->tk_status == 0)
|
|
|
|
+ nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
|
|
ret = task->tk_status;
|
|
ret = task->tk_status;
|
|
|
|
+ }
|
|
rpc_put_task(task);
|
|
rpc_put_task(task);
|
|
out:
|
|
out:
|
|
dprintk("<-- %s status=%d\n", __func__, ret);
|
|
dprintk("<-- %s status=%d\n", __func__, ret);
|
|
@@ -5281,7 +5291,7 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
default:
|
|
default:
|
|
- nfs4_schedule_state_recovery(clp);
|
|
|
|
|
|
+ nfs4_schedule_lease_recovery(clp);
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -5349,6 +5359,9 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
|
|
status = PTR_ERR(task);
|
|
status = PTR_ERR(task);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
+ status = nfs4_wait_for_completion_rpc_task(task);
|
|
|
|
+ if (status == 0)
|
|
|
|
+ status = task->tk_status;
|
|
rpc_put_task(task);
|
|
rpc_put_task(task);
|
|
return 0;
|
|
return 0;
|
|
out:
|
|
out:
|