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

Reply via email to