From: Michael Vrable Date: Tue, 29 Dec 2009 05:53:11 +0000 (-0800) Subject: Preliminary NFS readdirplus support (not yet entirely to spec). X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=1fddb0453f35dd19cb96d2ef14784f0e31e63564 Preliminary NFS readdirplus support (not yet entirely to spec). --- diff --git a/nfs3/nfs3.c b/nfs3/nfs3.c index c668542..70c9a60 100644 --- a/nfs3/nfs3.c +++ b/nfs3/nfs3.c @@ -674,6 +674,7 @@ nfsproc3_link_3_svc(link3args *argp, struct svc_req *rqstp) gint bluesky_dirent_compare(gconstpointer a, gconstpointer b, gpointer unused); +#define MAX_READDIR_DIRENTS 4 readdir3res * nfsproc3_readdir_3_svc(readdir3args *argp, struct svc_req *rqstp) { @@ -692,7 +693,6 @@ nfsproc3_readdir_3_svc(readdir3args *argp, struct svc_req *rqstp) memset(result.readdir3res_u.resok.cookieverf, 0, sizeof(result.readdir3res_u.resok.cookieverf)); -#define MAX_READDIR_DIRENTS 4 static entry3 dirents[MAX_READDIR_DIRENTS]; int count = 0; @@ -726,7 +726,56 @@ nfsproc3_readdirplus_3_svc(readdirplus3args *argp, struct svc_req *rqstp) { static readdirplus3res result; - result.status = NFS3ERR_NOTSUPP; + BlueSkyInode *dir = lookup_fh(&argp->dir); + if (dir == NULL) { + result.status = NFS3ERR_STALE; + result.readdirplus3res_u.resfail.present = FALSE; + return &result; + } + + result.status = NFS3_OK; + result.readdirplus3res_u.resok.dir_attributes.present = TRUE; + encode_fattr3(&result.readdirplus3res_u.resok.dir_attributes.post_op_attr_u.attributes, dir); + memset(result.readdirplus3res_u.resok.cookieverf, 0, + sizeof(result.readdirplus3res_u.resok.cookieverf)); + + static entryplus3 dirents[MAX_READDIR_DIRENTS]; + static uint64_t fh_bytes[MAX_READDIR_DIRENTS]; + int count = 0; + + /* TODO: Handle dircount, maxcount arguments from client. */ + + BlueSkyDirent start = {NULL, NULL, argp->cookie, 0}; + GSequenceIter *i = g_sequence_search(dir->dirents, &start, + bluesky_dirent_compare, NULL); + + 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); + if (inode != NULL) { + dirents[count].fileid = d->inum; + dirents[count].name = d->name; + dirents[count].cookie = d->cookie; + dirents[count].nextentry = NULL; + dirents[count].name_attributes.present = TRUE; + encode_fattr3(&dirents[count].name_attributes.post_op_attr_u.attributes, inode); + fh_bytes[count] = GUINT64_TO_BE(d->inum); + dirents[count].name_handle.present = TRUE; + dirents[count].name_handle.post_op_fh3_u.handle.data.data_len = 8; + dirents[count].name_handle.post_op_fh3_u.handle.data.data_val + = (char *)&fh_bytes[count]; + if (count > 0) + dirents[count - 1].nextentry = &dirents[count]; + count++; + } + i = g_sequence_iter_next(i); + } + + if (count > 0) + result.readdirplus3res_u.resok.reply.entries = &dirents[0]; + else + result.readdirplus3res_u.resok.reply.entries = NULL; + result.readdirplus3res_u.resok.reply.eof = g_sequence_iter_is_end(i); return &result; }