Add a VOP_VPTOCNP implementation for pseudofs which covers file systems

such as procfs and linprocfs.

This implementation's locking was enhanced by kib.

Reviewed by:	kib
		des
Approved by:	des
		kib
Tested by:	pho
This commit is contained in:
Joe Marcus Clarke 2008-12-30 21:49:39 +00:00
parent 095104ac36
commit e7f54c1b71

View File

@ -309,6 +309,84 @@ pfs_getextattr(struct vop_getextattr_args *va)
PFS_RETURN (error);
}
/*
* Convert a vnode to its component name
*/
static int
pfs_vptocnp(struct vop_vptocnp_args *ap)
{
struct vnode *vp = ap->a_vp;
struct vnode **dvp = ap->a_vpp;
struct pfs_vdata *pvd = vp->v_data;
struct pfs_node *pd = pvd->pvd_pn;
struct pfs_node *pn;
struct mount *mp;
char *buf = ap->a_buf;
int *buflen = ap->a_buflen;
char pidbuf[PFS_NAMELEN];
pid_t pid = pvd->pvd_pid;
int len, i, error, locked;
i = *buflen;
error = 0;
pfs_lock(pd);
if (vp->v_type == VDIR && pd->pn_type == pfstype_root) {
*dvp = vp;
vhold(*dvp);
pfs_unlock(pd);
PFS_RETURN (0);
} else if (vp->v_type == VDIR && pd->pn_type == pfstype_procdir) {
len = snprintf(pidbuf, sizeof(pidbuf), "%d", pid);
i -= len;
if (i < 0) {
error = ENOMEM;
goto failed;
}
bcopy(pidbuf, buf + i, len);
} else {
i -= strlen(pd->pn_name);
if (i < 0) {
error = ENOMEM;
goto failed;
}
bcopy(pd->pn_name, buf + i, strlen(pd->pn_name));
}
pn = pd->pn_parent;
pfs_unlock(pd);
mp = vp->v_mount;
error = vfs_busy(mp, 0);
if (error)
return (error);
/*
* vp is held by caller.
*/
locked = VOP_ISLOCKED(vp);
VOP_UNLOCK(vp, 0);
error = pfs_vncache_alloc(mp, dvp, pn, pid);
if (error) {
vn_lock(vp, locked | LK_RETRY);
vfs_unbusy(mp);
PFS_RETURN(error);
}
*buflen = i;
vhold(*dvp);
vput(*dvp);
vn_lock(vp, locked | LK_RETRY);
vfs_unbusy(mp);
PFS_RETURN (0);
failed:
pfs_unlock(pd);
PFS_RETURN(error);
}
/*
* Look up a file or directory
*/
@ -890,6 +968,7 @@ struct vop_vector pfs_vnodeops = {
.vop_rmdir = VOP_EOPNOTSUPP,
.vop_setattr = pfs_setattr,
.vop_symlink = VOP_EOPNOTSUPP,
.vop_vptocnp = pfs_vptocnp,
.vop_write = pfs_write,
/* XXX I've probably forgotten a few that need VOP_EOPNOTSUPP */
};