Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
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;
}