Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Feb 2019 22:55:13 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344187 - head/sys/fs/fuse
Message-ID:  <201902152255.x1FMtDYJ018343@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Fri Feb 15 22:55:13 2019
New Revision: 344187
URL: https://svnweb.freebsd.org/changeset/base/344187

Log:
  FUSE: Refresh cached file size when it changes (lookup)
  
  The cached fvdat->filesize is indepedent of the (mostly unused)
  cached_attrs, and we failed to update it when a cached (but perhaps
  inactive) vnode was found during VOP_LOOKUP to have a different size than
  cached.
  
  As noted in the code comment, this can occur in distributed filesystems or
  with other kinds of irregular file behavior (anything is possible in FUSE).
  
  We do something similar in fuse_vnop_getattr already.
  
  PR:		230258 (as reported in description; other issues explored in
  			comments are not all resolved)
  Reported by:	MooseFS FreeBSD Team <freebsd AT moosefs.com>
  Submitted by:	Jakub Kruszona-Zawadzki <acid AT moosefs.com> (earlier version)

Modified:
  head/sys/fs/fuse/fuse_vnops.c

Modified: head/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vnops.c	Fri Feb 15 22:52:49 2019	(r344186)
+++ head/sys/fs/fuse/fuse_vnops.c	Fri Feb 15 22:55:13 2019	(r344187)
@@ -949,12 +949,45 @@ calldaemon:
 			vref(dvp);
 			*vpp = dvp;
 		} else {
+			struct fuse_vnode_data *fvdat;
+
 			err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
 			    &vp, cnp, IFTOVT(fattr->mode));
 			if (err) {
 				goto out;
 			}
 			fuse_vnode_setparent(vp, dvp);
+
+			/*
+			 * In the case where we are looking up a FUSE node
+			 * represented by an existing cached vnode, and the
+			 * true size reported by FUSE_LOOKUP doesn't match
+			 * the vnode's cached size, fix the vnode cache to
+			 * match the real object size.
+			 *
+			 * This can occur via FUSE distributed filesystems,
+			 * irregular files, etc.
+			 */
+			fvdat = VTOFUD(vp);
+			if (vnode_isreg(vp) &&
+			    fattr->size != fvdat->filesize) {
+				/*
+				 * The FN_SIZECHANGE flag reflects a dirty
+				 * append.  If userspace lets us know our cache
+				 * is invalid, that write was lost.  (Dirty
+				 * writes that do not cause append are also
+				 * lost, but we don't detect them here.)
+				 *
+				 * XXX: Maybe disable WB caching on this mount.
+				 */
+				if (fvdat->flag & FN_SIZECHANGE)
+					printf("%s: WB cache incoherent on "
+					    "%s!\n", __func__,
+					    vnode_mount(vp)->mnt_stat.f_mntonname);
+
+				(void)fuse_vnode_setsize(vp, cred, fattr->size);
+				fvdat->flag &= ~FN_SIZECHANGE;
+			}
 			*vpp = vp;
 		}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902152255.x1FMtDYJ018343>