nfs_opendir() switch to using READDIRPLUS3 instead of READDIR3 when reading directo...
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Fri, 2 Sep 2011 10:27:01 +0000 (20:27 +1000)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Fri, 2 Sep 2011 10:27:01 +0000 (20:27 +1000)
include/libnfs-raw.h
lib/libnfs.c
nfs/nfs.c

index 1650a8a18406621702f04c4bf0cc3bbacfddc033..573205c9c876c9ca48d38377806ea68369e0f1b4 100644 (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
index 80a7394d6d239c999ac70ee3e626b6d4908a6281..2e504a40cae616eb62bc0869e58ce00e26b36350 100644 (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;
index a9775e7f3ab3d4cf5f9cc8a9c9287bd3c2c68490..5b655cb3369e2aeea6f2a4f55f4ca1be320132a7 100644 (file)
--- a/nfs/nfs.c
+++ b/nfs/nfs.c
@@ -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;