Thanks Mouse and Martin. I got past that error. But
now I'm running into another problem - unable to
determine when write op occurs (to be able to return
ENOSPC error).

I'm trying to use the 'bypass routine' by creating a
new `full_bypass` by duplicating `layer_bypass`. In this
`full_bypass` I want to return ENOSPC error whenever
write occurs. Which variable contains this info? I'm
confused which structs contain what information.

-- IC

full_bypass for reference:

int
full_bypass(void *v)
{
        struct vop_generic_args /* {
                struct vnodeop_desc *a_desc;
                <other random data follows, presumably>
        } */ *ap = v;
        int (**our_vnodeop_p)(void *);
        struct vnode **this_vp_p;
        int error;
        struct vnode *old_vps[VDESC_MAX_VPS], *vp0;
        struct vnode **vps_p[VDESC_MAX_VPS];
        struct vnode ***vppp;
        struct mount *mp;
        struct vnodeop_desc *descp = ap->a_desc;
        int reles, i, flags;

#ifdef DIAGNOSTIC
        /*
         * We require at least one vp.
         */
        if (descp->vdesc_vp_offsets == NULL ||
            descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
                panic("%s: no vp's in map.\n", __func__);
#endif

        vps_p[0] =
            VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
        vp0 = *vps_p[0];
        mp = vp0->v_mount;
        flags = MOUNTTOLAYERMOUNT(mp)->layerm_flags;
        our_vnodeop_p = vp0->v_op;

        if (flags & LAYERFS_MBYPASSDEBUG)
                printf("%s: %s\n", __func__, descp->vdesc_name);

        /*
         * Map the vnodes going in.
         * Later, we'll invoke the operation based on
         * the first mapped vnode's operation vector.
         */
        reles = descp->vdesc_flags;
        for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
                if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
                        break;   /* bail out at end of list */
                vps_p[i] = this_vp_p =
                    VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i],
                    ap);
                /*
                 * We're not guaranteed that any but the first vnode
                 * are of our type.  Check for and don't map any
                 * that aren't.  (We must always map first vp or vclean fails.)
                 */
                if (i && (*this_vp_p == NULL ||
                    (*this_vp_p)->v_op != our_vnodeop_p)) {
                        old_vps[i] = NULL;
                } else {
                        old_vps[i] = *this_vp_p;
                        *(vps_p[i]) = LAYERVPTOLOWERVP(*this_vp_p);
                        /*
                         * XXX - Several operations have the side effect
                         * of vrele'ing their vp's.  We must account for
                         * that.  (This should go away in the future.)
                         */
                        if (reles & VDESC_VP0_WILLRELE)
                                vref(*this_vp_p);
                }
        }

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

                      I want to return ENOSPC here
                        if there is a write operation

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

        /*
         * Call the operation on the lower layer
         * with the modified argument structure.
         */
        error = VCALL(*vps_p[0], descp->vdesc_offset, ap);

        /*
         * Maintain the illusion of call-by-value
         * by restoring vnodes in the argument structure
         * to their original value.
         */
        reles = descp->vdesc_flags;
        for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
                if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
                        break;   /* bail out at end of list */
                if (old_vps[i]) {
                        *(vps_p[i]) = old_vps[i];
                        if (reles & VDESC_VP0_WILLRELE)
                                vrele(*(vps_p[i]));
                }
        }

        /*
         * Map the possible out-going vpp
         * (Assumes that the lower layer always returns
         * a VREF'ed vpp unless it gets an error.)
         */
        if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET && !error) {
                vppp = VOPARG_OFFSETTO(struct vnode***,
                                 descp->vdesc_vpp_offset, ap);
                /*
                 * Only vop_lookup, vop_create, vop_makedir, vop_mknod
                 * and vop_symlink return vpp's. vop_lookup doesn't call bypass
                 * as a lookup on "." would generate a locking error.
                 * So all the calls which get us here have a unlocked vpp. :-)
                 */
                error = layer_node_create(mp, **vppp, *vppp);
                if (error) {
                        vrele(**vppp);
                        **vppp = NULL;
                }
        }
        return error;
}

Reply via email to