static int puffs_vnop_link(struct vop_nlink_args *ap) { PUFFS_MSG_VARS(vn, link); struct vnode *dvp = ap->a_dvp; struct vnode *vp = ap->a_vp; struct puffs_node *dpn = VPTOPP(dvp); struct puffs_node *pn = VPTOPP(vp); struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); struct nchandle *nch = ap->a_nch; struct namecache *ncp = nch->ncp; struct ucred *cred = ap->a_cred; int error; if (!EXISTSOP(pmp, LINK)) return EOPNOTSUPP; if (vp->v_mount != dvp->v_mount) return EXDEV; if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { DPRINTF(("puffs_vnop_link: EAGAIN on ncp %p %s\n", ncp, ncp->nc_name)); return EAGAIN; } PUFFS_MSG_ALLOC(vn, link); link_msg->pvnr_cookie_targ = VPTOPNC(vp); puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred, ncp, cred); puffs_msg_setinfo(park_link, PUFFSOP_VN, PUFFS_VN_LINK, VPTOPNC(dvp)); puffs_msg_enqueue(pmp, park_link); error = puffs_msg_wait2(pmp, park_link, dpn, pn); PUFFS_MSG_RELEASE(link); error = checkerr(pmp, error, __func__); /* * XXX: stay in touch with the cache. I don't like this, but * don't have a better solution either. See also puffs_rename(). */ if (error == 0) { puffs_updatenode(pn, PUFFS_UPDATECTIME); } vput(dvp); if (error == 0) { cache_setunresolved(nch); cache_setvp(nch, vp); } return error; }
void puffs_gop_markupdate(struct vnode *vp, int flags) { int uflags = 0; if (flags & GOP_UPDATE_ACCESSED) uflags |= PUFFS_UPDATEATIME; if (flags & GOP_UPDATE_MODIFIED) uflags |= PUFFS_UPDATEMTIME; puffs_updatenode(VPTOPP(vp), uflags, 0); }
static int puffs_vnop_rename(struct vop_nrename_args *ap) { PUFFS_MSG_VARS(vn, rename); struct nchandle *fnch = ap->a_fnch; struct nchandle *tnch = ap->a_tnch; struct vnode *fdvp = ap->a_fdvp; struct vnode *fvp = fnch->ncp->nc_vp; struct vnode *tdvp = ap->a_tdvp; struct vnode *tvp = tnch->ncp->nc_vp; struct ucred *cred = ap->a_cred; struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount); int error; if (!EXISTSOP(pmp, RENAME)) return EOPNOTSUPP; error = vget(tdvp, LK_EXCLUSIVE); if (error != 0) { DPRINTF(("puffs_vnop_rename: EAGAIN on tdvp vnode %p %s\n", tdvp, tnch->ncp->nc_name)); return EAGAIN; } if (tvp != NULL) { error = vget(tvp, LK_EXCLUSIVE); if (error != 0) { DPRINTF(("puffs_vnop_rename: EAGAIN on tvp vnode %p %s\n", tvp, tnch->ncp->nc_name)); vput(tdvp); return EAGAIN; } } if ((fvp->v_mount != tdvp->v_mount) || (tvp && (fvp->v_mount != tvp->v_mount))) { error = EXDEV; goto out; } if (tvp) { if (fvp->v_type == VDIR && tvp->v_type != VDIR) { error = ENOTDIR; goto out; } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { error = EISDIR; goto out; } } PUFFS_MSG_ALLOC(vn, rename); rename_msg->pvnr_cookie_src = VPTOPNC(fvp); rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp); if (tvp) rename_msg->pvnr_cookie_targ = VPTOPNC(tvp); else rename_msg->pvnr_cookie_targ = NULL; puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred, fnch->ncp, cred); puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred, tnch->ncp, cred); puffs_msg_setinfo(park_rename, PUFFSOP_VN, PUFFS_VN_RENAME, VPTOPNC(fdvp)); PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error); PUFFS_MSG_RELEASE(rename); error = checkerr(pmp, error, __func__); if (error == 0) puffs_updatenode(VPTOPP(fvp), PUFFS_UPDATECTIME); out: if (tvp != NULL) vn_unlock(tvp); if (tdvp != tvp) vn_unlock(tdvp); if (error == 0) cache_rename(fnch, tnch); if (tvp != NULL) vrele(tvp); vrele(tdvp); return error; }