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
tarfs_open(struct vop_open_args * ap)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
tarfs_close(struct vop_close_args * ap)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
tarfs_access(struct vop_access_args * ap)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
tarfs_bmap(struct vop_bmap_args * ap)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
tarfs_getattr(struct vop_getattr_args * ap)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
tarfs_lookup(struct vop_cachedlookup_args * ap)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
tarfs_readdir(struct vop_readdir_args * ap)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
tarfs_read(struct vop_read_args * ap)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
tarfs_readlink(struct vop_readlink_args * ap)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
tarfs_reclaim(struct vop_reclaim_args * ap)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
tarfs_print(struct vop_print_args * ap)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
tarfs_strategy(struct vop_strategy_args * ap)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
tarfs_vptofh(struct vop_vptofh_args * ap)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