Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106131447
D30780.id90973.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
D30780.id90973.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 10:22 PM (11 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15608353
Default Alt Text
D30780.id90973.diff (6 KB)
Attached To
Mode
D30780: fusefs: improve warnings about buggy FUSE servers
Attached
Detach File
Event Timeline
Log In to Comment