Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 May 2019 00:22:04 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r348134 - projects/fuse2/sys/fs/fuse
Message-ID:  <201905230022.x4N0M4vA093606@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Thu May 23 00:22:03 2019
New Revision: 348134
URL: https://svnweb.freebsd.org/changeset/base/348134

Log:
  fusefs: improve attribute cacheing
  
  Consolidate all calls to fuse_vnode_setsize as a result of a file attribute
  change to one location in fuse_internal_setattr.  There are still a few
  calls elsewhere that happen as a result of a write.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_internal.c
  projects/fuse2/sys/fs/fuse/fuse_internal.h
  projects/fuse2/sys/fs/fuse/fuse_io.c
  projects/fuse2/sys/fs/fuse/fuse_node.c
  projects/fuse2/sys/fs/fuse/fuse_vnops.c

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.c	Wed May 22 23:34:41 2019	(r348133)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.c	Thu May 23 00:22:03 2019	(r348134)
@@ -193,8 +193,9 @@ fuse_internal_access(struct vnode *vp,
  * return the result to the caller).
  */
 void
-fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
-	uint64_t attr_valid, uint32_t attr_valid_nsec, struct vattr *vap)
+fuse_internal_cache_attrs(struct vnode *vp, struct ucred *cred,
+	struct fuse_attr *attr, uint64_t attr_valid, uint32_t attr_valid_nsec,
+	struct vattr *vap)
 {
 	struct mount *mp;
 	struct fuse_vnode_data *fvdat;
@@ -204,45 +205,53 @@ fuse_internal_cache_attrs(struct vnode *vp, struct fus
 	mp = vnode_mount(vp);
 	fvdat = VTOFUD(vp);
 	data = fuse_get_mpdata(mp);
+	if (!cred)
+		cred = curthread->td_ucred;
 
+	ASSERT_VOP_ELOCKED(*vpp, "fuse_internal_cache_attrs");
+
 	fuse_validity_2_bintime(attr_valid, attr_valid_nsec,
 		&fvdat->attr_cache_timeout);
 
-	vp_cache_at = VTOVA(vp);
+	/* Fix our buffers if the filesize changed without us knowing */
+	if (vnode_isreg(vp) && attr->size != fvdat->cached_attrs.va_size) {
+		(void)fuse_vnode_setsize(vp, cred, attr->size);
+		fvdat->cached_attrs.va_size = attr->size;
+	}
 
-	if (vap == NULL && vp_cache_at == NULL)
+	if (attr_valid > 0 || attr_valid_nsec > 0)
+		vp_cache_at = &(fvdat->cached_attrs);
+	else if (vap != NULL)
+		vp_cache_at = vap;
+	else
 		return;
 
-	if (vap == NULL)
-		vap = vp_cache_at;
-
-	vattr_null(vap);
-
-	vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
-	vap->va_fileid = attr->ino;
-	vap->va_mode = attr->mode & ~S_IFMT;
-	vap->va_nlink     = attr->nlink;
-	vap->va_uid       = attr->uid;
-	vap->va_gid       = attr->gid;
-	vap->va_rdev      = attr->rdev;
-	vap->va_size      = attr->size;
+	vattr_null(vp_cache_at);
+	vp_cache_at->va_fsid = mp->mnt_stat.f_fsid.val[0];
+	vp_cache_at->va_fileid = attr->ino;
+	vp_cache_at->va_mode = attr->mode & ~S_IFMT;
+	vp_cache_at->va_nlink     = attr->nlink;
+	vp_cache_at->va_uid       = attr->uid;
+	vp_cache_at->va_gid       = attr->gid;
+	vp_cache_at->va_rdev      = attr->rdev;
+	vp_cache_at->va_size      = attr->size;
 	/* XXX on i386, seconds are truncated to 32 bits */
-	vap->va_atime.tv_sec  = attr->atime;
-	vap->va_atime.tv_nsec = attr->atimensec;
-	vap->va_mtime.tv_sec  = attr->mtime;
-	vap->va_mtime.tv_nsec = attr->mtimensec;
-	vap->va_ctime.tv_sec  = attr->ctime;
-	vap->va_ctime.tv_nsec = attr->ctimensec;
+	vp_cache_at->va_atime.tv_sec  = attr->atime;
+	vp_cache_at->va_atime.tv_nsec = attr->atimensec;
+	vp_cache_at->va_mtime.tv_sec  = attr->mtime;
+	vp_cache_at->va_mtime.tv_nsec = attr->mtimensec;
+	vp_cache_at->va_ctime.tv_sec  = attr->ctime;
+	vp_cache_at->va_ctime.tv_nsec = attr->ctimensec;
 	if (fuse_libabi_geq(data, 7, 9) && attr->blksize > 0)
-		vap->va_blocksize = attr->blksize;
+		vp_cache_at->va_blocksize = attr->blksize;
 	else
-		vap->va_blocksize = PAGE_SIZE;
-	vap->va_type = IFTOVT(attr->mode);
-	vap->va_bytes = attr->blocks * S_BLKSIZE;
-	vap->va_flags = 0;
+		vp_cache_at->va_blocksize = PAGE_SIZE;
+	vp_cache_at->va_type = IFTOVT(attr->mode);
+	vp_cache_at->va_bytes = attr->blocks * S_BLKSIZE;
+	vp_cache_at->va_flags = 0;
 
-	if (vap != vp_cache_at && vp_cache_at != NULL)
-		memcpy(vp_cache_at, vap, sizeof(*vap));
+	if (vap != vp_cache_at && vap != NULL)
+		memcpy(vap, vp_cache_at, sizeof(*vap));
 }
 
 
@@ -560,7 +569,7 @@ fuse_internal_newentry_core(struct vnode *dvp,
 	 */
 	fuse_vnode_clear_attr_cache(dvp);
 
-	fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid,
+	fuse_internal_cache_attrs(*vpp, NULL, &feo->attr, feo->attr_valid,
 		feo->attr_valid_nsec, NULL);
 
 	return err;
@@ -646,25 +655,15 @@ fuse_internal_do_getattr(struct vnode *vp, struct vatt
 
 	fao = (struct fuse_attr_out *)fdi.answ;
 	vtyp = IFTOVT(fao->attr.mode);
-	fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
+	if (fvdat->flag & FN_SIZECHANGE)
+		fao->attr.size = old_filesize;
+	fuse_internal_cache_attrs(vp, NULL, &fao->attr, fao->attr_valid,
 		fao->attr_valid_nsec, vap);
 	if (vtyp != vnode_vtype(vp)) {
 		fuse_internal_vnode_disappear(vp);
 		err = ENOENT;
 	}
 
-	if ((fvdat->flag & FN_SIZECHANGE) != 0)
-		fvdat->cached_attrs.va_size = old_filesize;
-
-	if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) {
-		/*
-	         * This is for those cases when the file size changed without us
-	         * knowing, and we want to catch up.
-	         */
-		if (old_filesize != fao->attr.size)
-			fuse_vnode_setsize(vp, cred, fao->attr.size);
-	}
-
 out:
 	fdisp_destroy(&fdi);
 	return err;
@@ -675,14 +674,10 @@ int
 fuse_internal_getattr(struct vnode *vp, struct vattr *vap, struct ucred *cred,
 	struct thread *td)
 {
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
 	struct vattr *attrs;
-	off_t old_filesize = vap->va_size;
 
 	if ((attrs = VTOVA(vp)) != NULL) {
 		*vap = *attrs;	/* struct copy */
-		if ((fvdat->flag & FN_SIZECHANGE) != 0)
-			vap->va_size = old_filesize;
 		return 0;
 	}
 
@@ -829,6 +824,7 @@ int fuse_internal_setattr(struct vnode *vp, struct vat
 			fsai->fh = fufh->fh_id;
 			fsai->valid |= FATTR_FH;
 		}
+		VTOFUD(vp)->flag &= ~FN_SIZECHANGE;
 	}
 	if (vap->va_atime.tv_sec != VNOVAL) {
 		fsai->atime = vap->va_atime.tv_sec;
@@ -875,16 +871,12 @@ int fuse_internal_setattr(struct vnode *vp, struct vat
 	}
 	if (err == 0) {
 		struct fuse_attr_out *fao = (struct fuse_attr_out*)fdi.answ;
-		fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
+		fuse_internal_cache_attrs(vp, cred, &fao->attr, fao->attr_valid,
 			fao->attr_valid_nsec, NULL);
 	}
 
 out:
 	fdisp_destroy(&fdi);
-	if (!err && sizechanged) {
-		fuse_vnode_setsize(vp, cred, newsize);
-		VTOFUD(vp)->flag &= ~FN_SIZECHANGE;
-	}
 	return err;
 }
 

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.h
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.h	Wed May 22 23:34:41 2019	(r348133)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.h	Thu May 23 00:22:03 2019	(r348134)
@@ -209,8 +209,9 @@ int fuse_internal_access(struct vnode *vp, accmode_t m
     struct thread *td, struct ucred *cred);
 
 /* attributes */
-void fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
-	uint64_t attr_valid, uint32_t attr_valid_nsec, struct vattr *vap);
+void fuse_internal_cache_attrs(struct vnode *vp, struct ucred *cred,
+	struct fuse_attr *attr, uint64_t attr_valid, uint32_t attr_valid_nsec,
+	struct vattr *vap);
 
 /* fsync */
 

Modified: projects/fuse2/sys/fs/fuse/fuse_io.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_io.c	Wed May 22 23:34:41 2019	(r348133)
+++ projects/fuse2/sys/fs/fuse/fuse_io.c	Thu May 23 00:22:03 2019	(r348134)
@@ -473,10 +473,10 @@ retry:
 		as_written_offset = uio->uio_offset - diff;
 
 		if (as_written_offset - diff > filesize &&
-		    fuse_data_cache_mode != FUSE_CACHE_UC) {
+		    fuse_data_cache_mode != FUSE_CACHE_UC)
 			fuse_vnode_setsize(vp, cred, as_written_offset);
+		if (as_written_offset - diff >= filesize)
 			fvdat->flag &= ~FN_SIZECHANGE;
-		}
 
 		if (diff < 0) {
 			printf("WARNING: misbehaving FUSE filesystem "
@@ -528,6 +528,7 @@ static int
 fuse_write_biobackend(struct vnode *vp, struct uio *uio,
     struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid)
 {
+	struct fuse_vnode_data *fvdat = VTOFUD(vp);
 	struct buf *bp;
 	daddr_t lbn;
 	off_t filesize;
@@ -590,6 +591,8 @@ again:
 
 				err = fuse_vnode_setsize(vp, cred, 
 							 uio->uio_offset + n);
+				fvdat->flag |= FN_SIZECHANGE;
+
 				if (err) {
 					brelse(bp);
 					break;
@@ -617,10 +620,11 @@ again:
 			if (bp && uio->uio_offset + n > filesize) {
 				err = fuse_vnode_setsize(vp, cred, 
 							 uio->uio_offset + n);
+				fvdat->flag |= FN_SIZECHANGE;
 				if (err) {
 					brelse(bp);
 					break;
-				}
+				} 
 			}
 		}
 

Modified: projects/fuse2/sys/fs/fuse/fuse_node.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_node.c	Wed May 22 23:34:41 2019	(r348133)
+++ projects/fuse2/sys/fs/fuse/fuse_node.c	Thu May 23 00:22:03 2019	(r348134)
@@ -400,7 +400,6 @@ fuse_vnode_setsize(struct vnode *vp, struct ucred *cre
 	fvdat->cached_attrs.va_size = newsize;
 	if ((attrs = VTOVA(vp)) != NULL)
 		attrs->va_size = newsize;
-	fvdat->flag |= FN_SIZECHANGE;
 
 	if (newsize < oldsize) {
 		daddr_t lbn;

Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c	Wed May 22 23:34:41 2019	(r348133)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c	Thu May 23 00:22:03 2019	(r348134)
@@ -624,7 +624,7 @@ fuse_vnop_create(struct vop_create_args *ap)
 		goto out;
 	}
 	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");
-	fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid,
+	fuse_internal_cache_attrs(*vpp, cred, &feo->attr, feo->attr_valid,
 		feo->attr_valid_nsec, NULL);
 
 	fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo);
@@ -790,6 +790,7 @@ fuse_vnop_link(struct vop_link_args *ap)
 	struct vnode *vp = ap->a_vp;
 	struct vnode *tdvp = ap->a_tdvp;
 	struct componentname *cnp = ap->a_cnp;
+	struct ucred *cred = cnp->cn_cred;
 
 	struct vattr *vap = VTOVA(vp);
 
@@ -831,7 +832,7 @@ fuse_vnop_link(struct vop_link_args *ap)
 		 * should've updated its mtime and ctime
 		 */
 		fuse_vnode_clear_attr_cache(tdvp);
-		fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid,
+		fuse_internal_cache_attrs(vp, cred, &feo->attr, feo->attr_valid,
 			feo->attr_valid_nsec, NULL);
 	}
 out:
@@ -1040,17 +1041,17 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
 			 * 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.
+			 * the vnode's cached size, then any cached writes
+			 * beyond the file's current size are lost.
 			 *
 			 * We can get here:
 			 * * following attribute cache expiration, or
 			 * * due a bug in the daemon, or
-			 * * the first time that we looked up the file.
 			 */
 			fvdat = VTOFUD(vp);
 			if (vnode_isreg(vp) &&
-			    filesize != fvdat->cached_attrs.va_size) {
+			    filesize != fvdat->cached_attrs.va_size &&
+			    fvdat->flag & FN_SIZECHANGE) {
 				/*
 				 * The FN_SIZECHANGE flag reflects a dirty
 				 * append.  If userspace lets us know our cache
@@ -1060,17 +1061,15 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
 				 *
 				 * 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);
+				printf("%s: WB cache incoherent on %s!\n",
+				    __func__,
+				    vnode_mount(vp)->mnt_stat.f_mntonname);
 
-				(void)fuse_vnode_setsize(vp, cred, filesize);
 				fvdat->flag &= ~FN_SIZECHANGE;
 			}
 
 			MPASS(feo != NULL);
-			fuse_internal_cache_attrs(*vpp, &feo->attr,
+			fuse_internal_cache_attrs(*vpp, cred, &feo->attr,
 				feo->attr_valid, feo->attr_valid_nsec, NULL);
 
 			if ((nameiop == DELETE || nameiop == RENAME) &&



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