|
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; |