Implement SUPERREADDIR (like nfs readdirplus) getattr cache warming

a bit differently: when reading the directory, store all getattr
caching queries and fire off only when the directory read is
complete.  That way the common sequence is not [readdir, lots of
async getattr requests, readdir EOF] but rather [readdir, readdir
EOF, lots of async getattr].  This speeds up ls -lR by about 25%
(on my LAN).
This commit is contained in:
pooka 2007-05-20 17:47:12 +00:00
parent e9e5beefa0
commit a769baf075
2 changed files with 44 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: psshfs.h,v 1.17 2007/05/18 18:00:07 pooka Exp $ */
/* $NetBSD: psshfs.h,v 1.18 2007/05/20 17:47:12 pooka Exp $ */
/*
* Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved.
@ -107,6 +107,14 @@ struct psshfs_node {
struct puffs_node *parent;
struct psshfs_dir *dir; /* only valid if we're of type VDIR */
#ifdef SUPERREADDIR
struct delayattr {
struct puffs_framebuf *pufbuf;
struct readdirattr *rda;
} *da;
size_t nextda;
#endif /* SUPERREADDIR */
size_t denttot;
size_t dentnext;
time_t dentread;

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr.c,v 1.20 2007/05/18 18:00:07 pooka Exp $ */
/* $NetBSD: subr.c,v 1.21 2007/05/20 17:47:12 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: subr.c,v 1.20 2007/05/18 18:00:07 pooka Exp $");
__RCSID("$NetBSD: subr.c,v 1.21 2007/05/20 17:47:12 pooka Exp $");
#endif /* !lint */
#include <assert.h>
@ -65,6 +65,10 @@ allocdirs(struct psshfs_node *psn)
psn->dir = erealloc(psn->dir,
psn->denttot * sizeof(struct psshfs_dir));
memset(psn->dir + oldtot, 0, ENTRYCHUNK * sizeof(struct psshfs_dir));
#ifdef SUPERREADDIR
psn->da = erealloc(psn->da, psn->denttot * sizeof(struct delayattr));
#endif
}
struct psshfs_dir *
@ -143,7 +147,7 @@ readdir_getattr_resp(struct puffs_usermount *pu,
puffs_framebuf_destroy(pb);
}
static int
static void
readdir_getattr(struct puffs_usermount *pu, struct psshfs_node *psn,
const char *basepath, int idx)
{
@ -154,7 +158,6 @@ readdir_getattr(struct puffs_usermount *pu, struct psshfs_node *psn,
struct readdirattr *rda;
const char *entryname = pdir[idx].entryname;
uint32_t reqid = NEXTREQ(pctx);
int rv = 0;
rda = emalloc(sizeof(struct readdirattr));
rda->psn = psn;
@ -167,10 +170,23 @@ readdir_getattr(struct puffs_usermount *pu, struct psshfs_node *psn,
pb = psbuf_makeout();
psbuf_req_str(pb, SSH_FXP_LSTAT, reqid, path);
SENDCB(pb, readdir_getattr_resp, rda);
psn->da[psn->nextda].pufbuf = pb;
psn->da[psn->nextda].rda = rda;
psn->nextda++;
}
static void
readdir_getattr_send(struct puffs_usermount *pu, struct psshfs_node *psn)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
size_t i;
int rv = 0;
for (i = 0; i < psn->nextda; i++)
SENDCB(psn->da[i].pufbuf, readdir_getattr_resp, psn->da[i].rda);
out:
return rv;
return;
}
#endif
@ -266,6 +282,9 @@ sftp_readdir(struct puffs_cc *pcc, struct psshfs_ctx *pctx,
psn->dentnext = 0;
psn->denttot = 0;
psn->dir = NULL;
#ifdef SUPERREADDIR
psn->nextda = 0;
#endif /* SUPERREADDIR */
for (;;) {
reqid = NEXTREQ(pctx);
@ -315,16 +334,17 @@ sftp_readdir(struct puffs_cc *pcc, struct psshfs_ctx *pctx,
* the server responds to our queries out-of-order.
* fixxxme some day
*/
rv = readdir_getattr(puffs_cc_getusermount(pcc),
readdir_getattr(puffs_cc_getusermount(pcc),
psn, PNPATH(pn), idx);
if (rv)
goto out;
#endif
psn->dir[idx].valid = 1;
}
}
out:
/* fire off getattr requests */
readdir_getattr_send(pu, psn);
/* XXX: rv */
psn->dentnext = idx;
freedircache(olddir, nent);
@ -332,9 +352,9 @@ sftp_readdir(struct puffs_cc *pcc, struct psshfs_ctx *pctx,
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb);
psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, dhand, dhandlen);
JUSTSEND(pb);
free(dhand);
return rv;
wayout:
@ -436,8 +456,12 @@ doreclaim(struct puffs_node *pn)
if (dent)
dent->entry = NULL;
if (pn->pn_va.va_type == VDIR)
if (pn->pn_va.va_type == VDIR) {
freedircache(psn->dir, psn->dentnext);
#ifdef SUPERREADDIR
free(psn->da);
#endif
}
puffs_pn_put(pn);
}