Page MenuHomeFreeBSD

D30780.diff
No OneTemporary

D30780.diff

diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c
--- a/sys/fs/fuse/fuse_internal.c
+++ b/sys/fs/fuse/fuse_internal.c
@@ -870,9 +870,6 @@
fdisp_destroy(&fdi);
}
-SDT_PROBE_DEFINE2(fusefs, , internal, getattr_cache_incoherent,
- "struct vnode*", "struct fuse_attr_out*");
-
/* Fetch the vnode's attributes from the daemon*/
int
fuse_internal_do_getattr(struct vnode *vp, struct vattr *vap,
@@ -922,14 +919,14 @@
* The server changed the file's size even though we had it
* cached! That's a server bug.
*/
- SDT_PROBE2(fusefs, , internal, getattr_cache_incoherent, vp,
- fao);
- printf("%s: cache incoherent on %s! "
- "Buggy FUSE server detected. To prevent data corruption, "
- "disable the data cache by mounting with -o direct_io, or "
- "as directed otherwise by your FUSE server's "
- "documentation\n", __func__,
- vnode_mount(vp)->mnt_stat.f_mntonname);
+ struct mount *mp = vnode_mount(vp);
+ struct fuse_data *data = fuse_get_mpdata(mp);
+
+ fuse_warn(data, FSESS_WARN_CACHE_INCOHERENT,
+ "cache incoherent! "
+ "To prevent data corruption, disable the data cache "
+ "by mounting with -o direct_io, or as directed "
+ "otherwise by your FUSE server's documentation.");
int iosize = fuse_iosize(vp);
v_inval_buf_range(vp, 0, INT64_MAX, iosize);
}
diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c
--- a/sys/fs/fuse/fuse_io.c
+++ b/sys/fs/fuse/fuse_io.c
@@ -576,16 +576,16 @@
fvdat->flag &= ~FN_SIZECHANGE;
if (diff < 0) {
- printf("WARNING: misbehaving FUSE filesystem "
- "wrote more data than we provided it\n");
+ fuse_warn(data, FSESS_WARN_WROTE_LONG,
+ "wrote more data than we provided it.");
err = EINVAL;
break;
} else if (diff > 0) {
/* Short write */
if (!direct_io) {
- printf("WARNING: misbehaving FUSE filesystem: "
+ fuse_warn(data, FSESS_WARN_SHORT_WRITE,
"short writes are only allowed with "
- "direct_io\n");
+ "direct_io.");
}
if (ioflag & IO_DIRECT) {
/* Return early */
diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h
--- a/sys/fs/fuse/fuse_ipc.h
+++ b/sys/fs/fuse/fuse_ipc.h
@@ -233,6 +233,11 @@
#define FSESS_POSIX_LOCKS 0x2000 /* daemon supports POSIX locks */
#define FSESS_EXPORT_SUPPORT 0x10000 /* daemon supports NFS-style lookups */
#define FSESS_INTR 0x20000 /* interruptible mounts */
+#define FSESS_WARN_SHORT_WRITE 0x40000 /* Short write without direct_io */
+#define FSESS_WARN_WROTE_LONG 0x80000 /* Wrote more data than provided */
+#define FSESS_WARN_LSEXTATTR_LONG 0x100000 /* Returned too many extattrs */
+#define FSESS_WARN_CACHE_INCOHERENT 0x200000 /* Read cache incoherent */
+#define FSESS_WARN_WB_CACHE_INCOHERENT 0x400000 /* WB cache incoherent */
#define FSESS_MNTOPTS_MASK ( \
FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \
FSESS_DEFAULT_PERMISSIONS | FSESS_INTR)
@@ -394,6 +399,9 @@
data->fuse_libabi_minor >= abi_min));
}
+/* Print msg as a warning to the console, but no more than once per session */
+void fuse_warn(struct fuse_data *data, unsigned flag, const char *msg);
+
struct fuse_data *fdata_alloc(struct cdev *dev, struct ucred *cred);
void fdata_trydestroy(struct fuse_data *data);
void fdata_set_dead(struct fuse_data *data);
diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c
--- a/sys/fs/fuse/fuse_ipc.c
+++ b/sys/fs/fuse/fuse_ipc.c
@@ -1073,3 +1073,17 @@
counter_u64_free(fuse_ticket_count);
uma_zdestroy(ticket_zone);
}
+
+SDT_PROBE_DEFINE3(fusefs,, ipc, warn, "struct fuse_data*", "unsigned", "char*");
+void
+fuse_warn(struct fuse_data *data, unsigned flag, const char *msg)
+{
+ SDT_PROBE3(fusefs, , ipc, warn, data, flag, msg);
+ if (!(data->dataflags & flag)) {
+ printf("WARNING: FUSE protocol violation for server mounted at "
+ "%s: %s "
+ "This warning will not be repeated.\n",
+ data->mp->mnt_stat.f_mntonname, msg);
+ data->dataflags |= flag;
+ }
+}
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -592,9 +592,26 @@
if (vnode_isreg(*vpp) &&
filesize != fvdat->cached_attrs.va_size &&
fvdat->flag & FN_SIZECHANGE) {
- printf("%s: WB cache incoherent on %s!\n", __func__,
- vnode_mount(*vpp)->mnt_stat.f_mntonname);
-
+ if (data->cache_mode == fuse_data_cache_mode) {
+ const char *msg;
+
+ if (fuse_libabi_geq(data, 7, 23)) {
+ msg = "writeback cache incoherent!."
+ "To prevent data corruption, disable "
+ "the writeback cache according to your "
+ "FUSE server's documentation.";
+ } else {
+ msg = "writeback cache incoherent!."
+ "To prevent data corruption, disable "
+ "the writeback cache by setting "
+ "vfs.fusefs.data_cache_mode to 0 or 1.";
+ }
+ fuse_warn(data, FSESS_WARN_WB_CACHE_INCOHERENT, msg);
+ } else {
+ /* If we get here, it's likely a fusefs kernel bug */
+ printf("%s: WB cache incoherent on %s!\n", __func__,
+ vnode_mount(*vpp)->mnt_stat.f_mntonname);
+ }
fvdat->flag &= ~FN_SIZECHANGE;
}
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -1177,8 +1177,6 @@
SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup,
"int", "struct timespec*", "struct timespec*");
-SDT_PROBE_DEFINE2(fusefs, , vnops, lookup_cache_incoherent,
- "struct vnode*", "struct fuse_entry_out*");
/*
struct vnop_lookup_args {
struct vnodeop_desc *a_desc;
@@ -1388,20 +1386,19 @@
((vap = VTOVA(vp)) &&
filesize != vap->va_size)))
{
- SDT_PROBE2(fusefs, , vnops, lookup_cache_incoherent, vp, feo);
fvdat->flag &= ~FN_SIZECHANGE;
/*
* The server changed the file's size even
* though we had it cached, or had dirty writes
* in the WB cache!
*/
- printf("%s: cache incoherent on %s! "
- "Buggy FUSE server detected. To prevent "
+ fuse_warn(data, FSESS_WARN_CACHE_INCOHERENT,
+ "cache incoherent! "
+ "To prevent "
"data corruption, disable the data cache "
"by mounting with -o direct_io, or as "
"directed otherwise by your FUSE server's "
- "documentation\n", __func__,
- vnode_mount(vp)->mnt_stat.f_mntonname);
+ "documentation.");
int iosize = fuse_iosize(vp);
v_inval_buf_range(vp, 0, INT64_MAX, iosize);
}
@@ -2595,9 +2592,12 @@
linux_list = fdi.answ;
/* FUSE doesn't allow the server to return more data than requested */
if (fdi.iosize > linux_list_len) {
- printf("WARNING: FUSE protocol violation. Server returned "
+ struct fuse_data *data = fuse_get_mpdata(mp);
+
+ fuse_warn(data, FSESS_WARN_LSEXTATTR_LONG,
+ "server returned "
"more extended attribute data than requested; "
- "should've returned ERANGE instead");
+ "should've returned ERANGE instead.");
} else {
/* But returning less data is fine */
linux_list_len = fdi.iosize;

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 2:05 PM (21 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14698995
Default Alt Text
D30780.diff (6 KB)

Event Timeline