Add inode prefetching support in NFS readdirplus.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 28 Jan 2010 20:53:16 +0000 (12:53 -0800)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 28 Jan 2010 20:53:16 +0000 (12:53 -0800)
nfs3/nfs3.c

index 1b7e594..42ac46c 100644 (file)
@@ -937,12 +937,32 @@ void nfsproc3_readdirplus_3_svc(readdirplus3args *argp, RPCRequest *req)
     uint64_t fh_bytes[MAX_READDIR_DIRENTS];
     int count = 0;
 
-    /* TODO: Handle dircount, maxcount arguments from client. */
-
+    GSequenceIter *i;
     BlueSkyDirent start = {NULL, NULL, argp->cookie, 0};
-    GSequenceIter *i = g_sequence_search(dir->dirents, &start,
-                                         bluesky_dirent_compare, NULL);
 
+    /* Perform a prefetch pass on inodes: for all the inodes we think we will
+     * return information about, try to load each one but don't wait.  This
+     * should let multiple inodes be fetched in parallel, instead of
+     * sequentially in the loop that follows. */
+    i = g_sequence_search(dir->dirents, &start, bluesky_dirent_compare, NULL);
+    while (count < MAX_READDIR_DIRENTS
+           && !g_sequence_iter_is_end(i)
+           && dircount <= argp->dircount
+           && dircount + attrcount <= argp->maxcount)
+    {
+        BlueSkyDirent *d = g_sequence_get(i);
+        BlueSkyInode *inode = bluesky_get_inode(fs, d->inum);
+        if (inode != NULL)
+            bluesky_inode_unref(inode);
+        dircount += 24 + ((strlen(d->name) + 3) & ~3);
+        attrcount += 88 + 8 + 8;
+        i = g_sequence_iter_next(i);
+    }
+
+    i = g_sequence_search(dir->dirents, &start, bluesky_dirent_compare, NULL);
+    count = 0;
+    dircount = 88 + 16;
+    attrcount = 0;
     while (count < MAX_READDIR_DIRENTS && !g_sequence_iter_is_end(i)) {
         BlueSkyDirent *d = g_sequence_get(i);
         BlueSkyInode *inode = bluesky_get_inode(fs, d->inum);