/* * XXX: can't use callremove now because can't catch setbacks with * it due to lack of a pnode argument. */ static int puffs_vnop_remove(struct vop_nremove_args *ap) { PUFFS_MSG_VARS(vn, remove); struct vnode *dvp = ap->a_dvp; struct vnode *vp; struct puffs_node *dpn = VPTOPP(dvp); struct puffs_node *pn; struct nchandle *nch = ap->a_nch; struct namecache *ncp = nch->ncp; struct ucred *cred = ap->a_cred; struct mount *mp = dvp->v_mount; struct puffs_mount *pmp = MPTOPUFFSMP(mp); int error; if (!EXISTSOP(pmp, REMOVE)) return EOPNOTSUPP; error = vget(dvp, LK_EXCLUSIVE); if (error != 0) { DPRINTF(("puffs_vnop_remove: EAGAIN on parent vnode %p %s\n", dvp, ncp->nc_name)); return EAGAIN; } error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp); if (error != 0) { DPRINTF(("puffs_vnop_remove: cache_vget error: %p %s\n", dvp, ncp->nc_name)); return EAGAIN; } if (vp->v_type == VDIR) { error = EISDIR; goto out; } pn = VPTOPP(vp); PUFFS_MSG_ALLOC(vn, remove); remove_msg->pvnr_cookie_targ = VPTOPNC(vp); puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred, ncp, cred); puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, VPTOPNC(dvp)); puffs_msg_enqueue(pmp, park_remove); error = puffs_msg_wait2(pmp, park_remove, dpn, pn); PUFFS_MSG_RELEASE(remove); error = checkerr(pmp, error, __func__); out: vput(dvp); vn_unlock(vp); if (error == 0) cache_unlink(nch); vrele(vp); return error; }
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; }
static void callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck) { PUFFS_MSG_VARS(vn, reclaim); if (!EXISTSOP(pmp, RECLAIM)) return; PUFFS_MSG_ALLOC(vn, reclaim); puffs_msg_setfaf(park_reclaim); puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck); puffs_msg_enqueue(pmp, park_reclaim); PUFFS_MSG_RELEASE(reclaim); }
void puffs_senderr(struct puffs_mount *pmp, int type, int error, const char *str, puffs_cookie_t ck) { struct puffs_msgpark *park; struct puffs_error *perr; puffs_msgmem_alloc(sizeof(struct puffs_error), &park, (void *)&perr, 1); puffs_msg_setfaf(park); puffs_msg_setinfo(park, PUFFSOP_ERROR, type, ck); perr->perr_error = error; strlcpy(perr->perr_str, str, sizeof(perr->perr_str)); puffs_msg_enqueue(pmp, park); puffs_msgmem_release(park); }
static int puffs_vnop_close(struct vop_close_args *ap) { PUFFS_MSG_VARS(vn, close); struct vnode *vp = ap->a_vp; struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); vn_lock(vp, LK_UPGRADE | LK_RETRY); if (!EXISTSOP(pmp, CLOSE)) return vop_stdclose(ap); PUFFS_MSG_ALLOC(vn, close); puffs_msg_setfaf(park_close); close_msg->pvnr_fflag = ap->a_fflag; puffs_msg_setinfo(park_close, PUFFSOP_VN, PUFFS_VN_CLOSE, VPTOPNC(vp)); puffs_msg_enqueue(pmp, park_close); PUFFS_MSG_RELEASE(close); return vop_stdclose(ap); }
/* XXX: callinactive can't setback */ static int puffs_vnop_inactive(struct vop_inactive_args *ap) { PUFFS_MSG_VARS(vn, inactive); struct vnode *vp = ap->a_vp; struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); struct puffs_node *pnode = VPTOPP(vp); flushvncache(vp, MNT_NOWAIT); if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) { /* * do not wait for reply from userspace, otherwise it may * deadlock. */ PUFFS_MSG_ALLOC(vn, inactive); puffs_msg_setfaf(park_inactive); puffs_msg_setinfo(park_inactive, PUFFSOP_VN, PUFFS_VN_INACTIVE, VPTOPNC(vp)); puffs_msg_enqueue(pmp, park_inactive); PUFFS_MSG_RELEASE(inactive); } pnode->pn_stat &= ~PNODE_DOINACT; /* * file server thinks it's gone? then don't be afraid care, * node's life was already all it would ever be */ if (pnode->pn_stat & PNODE_NOREFS) { pnode->pn_stat |= PNODE_DYING; vrecycle(vp); } return 0; }
static int dosetattr(struct vnode *vp, struct vattr *vap, struct ucred *cred, int flags) { PUFFS_MSG_VARS(vn, setattr); struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); struct puffs_node *pn = VPTOPP(vp); int error = 0; if ((vp->v_mount->mnt_flag & MNT_RDONLY) && (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) return EROFS; if ((vp->v_mount->mnt_flag & MNT_RDONLY) && vp->v_type == VREG && vap->va_size != VNOVAL) return EROFS; /* * Flush metacache first. If we are called with some explicit * parameters, treat them as information overriding metacache * information. */ if (pn->pn_stat & PNODE_METACACHE_MASK) { if ((pn->pn_stat & PNODE_METACACHE_ATIME) && vap->va_atime.tv_sec == VNOVAL) vap->va_atime = pn->pn_mc_atime; if ((pn->pn_stat & PNODE_METACACHE_CTIME) && vap->va_ctime.tv_sec == VNOVAL) vap->va_ctime = pn->pn_mc_ctime; if ((pn->pn_stat & PNODE_METACACHE_MTIME) && vap->va_mtime.tv_sec == VNOVAL) vap->va_mtime = pn->pn_mc_mtime; if ((pn->pn_stat & PNODE_METACACHE_SIZE) && vap->va_size == VNOVAL) vap->va_size = pn->pn_mc_size; pn->pn_stat &= ~PNODE_METACACHE_MASK; } PUFFS_MSG_ALLOC(vn, setattr); (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr)); puffs_credcvt(&setattr_msg->pvnr_cred, cred); puffs_msg_setinfo(park_setattr, PUFFSOP_VN, PUFFS_VN_SETATTR, VPTOPNC(vp)); if (flags & SETATTR_ASYNC) puffs_msg_setfaf(park_setattr); puffs_msg_enqueue(pmp, park_setattr); if ((flags & SETATTR_ASYNC) == 0) error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL); PUFFS_MSG_RELEASE(setattr); if ((flags & SETATTR_ASYNC) == 0) { error = checkerr(pmp, error, __func__); if (error) return error; } else { error = 0; } if (vap->va_size != VNOVAL) { pn->pn_serversize = vap->va_size; if (flags & SETATTR_CHSIZE) puffs_meta_setsize(vp, vap->va_size, 0); } return 0; }