169d94f4cSDag-Erling Smørgrav /*- 269d94f4cSDag-Erling Smørgrav * SPDX-License-Identifier: BSD-2-Clause 369d94f4cSDag-Erling Smørgrav * 469d94f4cSDag-Erling Smørgrav * Copyright (c) 2013 Juniper Networks, Inc. 569d94f4cSDag-Erling Smørgrav * Copyright (c) 2022-2023 Klara, Inc. 669d94f4cSDag-Erling Smørgrav * 769d94f4cSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 869d94f4cSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 969d94f4cSDag-Erling Smørgrav * are met: 1069d94f4cSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 1169d94f4cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 1269d94f4cSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 1369d94f4cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 1469d94f4cSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 1569d94f4cSDag-Erling Smørgrav * 1669d94f4cSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1769d94f4cSDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1869d94f4cSDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1969d94f4cSDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2069d94f4cSDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2169d94f4cSDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2269d94f4cSDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2369d94f4cSDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2469d94f4cSDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2569d94f4cSDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2669d94f4cSDag-Erling Smørgrav * SUCH DAMAGE. 2769d94f4cSDag-Erling Smørgrav */ 2869d94f4cSDag-Erling Smørgrav 2969d94f4cSDag-Erling Smørgrav #include "opt_tarfs.h" 3069d94f4cSDag-Erling Smørgrav 3169d94f4cSDag-Erling Smørgrav #include <sys/param.h> 3269d94f4cSDag-Erling Smørgrav #include <sys/systm.h> 3369d94f4cSDag-Erling Smørgrav #include <sys/bio.h> 3469d94f4cSDag-Erling Smørgrav #include <sys/buf.h> 3569d94f4cSDag-Erling Smørgrav #include <sys/dirent.h> 3669d94f4cSDag-Erling Smørgrav #include <sys/fcntl.h> 3769d94f4cSDag-Erling Smørgrav #include <sys/limits.h> 3869d94f4cSDag-Erling Smørgrav #include <sys/mount.h> 3969d94f4cSDag-Erling Smørgrav #include <sys/namei.h> 4069d94f4cSDag-Erling Smørgrav #include <sys/proc.h> 4169d94f4cSDag-Erling Smørgrav #include <sys/vnode.h> 4269d94f4cSDag-Erling Smørgrav 4369d94f4cSDag-Erling Smørgrav #include <fs/tarfs/tarfs.h> 4469d94f4cSDag-Erling Smørgrav #include <fs/tarfs/tarfs_dbg.h> 4569d94f4cSDag-Erling Smørgrav 4669d94f4cSDag-Erling Smørgrav static int 4769d94f4cSDag-Erling Smørgrav tarfs_open(struct vop_open_args *ap) 4869d94f4cSDag-Erling Smørgrav { 4969d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 5069d94f4cSDag-Erling Smørgrav struct vnode *vp; 5169d94f4cSDag-Erling Smørgrav 5269d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 5369d94f4cSDag-Erling Smørgrav MPASS(VOP_ISLOCKED(vp)); 5469d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 5569d94f4cSDag-Erling Smørgrav 5669d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s, %o)\n", __func__, 5769d94f4cSDag-Erling Smørgrav tnp, tnp->name, ap->a_mode); 5869d94f4cSDag-Erling Smørgrav 5969d94f4cSDag-Erling Smørgrav if (vp->v_type != VREG && vp->v_type != VDIR) 6069d94f4cSDag-Erling Smørgrav return (EOPNOTSUPP); 6169d94f4cSDag-Erling Smørgrav 6269d94f4cSDag-Erling Smørgrav vnode_create_vobject(vp, tnp->size, ap->a_td); 6369d94f4cSDag-Erling Smørgrav return (0); 6469d94f4cSDag-Erling Smørgrav } 6569d94f4cSDag-Erling Smørgrav 6669d94f4cSDag-Erling Smørgrav static int 6769d94f4cSDag-Erling Smørgrav tarfs_close(struct vop_close_args *ap) 6869d94f4cSDag-Erling Smørgrav { 6969d94f4cSDag-Erling Smørgrav #ifdef TARFS_DEBUG 7069d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 7169d94f4cSDag-Erling Smørgrav struct vnode *vp; 7269d94f4cSDag-Erling Smørgrav 7369d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 7469d94f4cSDag-Erling Smørgrav 7569d94f4cSDag-Erling Smørgrav MPASS(VOP_ISLOCKED(vp)); 7669d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 7769d94f4cSDag-Erling Smørgrav 7869d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s)\n", __func__, 7969d94f4cSDag-Erling Smørgrav tnp, tnp->name); 8069d94f4cSDag-Erling Smørgrav #else 8169d94f4cSDag-Erling Smørgrav (void)ap; 8269d94f4cSDag-Erling Smørgrav #endif 8369d94f4cSDag-Erling Smørgrav return (0); 8469d94f4cSDag-Erling Smørgrav } 8569d94f4cSDag-Erling Smørgrav 8669d94f4cSDag-Erling Smørgrav static int 8769d94f4cSDag-Erling Smørgrav tarfs_access(struct vop_access_args *ap) 8869d94f4cSDag-Erling Smørgrav { 8969d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 9069d94f4cSDag-Erling Smørgrav struct vnode *vp; 9169d94f4cSDag-Erling Smørgrav accmode_t accmode; 9269d94f4cSDag-Erling Smørgrav struct ucred *cred; 9369d94f4cSDag-Erling Smørgrav int error; 9469d94f4cSDag-Erling Smørgrav 9569d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 9669d94f4cSDag-Erling Smørgrav accmode = ap->a_accmode; 9769d94f4cSDag-Erling Smørgrav cred = ap->a_cred; 9869d94f4cSDag-Erling Smørgrav 9969d94f4cSDag-Erling Smørgrav MPASS(VOP_ISLOCKED(vp)); 10069d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 10169d94f4cSDag-Erling Smørgrav 10269d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s, %o)\n", __func__, 10369d94f4cSDag-Erling Smørgrav tnp, tnp->name, accmode); 10469d94f4cSDag-Erling Smørgrav 10569d94f4cSDag-Erling Smørgrav switch (vp->v_type) { 10669d94f4cSDag-Erling Smørgrav case VDIR: 10769d94f4cSDag-Erling Smørgrav case VLNK: 10869d94f4cSDag-Erling Smørgrav case VREG: 10969d94f4cSDag-Erling Smørgrav if ((accmode & VWRITE) != 0) 11069d94f4cSDag-Erling Smørgrav return (EROFS); 11169d94f4cSDag-Erling Smørgrav break; 11269d94f4cSDag-Erling Smørgrav case VBLK: 11369d94f4cSDag-Erling Smørgrav case VCHR: 11469d94f4cSDag-Erling Smørgrav case VFIFO: 11569d94f4cSDag-Erling Smørgrav break; 11669d94f4cSDag-Erling Smørgrav default: 11769d94f4cSDag-Erling Smørgrav return (EINVAL); 11869d94f4cSDag-Erling Smørgrav } 11969d94f4cSDag-Erling Smørgrav 12069d94f4cSDag-Erling Smørgrav if ((accmode & VWRITE) != 0) 12169d94f4cSDag-Erling Smørgrav return (EPERM); 12269d94f4cSDag-Erling Smørgrav 12369d94f4cSDag-Erling Smørgrav error = vaccess(vp->v_type, tnp->mode, tnp->uid, 12469d94f4cSDag-Erling Smørgrav tnp->gid, accmode, cred); 12569d94f4cSDag-Erling Smørgrav return (error); 12669d94f4cSDag-Erling Smørgrav } 12769d94f4cSDag-Erling Smørgrav 12869d94f4cSDag-Erling Smørgrav static int 129a0895e39SMark Johnston tarfs_bmap(struct vop_bmap_args *ap) 130a0895e39SMark Johnston { 131a0895e39SMark Johnston struct tarfs_node *tnp; 132a0895e39SMark Johnston struct vnode *vp; 133a0895e39SMark Johnston off_t off; 134a0895e39SMark Johnston uint64_t iosize; 135a0895e39SMark Johnston int ra, rb, rmax; 136a0895e39SMark Johnston 137a0895e39SMark Johnston vp = ap->a_vp; 138a0895e39SMark Johnston iosize = vp->v_mount->mnt_stat.f_iosize; 139a0895e39SMark Johnston 140a0895e39SMark Johnston if (ap->a_bop != NULL) 141a0895e39SMark Johnston *ap->a_bop = &vp->v_bufobj; 142a0895e39SMark Johnston if (ap->a_bnp != NULL) 143a0895e39SMark Johnston *ap->a_bnp = ap->a_bn * btodb(iosize); 144a0895e39SMark Johnston if (ap->a_runp == NULL) 145a0895e39SMark Johnston return (0); 146a0895e39SMark Johnston 147a0895e39SMark Johnston tnp = VP_TO_TARFS_NODE(vp); 148a0895e39SMark Johnston off = ap->a_bn * iosize; 149a0895e39SMark Johnston 150a0895e39SMark Johnston ra = rb = 0; 151a0895e39SMark Johnston for (u_int i = 0; i < tnp->nblk; i++) { 152a0895e39SMark Johnston off_t bs, be; 153a0895e39SMark Johnston 154a0895e39SMark Johnston bs = tnp->blk[i].o; 155a0895e39SMark Johnston be = tnp->blk[i].o + tnp->blk[i].l; 156a0895e39SMark Johnston if (off > be) 157a0895e39SMark Johnston continue; 158a0895e39SMark Johnston else if (off < bs) { 159a0895e39SMark Johnston /* We're in a hole. */ 160a0895e39SMark Johnston ra = bs - off < iosize ? 161a0895e39SMark Johnston 0 : howmany(bs - (off + iosize), iosize); 162a0895e39SMark Johnston rb = howmany(off - (i == 0 ? 163a0895e39SMark Johnston 0 : tnp->blk[i - 1].o + tnp->blk[i - 1].l), 164a0895e39SMark Johnston iosize); 165a0895e39SMark Johnston break; 166a0895e39SMark Johnston } else { 167a0895e39SMark Johnston /* We'll be reading from the backing file. */ 168a0895e39SMark Johnston ra = be - off < iosize ? 169a0895e39SMark Johnston 0 : howmany(be - (off + iosize), iosize); 170a0895e39SMark Johnston rb = howmany(off - bs, iosize); 171a0895e39SMark Johnston break; 172a0895e39SMark Johnston } 173a0895e39SMark Johnston } 174a0895e39SMark Johnston 175a0895e39SMark Johnston rmax = vp->v_mount->mnt_iosize_max / iosize - 1; 176a0895e39SMark Johnston *ap->a_runp = imin(ra, rmax); 177a0895e39SMark Johnston if (ap->a_runb != NULL) 178a0895e39SMark Johnston *ap->a_runb = imin(rb, rmax); 179a0895e39SMark Johnston return (0); 180a0895e39SMark Johnston } 181a0895e39SMark Johnston 182a0895e39SMark Johnston static int 18369d94f4cSDag-Erling Smørgrav tarfs_getattr(struct vop_getattr_args *ap) 18469d94f4cSDag-Erling Smørgrav { 18569d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 18669d94f4cSDag-Erling Smørgrav struct vnode *vp; 18769d94f4cSDag-Erling Smørgrav struct vattr *vap; 18869d94f4cSDag-Erling Smørgrav 18969d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 19069d94f4cSDag-Erling Smørgrav vap = ap->a_vap; 19169d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 19269d94f4cSDag-Erling Smørgrav 19369d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s)\n", __func__, 19469d94f4cSDag-Erling Smørgrav tnp, tnp->name); 19569d94f4cSDag-Erling Smørgrav 19669d94f4cSDag-Erling Smørgrav vap->va_type = vp->v_type; 19769d94f4cSDag-Erling Smørgrav vap->va_mode = tnp->mode; 19869d94f4cSDag-Erling Smørgrav vap->va_nlink = tnp->nlink; 19969d94f4cSDag-Erling Smørgrav vap->va_gid = tnp->gid; 20069d94f4cSDag-Erling Smørgrav vap->va_uid = tnp->uid; 20169d94f4cSDag-Erling Smørgrav vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 20269d94f4cSDag-Erling Smørgrav vap->va_fileid = tnp->ino; 20369d94f4cSDag-Erling Smørgrav vap->va_size = tnp->size; 20469d94f4cSDag-Erling Smørgrav vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 20569d94f4cSDag-Erling Smørgrav vap->va_atime = tnp->atime; 20669d94f4cSDag-Erling Smørgrav vap->va_ctime = tnp->ctime; 20769d94f4cSDag-Erling Smørgrav vap->va_mtime = tnp->mtime; 20869d94f4cSDag-Erling Smørgrav vap->va_birthtime = tnp->birthtime; 20969d94f4cSDag-Erling Smørgrav vap->va_gen = tnp->gen; 21069d94f4cSDag-Erling Smørgrav vap->va_flags = tnp->flags; 21169d94f4cSDag-Erling Smørgrav vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? 21269d94f4cSDag-Erling Smørgrav tnp->rdev : NODEV; 21369d94f4cSDag-Erling Smørgrav vap->va_bytes = round_page(tnp->physize); 21469d94f4cSDag-Erling Smørgrav vap->va_filerev = 0; 21569d94f4cSDag-Erling Smørgrav 21669d94f4cSDag-Erling Smørgrav return (0); 21769d94f4cSDag-Erling Smørgrav } 21869d94f4cSDag-Erling Smørgrav 21969d94f4cSDag-Erling Smørgrav static int 22069d94f4cSDag-Erling Smørgrav tarfs_lookup(struct vop_cachedlookup_args *ap) 22169d94f4cSDag-Erling Smørgrav { 222af0435e1SDag-Erling Smørgrav struct tarfs_mount *tmp; 22369d94f4cSDag-Erling Smørgrav struct tarfs_node *dirnode, *parent, *tnp; 22469d94f4cSDag-Erling Smørgrav struct componentname *cnp; 22569d94f4cSDag-Erling Smørgrav struct vnode *dvp, **vpp; 22669d94f4cSDag-Erling Smørgrav #ifdef TARFS_DEBUG 22769d94f4cSDag-Erling Smørgrav struct vnode *vp; 22869d94f4cSDag-Erling Smørgrav #endif 22969d94f4cSDag-Erling Smørgrav int error; 23069d94f4cSDag-Erling Smørgrav 23169d94f4cSDag-Erling Smørgrav dvp = ap->a_dvp; 23269d94f4cSDag-Erling Smørgrav vpp = ap->a_vpp; 23369d94f4cSDag-Erling Smørgrav cnp = ap->a_cnp; 23469d94f4cSDag-Erling Smørgrav 23569d94f4cSDag-Erling Smørgrav *vpp = NULLVP; 23669d94f4cSDag-Erling Smørgrav dirnode = VP_TO_TARFS_NODE(dvp); 23769d94f4cSDag-Erling Smørgrav parent = dirnode->parent; 238af0435e1SDag-Erling Smørgrav tmp = dirnode->tmp; 23969d94f4cSDag-Erling Smørgrav tnp = NULL; 24069d94f4cSDag-Erling Smørgrav 24169d94f4cSDag-Erling Smørgrav TARFS_DPF(LOOKUP, "%s(%p=%s, %.*s)\n", __func__, 24269d94f4cSDag-Erling Smørgrav dirnode, dirnode->name, 24369d94f4cSDag-Erling Smørgrav (int)cnp->cn_namelen, cnp->cn_nameptr); 24469d94f4cSDag-Erling Smørgrav 24569d94f4cSDag-Erling Smørgrav error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, curthread); 24669d94f4cSDag-Erling Smørgrav if (error != 0) 24769d94f4cSDag-Erling Smørgrav return (error); 24869d94f4cSDag-Erling Smørgrav 24969d94f4cSDag-Erling Smørgrav if (cnp->cn_flags & ISDOTDOT) { 25069d94f4cSDag-Erling Smørgrav /* Do not allow .. on the root node */ 25169d94f4cSDag-Erling Smørgrav if (parent == NULL || parent == dirnode) 25269d94f4cSDag-Erling Smørgrav return (ENOENT); 25369d94f4cSDag-Erling Smørgrav 25469d94f4cSDag-Erling Smørgrav /* Allocate a new vnode on the matching entry */ 25569d94f4cSDag-Erling Smørgrav error = vn_vget_ino(dvp, parent->ino, cnp->cn_lkflags, 25669d94f4cSDag-Erling Smørgrav vpp); 25769d94f4cSDag-Erling Smørgrav if (error != 0) 25869d94f4cSDag-Erling Smørgrav return (error); 25969d94f4cSDag-Erling Smørgrav } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 26069d94f4cSDag-Erling Smørgrav VREF(dvp); 26169d94f4cSDag-Erling Smørgrav *vpp = dvp; 26269d94f4cSDag-Erling Smørgrav #ifdef TARFS_DEBUG 26369d94f4cSDag-Erling Smørgrav } else if (dirnode == dirnode->tmp->root && 26469d94f4cSDag-Erling Smørgrav (vp = dirnode->tmp->znode) != NULL && 26569d94f4cSDag-Erling Smørgrav cnp->cn_namelen == TARFS_ZIO_NAMELEN && 26669d94f4cSDag-Erling Smørgrav memcmp(cnp->cn_nameptr, TARFS_ZIO_NAME, TARFS_ZIO_NAMELEN) == 0) { 26769d94f4cSDag-Erling Smørgrav error = vn_lock(vp, cnp->cn_lkflags); 26869d94f4cSDag-Erling Smørgrav if (error != 0) 26969d94f4cSDag-Erling Smørgrav return (error); 27069d94f4cSDag-Erling Smørgrav vref(vp); 27169d94f4cSDag-Erling Smørgrav *vpp = vp; 27269d94f4cSDag-Erling Smørgrav return (0); 27369d94f4cSDag-Erling Smørgrav #endif 27469d94f4cSDag-Erling Smørgrav } else { 27569d94f4cSDag-Erling Smørgrav tnp = tarfs_lookup_node(dirnode, NULL, cnp); 27669d94f4cSDag-Erling Smørgrav if (tnp == NULL) { 27769d94f4cSDag-Erling Smørgrav TARFS_DPF(LOOKUP, "%s(%p=%s, %.*s): file not found\n", __func__, 27869d94f4cSDag-Erling Smørgrav dirnode, dirnode->name, 27969d94f4cSDag-Erling Smørgrav (int)cnp->cn_namelen, cnp->cn_nameptr); 28069d94f4cSDag-Erling Smørgrav return (ENOENT); 28169d94f4cSDag-Erling Smørgrav } 28269d94f4cSDag-Erling Smørgrav 28369d94f4cSDag-Erling Smørgrav if ((cnp->cn_flags & ISLASTCN) == 0 && 28469d94f4cSDag-Erling Smørgrav (tnp->type != VDIR && tnp->type != VLNK)) 28569d94f4cSDag-Erling Smørgrav return (ENOTDIR); 28669d94f4cSDag-Erling Smørgrav 287af0435e1SDag-Erling Smørgrav error = VFS_VGET(tmp->vfs, tnp->ino, cnp->cn_lkflags, vpp); 28869d94f4cSDag-Erling Smørgrav if (error != 0) 28969d94f4cSDag-Erling Smørgrav return (error); 29069d94f4cSDag-Erling Smørgrav } 29169d94f4cSDag-Erling Smørgrav 29269d94f4cSDag-Erling Smørgrav #ifdef TARFS_DEBUG 29369d94f4cSDag-Erling Smørgrav if (tnp == NULL) 29469d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(*vpp); 29569d94f4cSDag-Erling Smørgrav TARFS_DPF(LOOKUP, "%s: found vnode %p, tarfs_node %p\n", __func__, 29669d94f4cSDag-Erling Smørgrav *vpp, tnp); 29769d94f4cSDag-Erling Smørgrav #endif /* TARFS_DEBUG */ 29869d94f4cSDag-Erling Smørgrav 299742f4b77SGordon Bergling /* Store the result of the cache if MAKEENTRY is specified in flags */ 30069d94f4cSDag-Erling Smørgrav if ((cnp->cn_flags & MAKEENTRY) != 0 && cnp->cn_nameiop != CREATE) 30169d94f4cSDag-Erling Smørgrav cache_enter(dvp, *vpp, cnp); 30269d94f4cSDag-Erling Smørgrav 30369d94f4cSDag-Erling Smørgrav return (error); 30469d94f4cSDag-Erling Smørgrav } 30569d94f4cSDag-Erling Smørgrav 30669d94f4cSDag-Erling Smørgrav static int 30769d94f4cSDag-Erling Smørgrav tarfs_readdir(struct vop_readdir_args *ap) 30869d94f4cSDag-Erling Smørgrav { 309ce6a0c77SDag-Erling Smørgrav struct dirent cde = { }; 31069d94f4cSDag-Erling Smørgrav struct tarfs_node *current, *tnp; 31169d94f4cSDag-Erling Smørgrav struct vnode *vp; 31269d94f4cSDag-Erling Smørgrav struct uio *uio; 31369d94f4cSDag-Erling Smørgrav int *eofflag; 314fb53e7adSDag-Erling Smørgrav uint64_t **cookies; 31569d94f4cSDag-Erling Smørgrav int *ncookies; 31669d94f4cSDag-Erling Smørgrav off_t off; 31769d94f4cSDag-Erling Smørgrav u_int idx, ndirents; 31869d94f4cSDag-Erling Smørgrav int error; 31969d94f4cSDag-Erling Smørgrav 32069d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 32169d94f4cSDag-Erling Smørgrav uio = ap->a_uio; 32269d94f4cSDag-Erling Smørgrav eofflag = ap->a_eofflag; 32369d94f4cSDag-Erling Smørgrav cookies = ap->a_cookies; 32469d94f4cSDag-Erling Smørgrav ncookies = ap->a_ncookies; 32569d94f4cSDag-Erling Smørgrav 32669d94f4cSDag-Erling Smørgrav if (vp->v_type != VDIR) 32769d94f4cSDag-Erling Smørgrav return (ENOTDIR); 32869d94f4cSDag-Erling Smørgrav 32969d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 33069d94f4cSDag-Erling Smørgrav off = uio->uio_offset; 33169d94f4cSDag-Erling Smørgrav current = NULL; 33269d94f4cSDag-Erling Smørgrav ndirents = 0; 33369d94f4cSDag-Erling Smørgrav 33469d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s, %zu, %zd)\n", __func__, 33569d94f4cSDag-Erling Smørgrav tnp, tnp->name, uio->uio_offset, uio->uio_resid); 33669d94f4cSDag-Erling Smørgrav 33769d94f4cSDag-Erling Smørgrav if (uio->uio_offset == TARFS_COOKIE_EOF) { 33869d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: EOF\n", __func__); 33969d94f4cSDag-Erling Smørgrav return (0); 34069d94f4cSDag-Erling Smørgrav } 34169d94f4cSDag-Erling Smørgrav 34269d94f4cSDag-Erling Smørgrav if (uio->uio_offset == TARFS_COOKIE_DOT) { 34369d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: Generating . entry\n", __func__); 34469d94f4cSDag-Erling Smørgrav /* fake . entry */ 34569d94f4cSDag-Erling Smørgrav cde.d_fileno = tnp->ino; 34669d94f4cSDag-Erling Smørgrav cde.d_type = DT_DIR; 34769d94f4cSDag-Erling Smørgrav cde.d_namlen = 1; 34869d94f4cSDag-Erling Smørgrav cde.d_name[0] = '.'; 34969d94f4cSDag-Erling Smørgrav cde.d_name[1] = '\0'; 35069d94f4cSDag-Erling Smørgrav cde.d_reclen = GENERIC_DIRSIZ(&cde); 35169d94f4cSDag-Erling Smørgrav if (cde.d_reclen > uio->uio_resid) 35269d94f4cSDag-Erling Smørgrav goto full; 353c9ff56ceSDag-Erling Smørgrav dirent_terminate(&cde); 35469d94f4cSDag-Erling Smørgrav error = uiomove(&cde, cde.d_reclen, uio); 35569d94f4cSDag-Erling Smørgrav if (error) 35669d94f4cSDag-Erling Smørgrav return (error); 35769d94f4cSDag-Erling Smørgrav /* next is .. */ 35869d94f4cSDag-Erling Smørgrav uio->uio_offset = TARFS_COOKIE_DOTDOT; 35969d94f4cSDag-Erling Smørgrav ndirents++; 36069d94f4cSDag-Erling Smørgrav } 36169d94f4cSDag-Erling Smørgrav 36269d94f4cSDag-Erling Smørgrav if (uio->uio_offset == TARFS_COOKIE_DOTDOT) { 36369d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: Generating .. entry\n", __func__); 36469d94f4cSDag-Erling Smørgrav /* fake .. entry */ 36569d94f4cSDag-Erling Smørgrav MPASS(tnp->parent != NULL); 36669d94f4cSDag-Erling Smørgrav TARFS_NODE_LOCK(tnp->parent); 36769d94f4cSDag-Erling Smørgrav cde.d_fileno = tnp->parent->ino; 36869d94f4cSDag-Erling Smørgrav TARFS_NODE_UNLOCK(tnp->parent); 36969d94f4cSDag-Erling Smørgrav cde.d_type = DT_DIR; 37069d94f4cSDag-Erling Smørgrav cde.d_namlen = 2; 37169d94f4cSDag-Erling Smørgrav cde.d_name[0] = '.'; 37269d94f4cSDag-Erling Smørgrav cde.d_name[1] = '.'; 37369d94f4cSDag-Erling Smørgrav cde.d_name[2] = '\0'; 37469d94f4cSDag-Erling Smørgrav cde.d_reclen = GENERIC_DIRSIZ(&cde); 37569d94f4cSDag-Erling Smørgrav if (cde.d_reclen > uio->uio_resid) 37669d94f4cSDag-Erling Smørgrav goto full; 377c9ff56ceSDag-Erling Smørgrav dirent_terminate(&cde); 37869d94f4cSDag-Erling Smørgrav error = uiomove(&cde, cde.d_reclen, uio); 37969d94f4cSDag-Erling Smørgrav if (error) 38069d94f4cSDag-Erling Smørgrav return (error); 38169d94f4cSDag-Erling Smørgrav /* next is first child */ 38269d94f4cSDag-Erling Smørgrav current = TAILQ_FIRST(&tnp->dir.dirhead); 38369d94f4cSDag-Erling Smørgrav if (current == NULL) 38469d94f4cSDag-Erling Smørgrav goto done; 38569d94f4cSDag-Erling Smørgrav uio->uio_offset = current->ino; 38669d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: [%u] setting current node to %p=%s\n", 38769d94f4cSDag-Erling Smørgrav __func__, ndirents, current, current->name); 38869d94f4cSDag-Erling Smørgrav ndirents++; 38969d94f4cSDag-Erling Smørgrav } 39069d94f4cSDag-Erling Smørgrav 39169d94f4cSDag-Erling Smørgrav /* resuming previous call */ 39269d94f4cSDag-Erling Smørgrav if (current == NULL) { 39369d94f4cSDag-Erling Smørgrav current = tarfs_lookup_dir(tnp, uio->uio_offset); 39469d94f4cSDag-Erling Smørgrav if (current == NULL) { 39569d94f4cSDag-Erling Smørgrav error = EINVAL; 39669d94f4cSDag-Erling Smørgrav goto done; 39769d94f4cSDag-Erling Smørgrav } 39869d94f4cSDag-Erling Smørgrav uio->uio_offset = current->ino; 39969d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: [%u] setting current node to %p=%s\n", 40069d94f4cSDag-Erling Smørgrav __func__, ndirents, current, current->name); 40169d94f4cSDag-Erling Smørgrav } 40269d94f4cSDag-Erling Smørgrav 40369d94f4cSDag-Erling Smørgrav for (;;) { 40469d94f4cSDag-Erling Smørgrav cde.d_fileno = current->ino; 40569d94f4cSDag-Erling Smørgrav switch (current->type) { 40669d94f4cSDag-Erling Smørgrav case VBLK: 40769d94f4cSDag-Erling Smørgrav cde.d_type = DT_BLK; 40869d94f4cSDag-Erling Smørgrav break; 40969d94f4cSDag-Erling Smørgrav case VCHR: 41069d94f4cSDag-Erling Smørgrav cde.d_type = DT_CHR; 41169d94f4cSDag-Erling Smørgrav break; 41269d94f4cSDag-Erling Smørgrav case VDIR: 41369d94f4cSDag-Erling Smørgrav cde.d_type = DT_DIR; 41469d94f4cSDag-Erling Smørgrav break; 41569d94f4cSDag-Erling Smørgrav case VFIFO: 41669d94f4cSDag-Erling Smørgrav cde.d_type = DT_FIFO; 41769d94f4cSDag-Erling Smørgrav break; 41869d94f4cSDag-Erling Smørgrav case VLNK: 41969d94f4cSDag-Erling Smørgrav cde.d_type = DT_LNK; 42069d94f4cSDag-Erling Smørgrav break; 42169d94f4cSDag-Erling Smørgrav case VREG: 42269d94f4cSDag-Erling Smørgrav cde.d_type = DT_REG; 42369d94f4cSDag-Erling Smørgrav break; 42469d94f4cSDag-Erling Smørgrav default: 42569d94f4cSDag-Erling Smørgrav panic("%s: tarfs_node %p, type %d\n", __func__, 42669d94f4cSDag-Erling Smørgrav current, current->type); 42769d94f4cSDag-Erling Smørgrav } 42869d94f4cSDag-Erling Smørgrav cde.d_namlen = current->namelen; 42969d94f4cSDag-Erling Smørgrav MPASS(tnp->namelen < sizeof(cde.d_name)); 43069d94f4cSDag-Erling Smørgrav (void)memcpy(cde.d_name, current->name, current->namelen); 43169d94f4cSDag-Erling Smørgrav cde.d_name[current->namelen] = '\0'; 43269d94f4cSDag-Erling Smørgrav cde.d_reclen = GENERIC_DIRSIZ(&cde); 43369d94f4cSDag-Erling Smørgrav if (cde.d_reclen > uio->uio_resid) 43469d94f4cSDag-Erling Smørgrav goto full; 435c9ff56ceSDag-Erling Smørgrav dirent_terminate(&cde); 43669d94f4cSDag-Erling Smørgrav error = uiomove(&cde, cde.d_reclen, uio); 43769d94f4cSDag-Erling Smørgrav if (error != 0) 43869d94f4cSDag-Erling Smørgrav goto done; 43969d94f4cSDag-Erling Smørgrav ndirents++; 44069d94f4cSDag-Erling Smørgrav /* next sibling */ 44169d94f4cSDag-Erling Smørgrav current = TAILQ_NEXT(current, dirents); 44269d94f4cSDag-Erling Smørgrav if (current == NULL) 44369d94f4cSDag-Erling Smørgrav goto done; 44469d94f4cSDag-Erling Smørgrav uio->uio_offset = current->ino; 44569d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: [%u] setting current node to %p=%s\n", 44669d94f4cSDag-Erling Smørgrav __func__, ndirents, current, current->name); 44769d94f4cSDag-Erling Smørgrav } 44869d94f4cSDag-Erling Smørgrav full: 44969d94f4cSDag-Erling Smørgrav if (cde.d_reclen > uio->uio_resid) { 45069d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: out of space, returning\n", 45169d94f4cSDag-Erling Smørgrav __func__); 45269d94f4cSDag-Erling Smørgrav error = (ndirents == 0) ? EINVAL : 0; 45369d94f4cSDag-Erling Smørgrav } 45469d94f4cSDag-Erling Smørgrav done: 45569d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: %u entries written\n", __func__, ndirents); 45669d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: saving cache information\n", __func__); 45769d94f4cSDag-Erling Smørgrav if (current == NULL) { 45869d94f4cSDag-Erling Smørgrav uio->uio_offset = TARFS_COOKIE_EOF; 45969d94f4cSDag-Erling Smørgrav tnp->dir.lastcookie = 0; 46069d94f4cSDag-Erling Smørgrav tnp->dir.lastnode = NULL; 46169d94f4cSDag-Erling Smørgrav } else { 46269d94f4cSDag-Erling Smørgrav tnp->dir.lastcookie = current->ino; 46369d94f4cSDag-Erling Smørgrav tnp->dir.lastnode = current; 46469d94f4cSDag-Erling Smørgrav } 46569d94f4cSDag-Erling Smørgrav 46669d94f4cSDag-Erling Smørgrav if (eofflag != NULL) { 46769d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: Setting EOF flag\n", __func__); 46869d94f4cSDag-Erling Smørgrav *eofflag = (error == 0 && current == NULL); 46969d94f4cSDag-Erling Smørgrav } 47069d94f4cSDag-Erling Smørgrav 47169d94f4cSDag-Erling Smørgrav /* Update for NFS */ 47269d94f4cSDag-Erling Smørgrav if (error == 0 && cookies != NULL && ncookies != NULL) { 47369d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: Updating NFS cookies\n", __func__); 47469d94f4cSDag-Erling Smørgrav current = NULL; 47569d94f4cSDag-Erling Smørgrav *cookies = malloc(ndirents * sizeof(off_t), M_TEMP, M_WAITOK); 47669d94f4cSDag-Erling Smørgrav *ncookies = ndirents; 47769d94f4cSDag-Erling Smørgrav for (idx = 0; idx < ndirents; idx++) { 47869d94f4cSDag-Erling Smørgrav if (off == TARFS_COOKIE_DOT) 47969d94f4cSDag-Erling Smørgrav off = TARFS_COOKIE_DOTDOT; 48069d94f4cSDag-Erling Smørgrav else { 48169d94f4cSDag-Erling Smørgrav if (off == TARFS_COOKIE_DOTDOT) { 48269d94f4cSDag-Erling Smørgrav current = TAILQ_FIRST(&tnp->dir.dirhead); 48369d94f4cSDag-Erling Smørgrav } else if (current != NULL) { 48469d94f4cSDag-Erling Smørgrav current = TAILQ_NEXT(current, dirents); 48569d94f4cSDag-Erling Smørgrav } else { 48669d94f4cSDag-Erling Smørgrav current = tarfs_lookup_dir(tnp, off); 48769d94f4cSDag-Erling Smørgrav current = TAILQ_NEXT(current, dirents); 48869d94f4cSDag-Erling Smørgrav } 48969d94f4cSDag-Erling Smørgrav if (current == NULL) 49069d94f4cSDag-Erling Smørgrav off = TARFS_COOKIE_EOF; 49169d94f4cSDag-Erling Smørgrav else 49269d94f4cSDag-Erling Smørgrav off = current->ino; 49369d94f4cSDag-Erling Smørgrav } 49469d94f4cSDag-Erling Smørgrav 49569d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s: [%u] offset %zu\n", __func__, 49669d94f4cSDag-Erling Smørgrav idx, off); 49769d94f4cSDag-Erling Smørgrav (*cookies)[idx] = off; 49869d94f4cSDag-Erling Smørgrav } 49969d94f4cSDag-Erling Smørgrav MPASS(uio->uio_offset == off); 50069d94f4cSDag-Erling Smørgrav } 50169d94f4cSDag-Erling Smørgrav 50269d94f4cSDag-Erling Smørgrav return (error); 50369d94f4cSDag-Erling Smørgrav } 50469d94f4cSDag-Erling Smørgrav 50569d94f4cSDag-Erling Smørgrav static int 50669d94f4cSDag-Erling Smørgrav tarfs_read(struct vop_read_args *ap) 50769d94f4cSDag-Erling Smørgrav { 50869d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 50969d94f4cSDag-Erling Smørgrav struct uio *uiop; 51069d94f4cSDag-Erling Smørgrav struct vnode *vp; 51169d94f4cSDag-Erling Smørgrav size_t len; 51269d94f4cSDag-Erling Smørgrav off_t resid; 51369d94f4cSDag-Erling Smørgrav int error; 51469d94f4cSDag-Erling Smørgrav 51569d94f4cSDag-Erling Smørgrav uiop = ap->a_uio; 51669d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 51769d94f4cSDag-Erling Smørgrav 51869d94f4cSDag-Erling Smørgrav if (vp->v_type == VCHR || vp->v_type == VBLK) 51969d94f4cSDag-Erling Smørgrav return (EOPNOTSUPP); 52069d94f4cSDag-Erling Smørgrav 52169d94f4cSDag-Erling Smørgrav if (vp->v_type != VREG) 52269d94f4cSDag-Erling Smørgrav return (EISDIR); 52369d94f4cSDag-Erling Smørgrav 52469d94f4cSDag-Erling Smørgrav if (uiop->uio_offset < 0) 52569d94f4cSDag-Erling Smørgrav return (EINVAL); 52669d94f4cSDag-Erling Smørgrav 52769d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 52869d94f4cSDag-Erling Smørgrav error = 0; 52969d94f4cSDag-Erling Smørgrav 53069d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s, %zu, %zd)\n", __func__, 53169d94f4cSDag-Erling Smørgrav tnp, tnp->name, uiop->uio_offset, uiop->uio_resid); 53269d94f4cSDag-Erling Smørgrav 53369d94f4cSDag-Erling Smørgrav while ((resid = uiop->uio_resid) > 0) { 53469d94f4cSDag-Erling Smørgrav if (tnp->size <= uiop->uio_offset) 53569d94f4cSDag-Erling Smørgrav break; 53669d94f4cSDag-Erling Smørgrav len = MIN(tnp->size - uiop->uio_offset, resid); 53769d94f4cSDag-Erling Smørgrav if (len == 0) 53869d94f4cSDag-Erling Smørgrav break; 53969d94f4cSDag-Erling Smørgrav 54069d94f4cSDag-Erling Smørgrav error = tarfs_read_file(tnp, len, uiop); 54169d94f4cSDag-Erling Smørgrav if (error != 0 || resid == uiop->uio_resid) 54269d94f4cSDag-Erling Smørgrav break; 54369d94f4cSDag-Erling Smørgrav } 54469d94f4cSDag-Erling Smørgrav 54569d94f4cSDag-Erling Smørgrav return (error); 54669d94f4cSDag-Erling Smørgrav } 54769d94f4cSDag-Erling Smørgrav 54869d94f4cSDag-Erling Smørgrav static int 54969d94f4cSDag-Erling Smørgrav tarfs_readlink(struct vop_readlink_args *ap) 55069d94f4cSDag-Erling Smørgrav { 55169d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 55269d94f4cSDag-Erling Smørgrav struct uio *uiop; 55369d94f4cSDag-Erling Smørgrav struct vnode *vp; 55469d94f4cSDag-Erling Smørgrav int error; 55569d94f4cSDag-Erling Smørgrav 55669d94f4cSDag-Erling Smørgrav uiop = ap->a_uio; 55769d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 55869d94f4cSDag-Erling Smørgrav 55969d94f4cSDag-Erling Smørgrav MPASS(uiop->uio_offset == 0); 56069d94f4cSDag-Erling Smørgrav MPASS(vp->v_type == VLNK); 56169d94f4cSDag-Erling Smørgrav 56269d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 56369d94f4cSDag-Erling Smørgrav 56469d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s)\n", __func__, 56569d94f4cSDag-Erling Smørgrav tnp, tnp->name); 56669d94f4cSDag-Erling Smørgrav 56769d94f4cSDag-Erling Smørgrav error = uiomove(tnp->link.name, 56869d94f4cSDag-Erling Smørgrav MIN(tnp->size, uiop->uio_resid), uiop); 56969d94f4cSDag-Erling Smørgrav 57069d94f4cSDag-Erling Smørgrav return (error); 57169d94f4cSDag-Erling Smørgrav } 57269d94f4cSDag-Erling Smørgrav 57369d94f4cSDag-Erling Smørgrav static int 57469d94f4cSDag-Erling Smørgrav tarfs_reclaim(struct vop_reclaim_args *ap) 57569d94f4cSDag-Erling Smørgrav { 57669d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 57769d94f4cSDag-Erling Smørgrav struct vnode *vp; 57869d94f4cSDag-Erling Smørgrav 57969d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 58069d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 58169d94f4cSDag-Erling Smørgrav 58269d94f4cSDag-Erling Smørgrav vfs_hash_remove(vp); 58369d94f4cSDag-Erling Smørgrav 58469d94f4cSDag-Erling Smørgrav TARFS_NODE_LOCK(tnp); 58569d94f4cSDag-Erling Smørgrav tnp->vnode = NULLVP; 58669d94f4cSDag-Erling Smørgrav vp->v_data = NULL; 58769d94f4cSDag-Erling Smørgrav TARFS_NODE_UNLOCK(tnp); 58869d94f4cSDag-Erling Smørgrav 58969d94f4cSDag-Erling Smørgrav return (0); 59069d94f4cSDag-Erling Smørgrav } 59169d94f4cSDag-Erling Smørgrav 59269d94f4cSDag-Erling Smørgrav static int 59369d94f4cSDag-Erling Smørgrav tarfs_print(struct vop_print_args *ap) 59469d94f4cSDag-Erling Smørgrav { 59569d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 59669d94f4cSDag-Erling Smørgrav struct vnode *vp; 59769d94f4cSDag-Erling Smørgrav 59869d94f4cSDag-Erling Smørgrav vp = ap->a_vp; 59969d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(vp); 60069d94f4cSDag-Erling Smørgrav 60169d94f4cSDag-Erling Smørgrav printf("tag tarfs, tarfs_node %p, links %lu\n", 602fb53e7adSDag-Erling Smørgrav tnp, (unsigned long)tnp->nlink); 60369d94f4cSDag-Erling Smørgrav printf("\tmode 0%o, owner %d, group %d, size %zd\n", 60469d94f4cSDag-Erling Smørgrav tnp->mode, tnp->uid, tnp->gid, 60569d94f4cSDag-Erling Smørgrav tnp->size); 60669d94f4cSDag-Erling Smørgrav 60769d94f4cSDag-Erling Smørgrav if (vp->v_type == VFIFO) 60869d94f4cSDag-Erling Smørgrav fifo_printinfo(vp); 60969d94f4cSDag-Erling Smørgrav 61069d94f4cSDag-Erling Smørgrav printf("\n"); 61169d94f4cSDag-Erling Smørgrav 61269d94f4cSDag-Erling Smørgrav return (0); 61369d94f4cSDag-Erling Smørgrav } 61469d94f4cSDag-Erling Smørgrav 61569d94f4cSDag-Erling Smørgrav static int 61669d94f4cSDag-Erling Smørgrav tarfs_strategy(struct vop_strategy_args *ap) 61769d94f4cSDag-Erling Smørgrav { 61869d94f4cSDag-Erling Smørgrav struct uio auio; 61969d94f4cSDag-Erling Smørgrav struct iovec iov; 62069d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 62169d94f4cSDag-Erling Smørgrav struct buf *bp; 62269d94f4cSDag-Erling Smørgrav off_t off; 62369d94f4cSDag-Erling Smørgrav size_t len; 62469d94f4cSDag-Erling Smørgrav int error; 62569d94f4cSDag-Erling Smørgrav 62669d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(ap->a_vp); 62769d94f4cSDag-Erling Smørgrav bp = ap->a_bp; 62869d94f4cSDag-Erling Smørgrav MPASS(bp->b_iocmd == BIO_READ); 62969d94f4cSDag-Erling Smørgrav MPASS(bp->b_iooffset >= 0); 63069d94f4cSDag-Erling Smørgrav MPASS(bp->b_bcount > 0); 63169d94f4cSDag-Erling Smørgrav MPASS(bp->b_bufsize >= bp->b_bcount); 63269d94f4cSDag-Erling Smørgrav TARFS_DPF(VNODE, "%s(%p=%s, %zu, %ld/%ld)\n", __func__, tnp, 63369d94f4cSDag-Erling Smørgrav tnp->name, (size_t)bp->b_iooffset, bp->b_bcount, bp->b_bufsize); 63469d94f4cSDag-Erling Smørgrav iov.iov_base = bp->b_data; 63569d94f4cSDag-Erling Smørgrav iov.iov_len = bp->b_bcount; 63669d94f4cSDag-Erling Smørgrav off = bp->b_iooffset; 63769d94f4cSDag-Erling Smørgrav len = bp->b_bcount; 63869d94f4cSDag-Erling Smørgrav bp->b_resid = len; 63969d94f4cSDag-Erling Smørgrav if (off > tnp->size) { 64069d94f4cSDag-Erling Smørgrav /* XXX read beyond EOF - figure out correct handling */ 64169d94f4cSDag-Erling Smørgrav error = EIO; 64269d94f4cSDag-Erling Smørgrav goto out; 64369d94f4cSDag-Erling Smørgrav } 64469d94f4cSDag-Erling Smørgrav if (off + len > tnp->size) { 64569d94f4cSDag-Erling Smørgrav /* clip to file length */ 64669d94f4cSDag-Erling Smørgrav len = tnp->size - off; 64769d94f4cSDag-Erling Smørgrav } 64869d94f4cSDag-Erling Smørgrav auio.uio_iov = &iov; 64969d94f4cSDag-Erling Smørgrav auio.uio_iovcnt = 1; 65069d94f4cSDag-Erling Smørgrav auio.uio_offset = off; 65169d94f4cSDag-Erling Smørgrav auio.uio_resid = len; 65269d94f4cSDag-Erling Smørgrav auio.uio_segflg = UIO_SYSSPACE; 65369d94f4cSDag-Erling Smørgrav auio.uio_rw = UIO_READ; 65469d94f4cSDag-Erling Smørgrav auio.uio_td = curthread; 65569d94f4cSDag-Erling Smørgrav error = tarfs_read_file(tnp, len, &auio); 65669d94f4cSDag-Erling Smørgrav bp->b_resid -= len - auio.uio_resid; 65769d94f4cSDag-Erling Smørgrav out: 65869d94f4cSDag-Erling Smørgrav if (error != 0) { 65969d94f4cSDag-Erling Smørgrav bp->b_ioflags |= BIO_ERROR; 66069d94f4cSDag-Erling Smørgrav bp->b_error = error; 66169d94f4cSDag-Erling Smørgrav } 66269d94f4cSDag-Erling Smørgrav bp->b_flags |= B_DONE; 66369d94f4cSDag-Erling Smørgrav return (0); 66469d94f4cSDag-Erling Smørgrav } 66569d94f4cSDag-Erling Smørgrav 66669d94f4cSDag-Erling Smørgrav static int 66769d94f4cSDag-Erling Smørgrav tarfs_vptofh(struct vop_vptofh_args *ap) 66869d94f4cSDag-Erling Smørgrav { 66969d94f4cSDag-Erling Smørgrav struct tarfs_fid *tfp; 67069d94f4cSDag-Erling Smørgrav struct tarfs_node *tnp; 671*4db1b113SRick Macklem _Static_assert(sizeof(struct tarfs_fid) <= sizeof(struct fid), 672*4db1b113SRick Macklem "struct tarfs_fid cannot be larger than struct fid"); 67369d94f4cSDag-Erling Smørgrav 67469d94f4cSDag-Erling Smørgrav tfp = (struct tarfs_fid *)ap->a_fhp; 67569d94f4cSDag-Erling Smørgrav tnp = VP_TO_TARFS_NODE(ap->a_vp); 67669d94f4cSDag-Erling Smørgrav 67769d94f4cSDag-Erling Smørgrav tfp->len = sizeof(struct tarfs_fid); 67869d94f4cSDag-Erling Smørgrav tfp->ino = tnp->ino; 67969d94f4cSDag-Erling Smørgrav tfp->gen = tnp->gen; 68069d94f4cSDag-Erling Smørgrav 68169d94f4cSDag-Erling Smørgrav return (0); 68269d94f4cSDag-Erling Smørgrav } 68369d94f4cSDag-Erling Smørgrav 68469d94f4cSDag-Erling Smørgrav struct vop_vector tarfs_vnodeops = { 68569d94f4cSDag-Erling Smørgrav .vop_default = &default_vnodeops, 68669d94f4cSDag-Erling Smørgrav 68769d94f4cSDag-Erling Smørgrav .vop_access = tarfs_access, 688a0895e39SMark Johnston .vop_bmap = tarfs_bmap, 68969d94f4cSDag-Erling Smørgrav .vop_cachedlookup = tarfs_lookup, 69069d94f4cSDag-Erling Smørgrav .vop_close = tarfs_close, 69169d94f4cSDag-Erling Smørgrav .vop_getattr = tarfs_getattr, 69269d94f4cSDag-Erling Smørgrav .vop_lookup = vfs_cache_lookup, 69369d94f4cSDag-Erling Smørgrav .vop_open = tarfs_open, 69469d94f4cSDag-Erling Smørgrav .vop_print = tarfs_print, 69569d94f4cSDag-Erling Smørgrav .vop_read = tarfs_read, 69669d94f4cSDag-Erling Smørgrav .vop_readdir = tarfs_readdir, 69769d94f4cSDag-Erling Smørgrav .vop_readlink = tarfs_readlink, 69869d94f4cSDag-Erling Smørgrav .vop_reclaim = tarfs_reclaim, 69969d94f4cSDag-Erling Smørgrav .vop_strategy = tarfs_strategy, 70069d94f4cSDag-Erling Smørgrav .vop_vptofh = tarfs_vptofh, 70169d94f4cSDag-Erling Smørgrav }; 70269d94f4cSDag-Erling Smørgrav VFS_VOP_VECTOR_REGISTER(tarfs_vnodeops); 703