Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/doorfs/doorfs_vnops.c
- This file was added.
#include <sys/types.h> | |||||
#include <sys/systm.h> | |||||
#include <sys/door.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/lock.h> | |||||
#include <sys/proc.h> | |||||
#include <sys/syslog.h> | |||||
#include <sys/unistd.h> | |||||
#include <sys/vnode.h> | |||||
MALLOC_DECLARE(M_DOOR); | |||||
static int | |||||
door_open(struct vop_open_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
KASSERT(vp->v_type == VDOOR, ("door_open invoked on non-door vnode")); | |||||
struct door *d = vp->v_door_vnode_info->v_door; | |||||
struct vop_vector *prev_vnops = | |||||
ap->a_vp->v_door_vnode_info->v_prev_vnops; | |||||
KASSERT( | |||||
vp != d->door_vnode, ("door_open invoked on non-attached vnode")); | |||||
DOOR_LOCK(d); | |||||
d->refcount++; | |||||
DOOR_UNLOCK(d); | |||||
return prev_vnops->vop_open(ap); | |||||
} | |||||
static int | |||||
door_close(struct vop_close_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
KASSERT(vp->v_type == VDOOR, ("door_close invoked on non-door vnode")); | |||||
struct door *d = vp->v_door_vnode_info->v_door; | |||||
DOOR_LOCK(d); | |||||
d->refcount--; | |||||
if ((d->attr & (DOOR_UNREF | DOOR_UNREF_MULTI)) && d->refcount == 1) { | |||||
d->unrefcount++; | |||||
if ((d->attr & DOOR_UNREF_ACTIVE) == 0) { | |||||
/* | |||||
* If an unref thread is not bound yet | |||||
* (can occur if client only opens and closes door file | |||||
* shortly after door_create) wait for a while and then | |||||
* (hopefully) proceed. | |||||
*/ | |||||
if (d->unref_td == NULL) { | |||||
int error = cv_timedwait( | |||||
&d->unref_cv, &d->door_lock, hz / 2); | |||||
if (error == EWOULDBLOCK) { | |||||
// TODO: log error rather than | |||||
// panicking | |||||
printf("door_close: no unref thread attached"); | |||||
return 0; | |||||
} | |||||
} | |||||
DOOR_UNLOCK(d); | |||||
/* Deliver unref */ | |||||
wakeup_one(d->unref_td); | |||||
} | |||||
} else if (d->refcount == 0) { | |||||
/* | |||||
* This close could have come from another process which opened | |||||
* an attached node or from the owning process. | |||||
*/ | |||||
if (d->proc) { | |||||
PROC_LOCK(d->proc); | |||||
LIST_REMOVE(d, entries); | |||||
/* Wake all calling threads waiting for a server */ | |||||
cv_broadcast(&d->proc->door_td_pool.pool_cv); | |||||
PROC_UNLOCK(d->proc); | |||||
d->proc = NULL; | |||||
} | |||||
if (d->attr & DOOR_PRIVATE) { | |||||
/* Wake all calling threads waiting for a server */ | |||||
cv_broadcast(&d->priv_pool.pool_cv); | |||||
} | |||||
/* "Detach" door from vnode if the last reference was held by | |||||
* another process */ | |||||
if (d->door_vnode != vp) { | |||||
vp->v_type = VREG; | |||||
vp->v_op = vp->v_door_vnode_info->v_prev_vnops; | |||||
} | |||||
struct door_vnode_info *tmp = vp->v_door_vnode_info; | |||||
vp->v_door_vnode_info = NULL; | |||||
wakeup(d); | |||||
while (d->active_invocations > 0) { | |||||
cv_wait(&d->close_cv, &d->door_lock); | |||||
} | |||||
DOOR_UNLOCK(d); | |||||
cv_destroy(&d->unref_cv); | |||||
kib: Why do you look vnode interlock there? | |||||
Done Inline ActionsAnother redundant lock, this will be removed. bnovkov: Another redundant lock, this will be removed. | |||||
cv_destroy(&d->close_cv); | |||||
free(tmp, M_TEMP); | |||||
free(d, M_DOOR); | |||||
} else { | |||||
DOOR_UNLOCK(d); | |||||
} | |||||
return 0; | |||||
} | |||||
/* A VDOOR type vnode can only be accessed when attached */ | |||||
static int | |||||
door_access(struct vop_access_args *ap) | |||||
{ | |||||
KASSERT(ap->a_vp->v_type == VDOOR, | |||||
("door_access invoked on non-door vnode")); | |||||
/* Forward access to underlying fs */ | |||||
struct vop_vector *prev_vnops = | |||||
ap->a_vp->v_door_vnode_info->v_prev_vnops; | |||||
KASSERT(prev_vnops, ("door_access invoked on detached door vnode")); | |||||
return prev_vnops->vop_access(ap); | |||||
} | |||||
static int | |||||
door_accessx(struct vop_accessx_args *ap) | |||||
{ | |||||
KASSERT(ap->a_vp->v_type == VDOOR, | |||||
("door_accessx invoked on non-door vnode")); | |||||
/* Forward access to underlying fs */ | |||||
struct vop_vector *prev_vnops = | |||||
ap->a_vp->v_door_vnode_info->v_prev_vnops; | |||||
return prev_vnops->vop_accessx(ap); | |||||
} | |||||
static int | |||||
door_reclaim(struct vop_reclaim_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
KASSERT( | |||||
vp->v_type == VDOOR, ("door_reclaim invoked on non-door vnode")); | |||||
return 0; | |||||
} | |||||
struct vop_vector door_vnops = { | |||||
.vop_default = &default_vnodeops, | |||||
.vop_access = door_access, | |||||
.vop_accessx = door_accessx, | |||||
.vop_close = door_close, | |||||
.vop_reclaim = door_reclaim, | |||||
.vop_open = door_open, | |||||
.vop_create = VOP_EBADF, | |||||
.vop_getattr = VOP_EBADF, | |||||
.vop_advlock = VOP_EBADF, | |||||
Done Inline ActionsI think this code is never executed at all. kib: I think this code is never executed at all. | |||||
.vop_ioctl = VOP_EBADF, | |||||
.vop_kqfilter = VOP_EBADF, | |||||
Done Inline ActionsWhy? kib: Why? | |||||
.vop_link = VOP_EBADF, | |||||
.vop_mkdir = VOP_EBADF, | |||||
.vop_mknod = VOP_EBADF, | |||||
.vop_pathconf = VOP_EBADF, | |||||
.vop_print = VOP_EBADF, | |||||
.vop_read = VOP_EBADF, | |||||
.vop_readdir = VOP_EBADF, | |||||
.vop_readlink = VOP_EBADF, | |||||
.vop_reallocblks = VOP_EBADF, | |||||
.vop_rename = VOP_EBADF, | |||||
.vop_rmdir = VOP_EBADF, | |||||
.vop_remove = VOP_EBADF, | |||||
.vop_setattr = VOP_EBADF, | |||||
.vop_symlink = VOP_EBADF, | |||||
.vop_write = VOP_EBADF, | |||||
}; | |||||
VFS_VOP_VECTOR_REGISTER(door_vnops); |
Why do you look vnode interlock there?