|
|
} | } |
| |
int | int |
devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td) |
devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, |
|
int *dm_unlock, struct thread *td) |
{ | { |
int error; | int error; |
struct vnode *vp; | struct vnode *vp; |
struct cdev *dev; | struct cdev *dev; |
|
struct devfs_mount *dmp; |
| |
KASSERT(td == curthread, ("devfs_allocv: td != curthread")); | KASSERT(td == curthread, ("devfs_allocv: td != curthread")); |
|
dmp = VFSTODEVFS(mp); |
loop: | loop: |
vp = de->de_vnode; | vp = de->de_vnode; |
if (vp != NULL) { | if (vp != NULL) { |
|
if (*dm_unlock) { |
|
sx_xunlock(&dmp->dm_lock); |
|
*dm_unlock = 0; |
|
} |
if (vget(vp, LK_EXCLUSIVE, td)) | if (vget(vp, LK_EXCLUSIVE, td)) |
goto loop; | goto loop; |
*vpp = vp; | *vpp = vp; |
|
|
} | } |
vp->v_data = de; | vp->v_data = de; |
de->de_vnode = vp; | de->de_vnode = vp; |
|
if (*dm_unlock) { |
|
sx_xunlock(&dmp->dm_lock); |
|
*dm_unlock = 0; |
|
} |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); |
#ifdef MAC | #ifdef MAC |
mac_associate_vnode_devfs(mp, de, vp); | mac_associate_vnode_devfs(mp, de, vp); |
|
|
} | } |
| |
static int | static int |
devfs_lookupx(struct vop_lookup_args *ap) |
devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) |
{ | { |
struct componentname *cnp; | struct componentname *cnp; |
struct vnode *dvp, **vpp; | struct vnode *dvp, **vpp; |
|
|
de = TAILQ_FIRST(&dd->de_dlist); /* "." */ | de = TAILQ_FIRST(&dd->de_dlist); /* "." */ |
de = TAILQ_NEXT(de, de_list); /* ".." */ | de = TAILQ_NEXT(de, de_list); /* ".." */ |
de = de->de_dir; | de = de->de_dir; |
error = devfs_allocv(de, dvp->v_mount, vpp, td); |
error = devfs_allocv(de, dvp->v_mount, vpp, dm_unlock, td); |
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); | vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); |
return (error); | return (error); |
} | } |
|
|
return (0); | return (0); |
} | } |
} | } |
error = devfs_allocv(de, dvp->v_mount, vpp, td); |
error = devfs_allocv(de, dvp->v_mount, vpp, dm_unlock, td); |
return (error); | return (error); |
} | } |
| |
|
|
{ | { |
int j; | int j; |
struct devfs_mount *dmp; | struct devfs_mount *dmp; |
|
int dm_unlock; |
| |
dmp = VFSTODEVFS(ap->a_dvp->v_mount); | dmp = VFSTODEVFS(ap->a_dvp->v_mount); |
|
dm_unlock = 1; |
sx_xlock(&dmp->dm_lock); | sx_xlock(&dmp->dm_lock); |
j = devfs_lookupx(ap); |
j = devfs_lookupx(ap, &dm_unlock); |
sx_xunlock(&dmp->dm_lock); |
if (dm_unlock == 1) |
|
sx_xunlock(&dmp->dm_lock); |
return (j); | return (j); |
} | } |
| |
|
|
struct thread *td; | struct thread *td; |
struct devfs_dirent *dd, *de; | struct devfs_dirent *dd, *de; |
struct devfs_mount *dmp; | struct devfs_mount *dmp; |
|
int dm_unlock; |
int error; | int error; |
| |
/* | /* |
|
|
dvp = ap->a_dvp; | dvp = ap->a_dvp; |
dmp = VFSTODEVFS(dvp->v_mount); | dmp = VFSTODEVFS(dvp->v_mount); |
sx_xlock(&dmp->dm_lock); | sx_xlock(&dmp->dm_lock); |
|
dm_unlock = 1; |
| |
cnp = ap->a_cnp; | cnp = ap->a_cnp; |
vpp = ap->a_vpp; | vpp = ap->a_vpp; |
|
|
if (de == NULL) | if (de == NULL) |
goto notfound; | goto notfound; |
de->de_flags &= ~DE_WHITEOUT; | de->de_flags &= ~DE_WHITEOUT; |
error = devfs_allocv(de, dvp->v_mount, vpp, td); |
error = devfs_allocv(de, dvp->v_mount, vpp, &dm_unlock, td); |
notfound: | notfound: |
sx_xunlock(&dmp->dm_lock); |
if (dm_unlock == 1) |
|
sx_xunlock(&dmp->dm_lock); |
return (error); | return (error); |
} | } |
| |
|
|
struct devfs_dirent *de; | struct devfs_dirent *de; |
struct devfs_mount *dmp; | struct devfs_mount *dmp; |
struct thread *td; | struct thread *td; |
|
int dm_unlock; |
| |
td = ap->a_cnp->cn_thread; | td = ap->a_cnp->cn_thread; |
KASSERT(td == curthread, ("devfs_symlink: td != curthread")); | KASSERT(td == curthread, ("devfs_symlink: td != curthread")); |
|
|
de->de_symlink = malloc(i, M_DEVFS, M_WAITOK); | de->de_symlink = malloc(i, M_DEVFS, M_WAITOK); |
bcopy(ap->a_target, de->de_symlink, i); | bcopy(ap->a_target, de->de_symlink, i); |
sx_xlock(&dmp->dm_lock); | sx_xlock(&dmp->dm_lock); |
|
dm_unlock = 1; |
#ifdef MAC | #ifdef MAC |
mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); | mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); |
#endif | #endif |
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); | TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); |
devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td); |
devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, &dm_unlock, td); |
sx_xunlock(&dmp->dm_lock); |
if (dm_unlock == 1) |
|
sx_xunlock(&dmp->dm_lock); |
return (0); | return (0); |
} | } |
| |