mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 14:26:03 -04:00
tarfs: Implement VOP_BMAP
This lets tarfs provide readahead/behind hints to the VFS, which helps memory-mapped I/O performance, important when running faulting in executables out of a tarfs mount as one might if tarfs is used to back the root filesystem, for example. The improvement is particularly noticeable when the backing tarball is zstd-compressed. The implementation simply returns the extent of the virtual block containing the target offset, clamped by the maximum I/O size. This is perhaps simplistic; it effectively just chooses values that would correspond to a single VOP_READ call in tarfs_read_file(). Reviewed by: des, kib MFC after: 1 month Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D44626
This commit is contained in:
parent
663a704a58
commit
a0895e394d
1 changed files with 55 additions and 0 deletions
|
|
@ -125,6 +125,60 @@ tarfs_access(struct vop_access_args *ap)
|
|||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
tarfs_bmap(struct vop_bmap_args *ap)
|
||||
{
|
||||
struct tarfs_node *tnp;
|
||||
struct vnode *vp;
|
||||
off_t off;
|
||||
uint64_t iosize;
|
||||
int ra, rb, rmax;
|
||||
|
||||
vp = ap->a_vp;
|
||||
iosize = vp->v_mount->mnt_stat.f_iosize;
|
||||
|
||||
if (ap->a_bop != NULL)
|
||||
*ap->a_bop = &vp->v_bufobj;
|
||||
if (ap->a_bnp != NULL)
|
||||
*ap->a_bnp = ap->a_bn * btodb(iosize);
|
||||
if (ap->a_runp == NULL)
|
||||
return (0);
|
||||
|
||||
tnp = VP_TO_TARFS_NODE(vp);
|
||||
off = ap->a_bn * iosize;
|
||||
|
||||
ra = rb = 0;
|
||||
for (u_int i = 0; i < tnp->nblk; i++) {
|
||||
off_t bs, be;
|
||||
|
||||
bs = tnp->blk[i].o;
|
||||
be = tnp->blk[i].o + tnp->blk[i].l;
|
||||
if (off > be)
|
||||
continue;
|
||||
else if (off < bs) {
|
||||
/* We're in a hole. */
|
||||
ra = bs - off < iosize ?
|
||||
0 : howmany(bs - (off + iosize), iosize);
|
||||
rb = howmany(off - (i == 0 ?
|
||||
0 : tnp->blk[i - 1].o + tnp->blk[i - 1].l),
|
||||
iosize);
|
||||
break;
|
||||
} else {
|
||||
/* We'll be reading from the backing file. */
|
||||
ra = be - off < iosize ?
|
||||
0 : howmany(be - (off + iosize), iosize);
|
||||
rb = howmany(off - bs, iosize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rmax = vp->v_mount->mnt_iosize_max / iosize - 1;
|
||||
*ap->a_runp = imin(ra, rmax);
|
||||
if (ap->a_runb != NULL)
|
||||
*ap->a_runb = imin(rb, rmax);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
tarfs_getattr(struct vop_getattr_args *ap)
|
||||
{
|
||||
|
|
@ -629,6 +683,7 @@ struct vop_vector tarfs_vnodeops = {
|
|||
.vop_default = &default_vnodeops,
|
||||
|
||||
.vop_access = tarfs_access,
|
||||
.vop_bmap = tarfs_bmap,
|
||||
.vop_cachedlookup = tarfs_lookup,
|
||||
.vop_close = tarfs_close,
|
||||
.vop_getattr = tarfs_getattr,
|
||||
|
|
|
|||
Loading…
Reference in a new issue