svn commit: r348134 - projects/fuse2/sys/fs/fuse
Alan Somers
asomers at FreeBSD.org
Thu May 23 00:22:05 UTC 2019
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) &&
More information about the svn-src-projects
mailing list