Lines 513-520
fuse_vnop_bmap(struct vop_bmap_args *ap)
Link Here
|
513 |
struct fuse_bmap_in *fbi; |
513 |
struct fuse_bmap_in *fbi; |
514 |
struct fuse_bmap_out *fbo; |
514 |
struct fuse_bmap_out *fbo; |
515 |
struct fuse_data *data; |
515 |
struct fuse_data *data; |
|
|
516 |
struct fuse_vnode_data *fvdat = VTOFUD(vp); |
516 |
uint64_t biosize; |
517 |
uint64_t biosize; |
517 |
off_t filesize; |
518 |
off_t fsize; |
518 |
daddr_t lbn = ap->a_bn; |
519 |
daddr_t lbn = ap->a_bn; |
519 |
daddr_t *pbn = ap->a_bnp; |
520 |
daddr_t *pbn = ap->a_bnp; |
520 |
int *runp = ap->a_runp; |
521 |
int *runp = ap->a_runp; |
Lines 547-556
fuse_vnop_bmap(struct vop_bmap_args *ap)
Link Here
|
547 |
*/ |
548 |
*/ |
548 |
if (runb != NULL) |
549 |
if (runb != NULL) |
549 |
*runb = MIN(lbn, maxrun); |
550 |
*runb = MIN(lbn, maxrun); |
550 |
if (runp != NULL) { |
551 |
if (runp != NULL && maxrun == 0) |
551 |
error = fuse_vnode_size(vp, &filesize, td->td_ucred, td); |
552 |
*runp = 0; |
|
|
553 |
else if (runp != NULL) { |
554 |
/* |
555 |
* If the file's size is cached, use that value to calculate |
556 |
* runp, even if the cache is expired. runp is only advisory, |
557 |
* and the risk of getting it wrong is not worth the cost of |
558 |
* another upcall. |
559 |
*/ |
560 |
if (fvdat->cached_attrs.va_size != VNOVAL) |
561 |
fsize = fvdat->cached_attrs.va_size; |
562 |
else |
563 |
error = fuse_vnode_size(vp, &fsize, td->td_ucred, td); |
552 |
if (error == 0) |
564 |
if (error == 0) |
553 |
*runp = MIN(MAX(0, filesize / (off_t)biosize - lbn - 1), |
565 |
*runp = MIN(MAX(0, fsize / (off_t)biosize - lbn - 1), |
554 |
maxrun); |
566 |
maxrun); |
555 |
else |
567 |
else |
556 |
*runp = 0; |
568 |
*runp = 0; |
Lines 892-898
fuse_vnop_create(struct vop_create_args *ap)
Link Here
|
892 |
} |
904 |
} |
893 |
ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create"); |
905 |
ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create"); |
894 |
fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, |
906 |
fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, |
895 |
feo->attr_valid_nsec, NULL); |
907 |
feo->attr_valid_nsec, NULL, true); |
896 |
|
908 |
|
897 |
fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo); |
909 |
fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo); |
898 |
fuse_vnode_open(*vpp, foo->open_flags, td); |
910 |
fuse_vnode_open(*vpp, foo->open_flags, td); |
Lines 1148-1154
fuse_vnop_link(struct vop_link_args *ap)
Link Here
|
1148 |
*/ |
1160 |
*/ |
1149 |
fuse_vnode_clear_attr_cache(tdvp); |
1161 |
fuse_vnode_clear_attr_cache(tdvp); |
1150 |
fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid, |
1162 |
fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid, |
1151 |
feo->attr_valid_nsec, NULL); |
1163 |
feo->attr_valid_nsec, NULL, true); |
1152 |
} |
1164 |
} |
1153 |
out: |
1165 |
out: |
1154 |
fdisp_destroy(&fdi); |
1166 |
fdisp_destroy(&fdi); |
Lines 1174-1181
fuse_lookup_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **vpp)
Link Here
|
1174 |
|
1186 |
|
1175 |
SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup, |
1187 |
SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup, |
1176 |
"int", "struct timespec*", "struct timespec*"); |
1188 |
"int", "struct timespec*", "struct timespec*"); |
1177 |
SDT_PROBE_DEFINE2(fusefs, , vnops, lookup_cache_incoherent, |
|
|
1178 |
"struct vnode*", "struct fuse_entry_out*"); |
1179 |
/* |
1189 |
/* |
1180 |
struct vnop_lookup_args { |
1190 |
struct vnop_lookup_args { |
1181 |
struct vnodeop_desc *a_desc; |
1191 |
struct vnodeop_desc *a_desc; |
Lines 1359-1411
fuse_vnop_lookup(struct vop_lookup_args *ap)
Link Here
|
1359 |
*vpp = dvp; |
1369 |
*vpp = dvp; |
1360 |
} else { |
1370 |
} else { |
1361 |
struct fuse_vnode_data *fvdat; |
1371 |
struct fuse_vnode_data *fvdat; |
1362 |
struct vattr *vap; |
|
|
1363 |
|
1372 |
|
1364 |
err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, |
1373 |
err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, |
1365 |
&vp, cnp, vtyp); |
1374 |
&vp, cnp, vtyp); |
1366 |
if (err) |
1375 |
if (err) |
1367 |
goto out; |
1376 |
goto out; |
1368 |
*vpp = vp; |
1377 |
*vpp = vp; |
1369 |
|
|
|
1370 |
/* |
1371 |
* In the case where we are looking up a FUSE node |
1372 |
* represented by an existing cached vnode, and the |
1373 |
* true size reported by FUSE_LOOKUP doesn't match |
1374 |
* the vnode's cached size, then any cached writes |
1375 |
* beyond the file's current size are lost. |
1376 |
* |
1377 |
* We can get here: |
1378 |
* * following attribute cache expiration, or |
1379 |
* * due a bug in the daemon, or |
1380 |
*/ |
1381 |
fvdat = VTOFUD(vp); |
1378 |
fvdat = VTOFUD(vp); |
1382 |
if (vnode_isreg(vp) && |
|
|
1383 |
((filesize != fvdat->cached_attrs.va_size && |
1384 |
fvdat->flag & FN_SIZECHANGE) || |
1385 |
((vap = VTOVA(vp)) && |
1386 |
filesize != vap->va_size))) |
1387 |
{ |
1388 |
SDT_PROBE2(fusefs, , vnops, lookup_cache_incoherent, vp, feo); |
1389 |
fvdat->flag &= ~FN_SIZECHANGE; |
1390 |
/* |
1391 |
* The server changed the file's size even |
1392 |
* though we had it cached, or had dirty writes |
1393 |
* in the WB cache! |
1394 |
*/ |
1395 |
printf("%s: cache incoherent on %s! " |
1396 |
"Buggy FUSE server detected. To prevent " |
1397 |
"data corruption, disable the data cache " |
1398 |
"by mounting with -o direct_io, or as " |
1399 |
"directed otherwise by your FUSE server's " |
1400 |
"documentation\n", __func__, |
1401 |
vnode_mount(vp)->mnt_stat.f_mntonname); |
1402 |
int iosize = fuse_iosize(vp); |
1403 |
v_inval_buf_range(vp, 0, INT64_MAX, iosize); |
1404 |
} |
1405 |
|
1379 |
|
1406 |
MPASS(feo != NULL); |
1380 |
MPASS(feo != NULL); |
1407 |
fuse_internal_cache_attrs(*vpp, &feo->attr, |
1381 |
fuse_internal_cache_attrs(*vpp, &feo->attr, |
1408 |
feo->attr_valid, feo->attr_valid_nsec, NULL); |
1382 |
feo->attr_valid, feo->attr_valid_nsec, NULL, true); |
1409 |
fuse_validity_2_bintime(feo->entry_valid, |
1383 |
fuse_validity_2_bintime(feo->entry_valid, |
1410 |
feo->entry_valid_nsec, |
1384 |
feo->entry_valid_nsec, |
1411 |
&fvdat->entry_cache_timeout); |
1385 |
&fvdat->entry_cache_timeout); |
Lines 2592-2600
fuse_vnop_listextattr(struct vop_listextattr_args *ap)
Link Here
|
2592 |
linux_list = fdi.answ; |
2566 |
linux_list = fdi.answ; |
2593 |
/* FUSE doesn't allow the server to return more data than requested */ |
2567 |
/* FUSE doesn't allow the server to return more data than requested */ |
2594 |
if (fdi.iosize > linux_list_len) { |
2568 |
if (fdi.iosize > linux_list_len) { |
2595 |
printf("WARNING: FUSE protocol violation. Server returned " |
2569 |
struct fuse_data *data = fuse_get_mpdata(mp); |
|
|
2570 |
|
2571 |
fuse_warn(data, FSESS_WARN_LSEXTATTR_LONG, |
2572 |
"server returned " |
2596 |
"more extended attribute data than requested; " |
2573 |
"more extended attribute data than requested; " |
2597 |
"should've returned ERANGE instead"); |
2574 |
"should've returned ERANGE instead."); |
2598 |
} else { |
2575 |
} else { |
2599 |
/* But returning less data is fine */ |
2576 |
/* But returning less data is fine */ |
2600 |
linux_list_len = fdi.iosize; |
2577 |
linux_list_len = fdi.iosize; |