Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fuse/fuse_vfsops.c
Show First 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct fuse_data *data = fuse_get_mpdata(mp); | struct fuse_data *data = fuse_get_mpdata(mp); | ||||
uint64_t nodeid = ino; | uint64_t nodeid = ino; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct fuse_dispatcher fdi; | struct fuse_dispatcher fdi; | ||||
struct fuse_entry_out *feo; | struct fuse_entry_out *feo; | ||||
struct fuse_vnode_data *fvdat; | struct fuse_vnode_data *fvdat; | ||||
const char dot[] = "."; | const char dot[] = "."; | ||||
off_t filesize; | |||||
enum vtype vtyp; | enum vtype vtyp; | ||||
int error; | int error; | ||||
if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) { | if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) { | ||||
/* | /* | ||||
* Unreachable unless you do something stupid, like export a | * Unreachable unless you do something stupid, like export a | ||||
* nullfs mount of a fusefs file system. | * nullfs mount of a fusefs file system. | ||||
*/ | */ | ||||
Show All 20 Lines | if (feo->nodeid == 0) { | ||||
error = ENOENT; | error = ENOENT; | ||||
goto out; | goto out; | ||||
} | } | ||||
vtyp = IFTOVT(feo->attr.mode); | vtyp = IFTOVT(feo->attr.mode); | ||||
error = fuse_vnode_get(mp, feo, nodeid, NULL, vpp, NULL, vtyp); | error = fuse_vnode_get(mp, feo, nodeid, NULL, vpp, NULL, vtyp); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
filesize = feo->attr.size; | |||||
/* | |||||
* 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, 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 | |||||
*/ | |||||
fvdat = VTOFUD(*vpp); | fvdat = VTOFUD(*vpp); | ||||
if (vnode_isreg(*vpp) && | |||||
filesize != fvdat->cached_attrs.va_size && | |||||
fvdat->flag & FN_SIZECHANGE) { | |||||
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; | |||||
} | |||||
fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, | fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, | ||||
feo->attr_valid_nsec, NULL); | feo->attr_valid_nsec, NULL, true); | ||||
fuse_validity_2_bintime(feo->entry_valid, feo->entry_valid_nsec, | fuse_validity_2_bintime(feo->entry_valid, feo->entry_valid_nsec, | ||||
&fvdat->entry_cache_timeout); | &fvdat->entry_cache_timeout); | ||||
out: | out: | ||||
fdisp_destroy(&fdi); | fdisp_destroy(&fdi); | ||||
return error; | return error; | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 89 Lines • Show Last 20 Lines |