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