summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/dev/sdev_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/dev/sdev_subr.c')
-rw-r--r--usr/src/uts/common/fs/dev/sdev_subr.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/usr/src/uts/common/fs/dev/sdev_subr.c b/usr/src/uts/common/fs/dev/sdev_subr.c
index 1075391d17..0159fc568e 100644
--- a/usr/src/uts/common/fs/dev/sdev_subr.c
+++ b/usr/src/uts/common/fs/dev/sdev_subr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -588,6 +588,9 @@ static struct sdev_vop_table vtab[] =
{ "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE },
+ { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
+ SDEV_DYNAMIC | SDEV_VTOR },
+
{ NULL, NULL, NULL, NULL, NULL, 0}
};
@@ -3709,3 +3712,70 @@ devname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
rw_exit(&parent->sdev_contents);
return (0);
}
+
+/*
+ * a generic inactive() function
+ */
+void
+devname_inactive_func(struct vnode *vp, struct cred *cred,
+ void (*callback)(struct vnode *))
+{
+ int clean;
+ struct sdev_node *dv = VTOSDEV(vp);
+ struct sdev_node *ddv = dv->sdev_dotdot;
+ struct sdev_node *idv;
+ struct sdev_node *prev = NULL;
+ int state;
+ struct devname_nsmap *map = NULL;
+ struct devname_ops *dirops = NULL;
+ void (*fn)(devname_handle_t *, struct cred *) = NULL;
+
+ rw_enter(&ddv->sdev_contents, RW_WRITER);
+ state = dv->sdev_state;
+
+ mutex_enter(&vp->v_lock);
+ ASSERT(vp->v_count >= 1);
+
+ if (vp->v_count == 1 && callback != NULL)
+ callback(vp);
+
+ clean = (vp->v_count == 1) && (state == SDEV_ZOMBIE);
+
+ /*
+ * last ref count on the ZOMBIE node is released.
+ * clean up the sdev_node, and
+ * release the hold on the backing store node so that
+ * the ZOMBIE backing stores also cleaned out.
+ */
+ if (clean) {
+ ASSERT(ddv);
+ if (SDEV_IS_GLOBAL(dv)) {
+ map = ddv->sdev_mapinfo;
+ dirops = map ? map->dir_ops : NULL;
+ if (dirops && (fn = dirops->devnops_inactive))
+ (*fn)(&(dv->sdev_handle), cred);
+ }
+
+ ddv->sdev_nlink--;
+ if (vp->v_type == VDIR) {
+ dv->sdev_nlink--;
+ }
+ for (idv = ddv->sdev_dot; idv && idv != dv;
+ prev = idv, idv = idv->sdev_next)
+ ;
+ ASSERT(idv == dv);
+ if (prev == NULL)
+ ddv->sdev_dot = dv->sdev_next;
+ else
+ prev->sdev_next = dv->sdev_next;
+ dv->sdev_next = NULL;
+ dv->sdev_nlink--;
+ --vp->v_count;
+ mutex_exit(&vp->v_lock);
+ sdev_nodedestroy(dv, 0);
+ } else {
+ --vp->v_count;
+ mutex_exit(&vp->v_lock);
+ }
+ rw_exit(&ddv->sdev_contents);
+}