Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151687650
D19088.id53610.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D19088.id53610.diff
View Options
Index: sys/fs/fuse/fuse_internal.h
===================================================================
--- sys/fs/fuse/fuse_internal.h
+++ sys/fs/fuse/fuse_internal.h
@@ -200,15 +200,47 @@
/* attributes */
+/*
+ * Cache FUSE attributes 'fat', with nominal expiration
+ * 'attr_valid'.'attr_valid_nsec', in attr cache associated with vnode 'vp'.
+ * Optionally, if argument 'vap' is not NULL, store a copy of the converted
+ * attributes there as well.
+ *
+ * If the nominal attribute cache TTL is zero, do not cache on the 'vp' (but do
+ * return the result to the caller).
+ */
static __inline
void
-fuse_internal_attr_fat2vat(struct mount *mp,
+fuse_internal_attr_fat2vat(struct vnode *vp,
struct fuse_attr *fat,
+ uint64_t attr_valid,
+ uint32_t attr_valid_nsec,
struct vattr *vap)
{
+ struct mount *mp;
+ struct fuse_vnode_data *fvdat;
+ struct vattr *vp_cache_at;
+
+ mp = vnode_mount(vp);
+ fvdat = VTOFUD(vp);
+
DEBUGX(FUSE_DEBUG_INTERNAL,
"node #%ju, mode 0%o\n", (uintmax_t)fat->ino, fat->mode);
+ /* Honor explicit do-not-cache requests from user filesystems. */
+ if (attr_valid == 0 && attr_valid_nsec == 0)
+ fvdat->valid_attr_cache = false;
+ else
+ fvdat->valid_attr_cache = true;
+
+ vp_cache_at = VTOVA(vp);
+
+ if (vap == NULL && vp_cache_at == NULL)
+ return;
+
+ if (vap == NULL)
+ vap = vp_cache_at;
+
vattr_null(vap);
vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
@@ -227,21 +259,17 @@
vap->va_ctime.tv_nsec = fat->ctimensec;
vap->va_blocksize = PAGE_SIZE;
vap->va_type = IFTOVT(fat->mode);
-
-#if (S_BLKSIZE == 512)
- /* Optimize this case */
- vap->va_bytes = fat->blocks << 9;
-#else
vap->va_bytes = fat->blocks * S_BLKSIZE;
-#endif
-
vap->va_flags = 0;
+
+ if (vap != vp_cache_at && vp_cache_at != NULL)
+ memcpy(vp_cache_at, vap, sizeof(*vap));
}
-#define cache_attrs(vp, fuse_out) \
- fuse_internal_attr_fat2vat(vnode_mount(vp), &(fuse_out)->attr, \
- VTOVA(vp));
+#define cache_attrs(vp, fuse_out, vap_out) \
+ fuse_internal_attr_fat2vat((vp), &(fuse_out)->attr, \
+ (fuse_out)->attr_valid, (fuse_out)->attr_valid_nsec, (vap_out))
/* fsync */
Index: sys/fs/fuse/fuse_internal.c
===================================================================
--- sys/fs/fuse/fuse_internal.c
+++ sys/fs/fuse/fuse_internal.c
@@ -373,7 +373,6 @@
/* remove */
-#define INVALIDATE_CACHED_VATTRS_UPON_UNLINK 1
int
fuse_internal_remove(struct vnode *dvp,
struct vnode *vp,
@@ -381,15 +380,11 @@
enum fuse_opcode op)
{
struct fuse_dispatcher fdi;
+ struct fuse_vnode_data *fvdat;
+ int err;
- struct vattr *vap = VTOVA(vp);
-
-#if INVALIDATE_CACHED_VATTRS_UPON_UNLINK
- int need_invalidate = 0;
- uint64_t target_nlink = 0;
-
-#endif
- int err = 0;
+ err = 0;
+ fvdat = VTOFUD(vp);
debug_printf("dvp=%p, cnp=%p, op=%d\n", vp, cnp, op);
@@ -399,13 +394,6 @@
memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
((char *)fdi.indata)[cnp->cn_namelen] = '\0';
-#if INVALIDATE_CACHED_VATTRS_UPON_UNLINK
- if (vap->va_nlink > 1) {
- need_invalidate = 1;
- target_nlink = vap->va_nlink;
- }
-#endif
-
err = fdisp_wait_answ(&fdi);
fdisp_destroy(&fdi);
return err;
@@ -489,7 +477,7 @@
feo->nodeid, 1);
return err;
}
- cache_attrs(*vpp, feo);
+ cache_attrs(*vpp, feo, NULL);
return err;
}
@@ -563,6 +551,7 @@
ASSERT_VOP_ELOCKED(vp, "fuse_internal_vnode_disappear");
fvdat->flag |= FN_REVOKED;
+ fvdat->valid_attr_cache = false;
cache_purge(vp);
}
Index: sys/fs/fuse/fuse_io.c
===================================================================
--- sys/fs/fuse/fuse_io.c
+++ sys/fs/fuse/fuse_io.c
@@ -655,6 +655,7 @@
uiop->uio_offset = ((off_t)bp->b_blkno) * biosize;
error = fuse_read_directbackend(vp, uiop, cred, fufh);
+ /* XXXCEM: Potentially invalid access to cached_attrs here */
if ((!error && uiop->uio_resid) ||
(fsess_opt_brokenio(vnode_mount(vp)) && error == EIO &&
uiop->uio_offset < fvdat->filesize && fvdat->filesize > 0 &&
Index: sys/fs/fuse/fuse_node.h
===================================================================
--- sys/fs/fuse/fuse_node.h
+++ sys/fs/fuse/fuse_node.h
@@ -86,6 +86,7 @@
uint32_t flag;
/** meta **/
+ bool valid_attr_cache;
struct vattr cached_attrs;
off_t filesize;
uint64_t nlookup;
@@ -95,7 +96,9 @@
#define VTOFUD(vp) \
((struct fuse_vnode_data *)((vp)->v_data))
#define VTOI(vp) (VTOFUD(vp)->nid)
-#define VTOVA(vp) (&(VTOFUD(vp)->cached_attrs))
+#define VTOVA(vp) \
+ (VTOFUD(vp)->valid_attr_cache ? \
+ &(VTOFUD(vp)->cached_attrs) : NULL)
#define VTOILLU(vp) ((uint64_t)(VTOFUD(vp) ? VTOI(vp) : 0))
#define FUSE_NULL_ID 0
Index: sys/fs/fuse/fuse_node.c
===================================================================
--- sys/fs/fuse/fuse_node.c
+++ sys/fs/fuse/fuse_node.c
@@ -147,6 +147,7 @@
int i;
fvdat->nid = nodeid;
+ vattr_null(&fvdat->cached_attrs);
if (nodeid == FUSE_ROOT_ID) {
vp->v_vflag |= VV_ROOT;
}
Index: sys/fs/fuse/fuse_vnops.c
===================================================================
--- sys/fs/fuse/fuse_vnops.c
+++ sys/fs/fuse/fuse_vnops.c
@@ -518,10 +518,8 @@
}
goto out;
}
- cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
- if (vap != VTOVA(vp)) {
- memcpy(vap, VTOVA(vp), sizeof(*vap));
- }
+
+ cache_attrs(vp, (struct fuse_attr_out *)fdi.answ, vap);
if (vap->va_type != vnode_vtype(vp)) {
fuse_internal_vnode_disappear(vp);
err = ENOENT;
@@ -628,9 +626,15 @@
if (vnode_mount(tdvp) != vnode_mount(vp)) {
return EXDEV;
}
- if (vap->va_nlink >= FUSE_LINK_MAX) {
+
+ /*
+ * This is a seatbelt check to protect naive userspace filesystems from
+ * themselves and the limitations of the FUSE IPC protocol. If a
+ * filesystem does not allow attribute caching, assume it is capable of
+ * validating that nlink does not overflow.
+ */
+ if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX)
return EMLINK;
- }
fli.oldnodeid = VTOI(vp);
fdisp_init(&fdi, 0);
@@ -966,9 +970,11 @@
}
if (op == FUSE_GETATTR) {
- cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ);
+ cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ,
+ NULL);
} else {
- cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ);
+ cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ,
+ NULL);
}
/* Insert name into cache if appropriate. */
@@ -1644,7 +1650,7 @@
}
}
if (!err && !sizechanged) {
- cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
+ cache_attrs(vp, (struct fuse_attr_out *)fdi.answ, NULL);
}
out:
fdisp_destroy(&fdi);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 11, 12:49 AM (15 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31258150
Default Alt Text
D19088.id53610.diff (6 KB)
Attached To
Mode
D19088: FUSE: Respect userspace FS "do-not-cache" of file attributes
Attached
Detach File
Event Timeline
Log In to Comment