nfs_opendir() switch to using READDIRPLUS3 instead of READDIR3 when reading directories.

libnfs-4.0.0-vitalif
Ronnie Sahlberg 2011-09-02 20:27:01 +10:00
parent e02614571c
commit f390f18157
3 changed files with 60 additions and 11 deletions

View File

@ -444,7 +444,7 @@ int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
/*
* Call NFS/REMOVE
* Call NFS/READDIR
* Function returns
* 0 : The call was initiated. The callback will be invoked when the call completes.
* <0 : An error occured when trying to set up the call. The callback will not be invoked.
@ -459,6 +459,22 @@ int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
*/
int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
/*
* Call NFS/READDIRPLUS
* Function returns
* 0 : The call was initiated. The callback will be invoked when the call completes.
* <0 : An error occured when trying to set up the call. The callback will not be invoked.
*
* When the callback is invoked, status indicates the result:
* RPC_STATUS_SUCCESS : We got a successful response from the nfs daemon.
* data is READDIRPLUS3res *
* RPC_STATUS_ERROR : An error occured when trying to contact the nfs daemon.
* data is the error string.
* RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
* data is NULL.
*/
int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
/*
* Call NFS/FSSTAT
* Function returns

View File

@ -1651,13 +1651,13 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void
*/
static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
{
READDIR3res *res;
READDIRPLUS3res *res;
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
struct nfsdir *nfsdir = data->continue_data;;
struct entry3 *entry;
struct entryplus3 *entry;
uint64_t cookie;
if (status == RPC_STATUS_ERROR) {
data->cb(-EFAULT, nfs, command_data, data->private_data);
nfs_free_nfsdir(nfsdir);
@ -1683,7 +1683,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman
return;
}
entry =res->READDIR3res_u.resok.reply.entries;
entry =res->READDIRPLUS3res_u.resok.reply.entries;
while (entry != NULL) {
struct nfsdirent *nfsdirent;
@ -1712,9 +1712,9 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman
entry = entry->nextentry;
}
if (res->READDIR3res_u.resok.reply.eof == 0) {
if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 20000, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
if (res->READDIRPLUS3res_u.resok.reply.eof == 0) {
if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIRPLUS3res_u.resok.cookieverf, 8192, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
nfs_free_nfsdir(nfsdir);
data->continue_data = NULL;
@ -1737,8 +1737,8 @@ static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_
cookieverf3 cv;
bzero(cv, sizeof(cookieverf3));
if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 20000, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
return -1;

View File

@ -476,7 +476,6 @@ int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
return 0;
}
int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
{
struct rpc_pdu *pdu;
@ -510,6 +509,40 @@ int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh
return 0;
}
int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
{
struct rpc_pdu *pdu;
READDIRPLUS3args args;
pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIRPLUS, cb, private_data, (xdrproc_t)xdr_READDIRPLUS3res, sizeof(READDIRPLUS3res));
if (pdu == NULL) {
rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/readdirplus call");
return -1;
}
bzero(&args, sizeof(READDIRPLUS3args));
args.dir.data.data_len = fh->data.data_len;
args.dir.data.data_val = fh->data.data_val;
args.cookie = cookie;
memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3));
args.dircount = count;
args.maxcount = count;
if (xdr_READDIRPLUS3args(&pdu->xdr, &args) == 0) {
rpc_set_error(rpc, "XDR error: Failed to encode READDIRPLUS3args");
rpc_free_pdu(rpc, pdu);
return -2;
}
if (rpc_queue_pdu(rpc, pdu) != 0) {
rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/readdirplus call");
rpc_free_pdu(rpc, pdu);
return -3;
}
return 0;
}
int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
{
struct rpc_pdu *pdu;