nfs_opendir_cb should not queue a READDIR on error

Explanation of the bug:
- nfs_opendir_cb() queues a READDIR when it receives RPC_STATUS_ERROR.
- rpc_purge_all_pdus() explicitly says that no further pdus should be
  queued when rpc_purge_all_pdus() is invoked and the outqueue is being
  cleared.
- Since nfs_opendir_cb() is called in rpc_purge_all_pdus() with
  status=RPC_STATUS_ERROR, this invariant is broken.

Fix:
- Invoke check_nfs3_error() which will invoke the appropriate
  callback with the right error.
- Disallow queueing a request in the if block
libnfs-4.0.0-vitalif
Shreyas Siravara 2018-04-23 12:33:29 -07:00
parent 8b064bf971
commit df72323c46
1 changed files with 8 additions and 11 deletions

View File

@ -2714,8 +2714,14 @@ nfs3_opendir_cb(struct rpc_context *rpc, int status, void *command_data,
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR ||
(status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP)) {
if (check_nfs3_error(nfs, status, data, command_data)) {
nfs_free_nfsdir(nfsdir);
data->continue_data = NULL;
free_nfs_cb_data(data);
return;
}
if (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) {
READDIR3args args;
args.dir.data.data_len = data->fh.len;
@ -2738,15 +2744,6 @@ nfs3_opendir_cb(struct rpc_context *rpc, int status, void *command_data,
return;
}
if (status == RPC_STATUS_CANCEL) {
data->cb(-EINTR, nfs, "Command was cancelled",
data->private_data);
nfs_free_nfsdir(nfsdir);
data->continue_data = NULL;
free_nfs_cb_data(data);
return;
}
if (res->status != NFS3_OK) {
nfs_set_error(nfs, "NFS: READDIRPLUS of %s failed with "
"%s(%d)", data->saved_path,