Module Name: src Committed By: riastradh Date: Fri Aug 12 04:14:00 UTC 2011
Modified Files: src/tests/fs/psshfs: t_psshfs.sh src/usr.sbin/puffs/mount_psshfs: node.c Log Message: Cache vattr in psshfs's setattr. This means within the cache window, a setattr that wouldn't change the remote file's attributes from our current view of them will not be relayed to the server and wait for the server to answer. Thus, e.g., a process with a periodic timer interrupt that calls open(2) in a loop can make progress with much higher probability than without caching. XXX The test case doesn't work, so it's currently disabled. It needs to stop the child of sshd that is handling an sftp session, not sshd itself, and it's not obvious how to do that. ok pooka To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/tests/fs/psshfs/t_psshfs.sh cvs rdiff -u -r1.62 -r1.63 src/usr.sbin/puffs/mount_psshfs/node.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/fs/psshfs/t_psshfs.sh diff -u src/tests/fs/psshfs/t_psshfs.sh:1.5 src/tests/fs/psshfs/t_psshfs.sh:1.6 --- src/tests/fs/psshfs/t_psshfs.sh:1.5 Thu Mar 31 12:56:03 2011 +++ src/tests/fs/psshfs/t_psshfs.sh Fri Aug 12 04:14:00 2011 @@ -1,4 +1,4 @@ -# $NetBSD: t_psshfs.sh,v 1.5 2011/03/31 12:56:03 pooka Exp $ +# $NetBSD: t_psshfs.sh,v 1.6 2011/08/12 04:14:00 riastradh Exp $ # # Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. # All rights reserved. @@ -235,6 +235,33 @@ stop_ssh } +atf_test_case setattr_cache cleanup +setattr_cache_head() { + atf_set "descr" "Checks that setattr caches" + # Don't wait for the eternity that atf usually waits. Twenty + # seconds should be good enough, except maybe on a VAX... + atf_set "timeout" 20 +} +setattr_cache_body() { + require_puffs + start_ssh + atf_check -s exit:0 mkdir root + atf_check -s exit:0 mkdir mnt + mount_psshfs root mnt + atf_check -s exit:0 -x ': > mnt/loser' + atf_check -s exit:0 -o save:stat stat mnt/loser + # Oops -- this doesn't work. We need to stop the child of the + # sshd that is handling the sftp session. + atf_check -s exit:0 kill -STOP $(cat sshd.pid) + atf_check -s exit:0 -x ': > mnt/loser' + atf_check -s exit:0 -o file:stat stat mnt/loser +} +setattr_cache_cleanup() { + umount mnt + kill -CONT $(cat sshd.pid) + stop_ssh +} + # ------------------------------------------------------------------------- # Initialization. # ------------------------------------------------------------------------- @@ -243,4 +270,5 @@ atf_add_test_case inode_nos atf_add_test_case pwd atf_add_test_case ls + #atf_add_test_case setattr_cache } Index: src/usr.sbin/puffs/mount_psshfs/node.c diff -u src/usr.sbin/puffs/mount_psshfs/node.c:1.62 src/usr.sbin/puffs/mount_psshfs/node.c:1.63 --- src/usr.sbin/puffs/mount_psshfs/node.c:1.62 Fri Oct 29 16:13:51 2010 +++ src/usr.sbin/puffs/mount_psshfs/node.c Fri Aug 12 04:14:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: node.c,v 1.62 2010/10/29 16:13:51 pooka Exp $ */ +/* $NetBSD: node.c,v 1.63 2011/08/12 04:14:00 riastradh Exp $ */ /* * Copyright (c) 2006-2009 Antti Kantee. All Rights Reserved. @@ -27,7 +27,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: node.c,v 1.62 2010/10/29 16:13:51 pooka Exp $"); +__RCSID("$NetBSD: node.c,v 1.63 2011/08/12 04:14:00 riastradh Exp $"); #endif /* !lint */ #include <assert.h> @@ -133,9 +133,57 @@ psshfs_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, const struct vattr *va, const struct puffs_cred *pcr) { - PSSHFSAUTOVAR(pu); + struct puffs_cc *pcc = puffs_cc_getcc(pu); + struct psshfs_ctx *pctx = puffs_getspecific(pu); + uint32_t reqid; + struct puffs_framebuf *pb; struct vattr kludgeva; struct puffs_node *pn = opc; + struct psshfs_node *psn = pn->pn_data; + int rv; + + /* + * If we cached the remote attributes recently enough, and this + * setattr operation would change nothing that sftp actually + * records, then we can skip the sftp request. So first check + * whether we have the attributes cached, and then compare + * every field that we might send to the sftp server. + */ + + if (!psn->attrread || REFRESHTIMEOUT(pctx, time(NULL)-psn->attrread)) + goto setattr; + +#define CHECK(FIELD, TYPE) do { \ + if ((va->FIELD != (TYPE)PUFFS_VNOVAL) && \ + (va->FIELD != pn->pn_va.FIELD)) \ + goto setattr; \ +} while (0) + +#define CHECKID(FIELD, TYPE, DOMANGLE, MINE, MANGLED) do { \ + if ((va->FIELD != (TYPE)PUFFS_VNOVAL) && \ + (pn->pn_va.FIELD != \ + ((pctx->DOMANGLE && (va->FIELD == pctx->MINE)) \ + ? pctx->MANGLED \ + : va->FIELD))) \ + goto setattr; \ +} while (0) + + CHECK(va_size, uint64_t); + CHECKID(va_uid, uid_t, domangleuid, myuid, mangleuid); + CHECKID(va_gid, gid_t, domanglegid, mygid, manglegid); + CHECK(va_mode, mode_t); + CHECK(va_atime.tv_sec, time_t); + CHECK(va_mtime.tv_sec, time_t); + + /* Nothing to change. */ + return 0; + +#undef CHECK +#undef CHECKID + + setattr: + reqid = NEXTREQ(pctx); + pb = psbuf_makeout(); psbuf_req_str(pb, SSH_FXP_SETSTAT, reqid, PNPATH(pn)); @@ -156,16 +204,19 @@ else kludgeva.va_atime.tv_sec = va->va_mtime.tv_sec; } - + psbuf_put_vattr(pb, &kludgeva, pctx); GETRESPONSE(pb, pctx->sshfd); rv = psbuf_expect_status(pb); - if (rv == 0) + if (rv == 0) { puffs_setvattr(&pn->pn_va, &kludgeva); + psn->attrread = time(NULL); + } out: - PSSHFSRETURN(rv); + puffs_framebuf_destroy(pb); + return rv; } int