From: Michael Vrable Date: Wed, 9 Mar 2011 04:57:15 +0000 (-0800) Subject: Rework inode prefetching. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=b0107f8024a860145c8c9c6890d2cd4bf9f74b41 Rework inode prefetching. Attempt to coalesce range requests for inodes where possible. --- diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index ae751fd..9921091 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -356,6 +356,7 @@ void bluesky_file_read(BlueSkyInode *inode, uint64_t offset, char *buf, gint len); void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum); +void bluesky_inode_prefetch(BlueSkyFS *fs, uint64_t inum); gint bluesky_dirent_compare(gconstpointer a, gconstpointer b, gpointer unused); diff --git a/bluesky/inode.c b/bluesky/inode.c index fe68328..42ae708 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -270,6 +270,30 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, return i; } +/* Issue a prefetch hint for an inode. This signals that the inode may be + * needed soon. Does not return any useful data. */ +void bluesky_inode_prefetch(BlueSkyFS *fs, uint64_t inum) +{ + BlueSkyInode *inode = NULL; + + g_mutex_lock(fs->lock); + inode = (BlueSkyInode *)g_hash_table_lookup(fs->inodes, &inum); + + if (inode != NULL) { + /* Inode is already available, no need for any prefetching... */ + g_mutex_unlock(fs->lock); + return; + } + + InodeMapEntry *entry = bluesky_inode_map_lookup(fs->inode_map, inum, 0); + if (entry != NULL) { + bluesky_cloudlog_prefetch(entry->item); + } + + g_mutex_unlock(fs->lock); + return; +} + /* Retrieve an inode from the filesystem. Eventually this will be a cache and * so we might need to go fetch the inode from elsewhere; for now all * filesystem state is stored here. inode is returned with a reference held diff --git a/nfs3/nfs3.c b/nfs3/nfs3.c index b5dae80..8f15857 100644 --- a/nfs3/nfs3.c +++ b/nfs3/nfs3.c @@ -1006,6 +1006,22 @@ void nfsproc3_readdirplus_3_svc(readdirplus3args *argp, RPCRequest *req) * 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); + bluesky_inode_prefetch(fs, d->inum); + 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) && dircount <= argp->dircount