summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/iwscons.c1075
-rw-r--r--usr/src/uts/common/io/strredirm.c83
-rw-r--r--usr/src/uts/common/io/wscons.c42
-rw-r--r--usr/src/uts/common/os/space.c16
-rw-r--r--usr/src/uts/common/os/streamio.c37
-rw-r--r--usr/src/uts/common/sys/strredir.h90
-rw-r--r--usr/src/uts/intel/ia32/ml/modstubs.s7
-rw-r--r--usr/src/uts/sparc/ml/modstubs.s7
8 files changed, 530 insertions, 827 deletions
diff --git a/usr/src/uts/common/io/iwscons.c b/usr/src/uts/common/io/iwscons.c
index 2587e18202..41157983d1 100644
--- a/usr/src/uts/common/io/iwscons.c
+++ b/usr/src/uts/common/io/iwscons.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,15 +18,16 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Redirecting driver; used to handle workstation console redirection.
+ * workstation console redirecting driver
*
* Redirects all I/O through a given device instance to the device designated
* as the current target, as given by the vnode associated with the first
@@ -45,28 +45,6 @@
* Supports the SRIOCISREDIR ioctl for inquiring whether the descriptor given
* as argument is the current front of the redirection list associated with
* the descriptor on which the ioctl was issued.
- *
- * Every open instance of this driver corresponds to an instance of the
- * underlying client driver. If the redirection stack would otherwise become
- * empty, this device (designated by the wd_vp field of the wcd_data
- * structure) is implicitly opened and added to the front of the list. Thus,
- * there's always an active device for handling i/o through an open instance
- * of this driver.
- *
- * XXX: Names -- many of the names in this driver and its companion STREAMS
- * module still reflect its origins as the workstation console
- * redirection driver. Ultimately, they should be changed to reflect the
- * fact that this driver is potentially a general purpose redirection
- * driver. In the meantime, the driver is still specialized to have a
- * single client -- the workstation console driver -- and its file name
- * remains iwscons.c to reflect that specialization.
- *
- * Proposed change: "iwscn" becomes either "dr" (for "streams redirecting
- * driver") or "srm" (for "streams redirecting module"), as appropriate.
- *
- * XXX: Add mechanism for notifying a redirectee that it's no longer the
- * current redirectee? (This in contrast to the current facility for
- * letting it ask.)
*/
#include <sys/types.h>
@@ -83,359 +61,265 @@
#include <sys/file.h>
#include <sys/kmem.h>
#include <sys/stat.h>
-
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/strsubr.h>
#include <sys/poll.h>
-
#include <sys/debug.h>
-
#include <sys/strredir.h>
-
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
-
-static int iwscninfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int iwscnattach(dev_info_t *, ddi_attach_cmd_t);
-static int iwscnopen(dev_t *, int, int, cred_t *);
-static int iwscnclose(dev_t, int, int, cred_t *);
-static int iwscnread(dev_t, struct uio *, cred_t *);
-static int iwscnwrite(dev_t, struct uio *, cred_t *);
-static int iwscnioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-static int iwscnpoll(dev_t, short, int, short *, struct pollhead **);
+#include <sys/errno.h>
+#include <sys/modctl.h>
+#include <sys/sunldi.h>
+#include <sys/consdev.h>
+#include <sys/fs/snode.h>
/*
- * Private copy of devinfo pointer; iwscninfo uses it.
+ * Global data
*/
static dev_info_t *iwscn_dip;
-struct cb_ops iwscn_cb_ops = {
- iwscnopen, /* open */
- iwscnclose, /* close */
- nodev, /* strategy */
- nodev, /* print */
- nodev, /* dump */
- iwscnread, /* read */
- iwscnwrite, /* write */
- iwscnioctl, /* ioctl */
- nodev, /* devmap */
- nodev, /* mmap */
- nodev, /* segmap */
- iwscnpoll, /* poll */
- ddi_prop_op, /* cb_prop_op */
- 0, /* streamtab */
- D_NEW|D_MP /* Driver compatibility flag */
-};
-
-struct dev_ops iwscn_ops = {
- DEVO_REV, /* devo_rev, */
- 0, /* refcnt */
- iwscninfo, /* info */
- nulldev, /* identify */
- nulldev, /* probe */
- iwscnattach, /* attach */
- nodev, /* detach */
- nodev, /* reset */
- &iwscn_cb_ops, /* driver operations */
- NULL /* bus operations */
-};
-
-static krwlock_t iwscn_lock; /* lock proecting almost everything here */
-
-/*
- * A read/write lock was used to serialize reads,writes/opens,closes.
- * Sometime the open would hang due to a pending read. The new lock
- * iwscn_open_lock and the read lock are held in open to assure a single
- * instance, while letting concurrent reads/writes to proceed.
- */
-static kmutex_t iwscn_open_lock; /* Serializes opens */
-
/*
- * These next two fields, protected by iwscn_lock, pass the data to wcmopen()
- * from the ioctl SRIOCSREDIR. wcmopen() uses the data only if the thread
- * matches. This keeps other threads from interfering.
+ * We record the list of redirections as a linked list of iwscn_list_t
+ * structures. We need to keep track of the target's vp, so that
+ * we can vector reads, writes, etc. off to the current designee.
*/
-extern kthread_id_t iwscn_thread; /* thread that is allowed to */
- /* push redirm */
-extern wcm_data_t *iwscn_wcm_data; /* allocated data for redirm */
+typedef struct _iwscn_list {
+ struct _iwscn_list *wl_next; /* next entry */
+ vnode_t *wl_vp; /* target's vnode */
+ int wl_ref_cnt; /* operation in progress */
+ boolean_t wl_is_console; /* is the real console */
+} iwscn_list_t;
+static iwscn_list_t *iwscn_list;
/*
- * Forward declarations of private routines.
+ * iwscn_list_lock serializes modifications to the global iwscn_list list.
+ *
+ * iwscn_list_cv is used when freeing an entry from iwscn_list to allow
+ * the caller to wait till the wl_ref_cnt field is zero.
+ *
+ * iwscn_redirect_lock is used to serialize redirection requests. This
+ * is required to ensure that all active redirection streams have
+ * the redirection streams module (redirmod) pushed on them.
+ *
+ * If both iwscn_redirect_lock and iwscn_list_lock must be held then
+ * iwscn_redirect_lock must be aquired first.
*/
-static int srreset(wcd_data_t *, int, cred_t *);
-static wcrlist_t *srrm(wcrlist_t **, vnode_t *, int);
-static wcd_data_t *srilookup(minor_t);
-static wcd_data_t *srialloc(minor_t);
-static void sridealloc(wcd_data_t *);
-static wcrlist_t *srpush(wcrlist_t **, vnode_t *);
+static kcondvar_t iwscn_list_cv;
+static kmutex_t iwscn_list_lock;
+static kmutex_t iwscn_redirect_lock;
/*
- * The head of the list of open instances.
+ * Routines for managing iwscn_list
*/
-static wcd_data_t *wcddata;
+static vnode_t *
+str_vp(vnode_t *vp)
+{
+ /*
+ * Here we switch to using the vnode that is linked
+ * to from the stream queue. (In the case of device
+ * streams this will correspond to the common vnode
+ * for the device.) The reason we use this vnode
+ * is that when wcmclose() calls srpop(), this is the
+ * only vnode that it has access to.
+ */
+ ASSERT(vp->v_stream != NULL);
+ return (vp->v_stream->sd_vnode);
+}
/*
- * Currently, the only client of this driver is the workstation console
- * driver. Thus, we can get away with hard-wiring a reference to it here.
- *
- * To handle multiple clients, the driver must be revised as follows.
- * 1) Add a registration routine that clients can call to announce
- * themselves to this driver. The routine should take as arguments the
- * major device number of the corresponding instantiation of the
- * redirecting driver and a pointer to its dedvnops ops vector.
- * 2) Maintain a list (or perhaps hash array) or registered clients,
- * recording for each the srvnops ops vector and a pointer to the list
- * of open instances for that client.
- * 3) Modify the driver entry points to use their dev argument to look up
- * the proper instantiation, get the list of open instances, and then use
- * that as they currently use the open instance list.
- * 4) To allow clients to unload themselves, we probably need an unregister
- * routine. This routine would have to cope with active open instances.
+ * Remove vp from the redirection list rooted at iwscn_list, should it
+ * be there. If iwscn_list is non-NULL, deallocate the entry. If
+ * the entry doesn't exist upon completion, return NULL; otherwise
+ * return a pointer to it.
*/
-extern srvnops_t wscons_srvnops;
+static iwscn_list_t *
+srrm(vnode_t *vp, boolean_t free_entry)
+{
+ iwscn_list_t *lp, **lpp;
-#include <sys/types.h>
-#include <sys/conf.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
+ ASSERT(MUTEX_HELD(&iwscn_list_lock));
-/*
- * Module linkage information for the kernel.
- */
+ /* Get the stream vnode */
+ vp = str_vp(vp);
+ ASSERT(vp);
-static struct modldrv modldrv = {
- &mod_driverops, /* Type of module. This one is a pseudo driver */
- "Workstation Redirection driver 'iwscn' %I%",
- &iwscn_ops, /* driver ops */
-};
+ /* Look for this vnode on the redirection list */
+ for (lpp = &iwscn_list; (lp = *lpp) != NULL; lpp = &lp->wl_next) {
+ if (lp->wl_vp == vp)
+ break;
+ }
+ if (lp == NULL)
+ return (NULL);
-static struct modlinkage modlinkage = {
- MODREV_1,
- &modldrv,
- NULL
-};
+ /* Found it, remove this entry from the redirection list */
+ *lpp = lp->wl_next;
+ if (free_entry == B_FALSE)
+ return (lp);
-int
-_init(void)
-{
- return (mod_install(&modlinkage));
-}
+ /*
+ * This entry is no longer on the global redirection list so now
+ * we have to wait for all operations currently in progress to
+ * finish before we can actually delete this entry. We don't
+ * have to worry about a new operation on this vnode starting up
+ * because we've removed it from the redirection list.
+ */
+ while (lp->wl_ref_cnt != 0) {
+ /*
+ * Interrupt any operations that may be outstanding
+ * against this vnode and wait for them to complete.
+ */
+ strsetrerror(lp->wl_vp, EINTR, 0, NULL);
+ strsetwerror(lp->wl_vp, EINTR, 0, NULL);
+ cv_wait(&iwscn_list_cv, &iwscn_list_lock);
+ }
-int
-_fini(void)
-{
- return (EBUSY);
-}
+ if (lp->wl_is_console == B_TRUE) {
+ /*
+ * Special case. If this is the underlying console device
+ * then we opened it so we need to close it.
+ */
+ (void) VOP_CLOSE(lp->wl_vp, 0, 1, (offset_t)0, kcred);
+ } else {
+ /* Release our hold on this vnode */
+ VN_RELE(lp->wl_vp);
+ }
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
+ /* Free the entry */
+ kmem_free(lp, sizeof (*lp));
+ return (NULL);
}
/*
- * DDI glue routines.
+ * Push vp onto the redirection list.
+ * If it's already there move it to the front position.
*/
-
-/*ARGSUSED*/
-static int
-iwscnattach(dev_info_t *devi, ddi_attach_cmd_t cmd)
+static void
+srpush(vnode_t *vp, boolean_t is_console)
{
- static char been_here;
+ iwscn_list_t *lp;
- if (!been_here) {
- been_here = 1;
- rw_init(&iwscn_lock, NULL, RW_DEFAULT, NULL);
- }
- if (ddi_create_minor_node(devi, "iwscn", S_IFCHR,
- 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
- ddi_remove_minor_node(devi, NULL);
- return (-1);
- }
- iwscn_dip = devi;
- return (DDI_SUCCESS);
-}
+ ASSERT(MUTEX_HELD(&iwscn_list_lock));
-/* ARGSUSED */
-static int
-iwscninfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
- int error;
+ /* Get the stream vnode */
+ vp = str_vp(vp);
+ ASSERT(vp);
- switch (infocmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if (iwscn_dip == NULL) {
- error = DDI_FAILURE;
+ /* Check if it's already on the redirection list */
+ if ((lp = srrm(vp, B_FALSE)) == NULL) {
+ lp = kmem_zalloc(sizeof (*lp), KM_SLEEP);
+ lp->wl_vp = vp;
+
+ if (is_console == B_TRUE) {
+ lp->wl_is_console = B_TRUE;
} else {
- *result = (void *)iwscn_dip;
- error = DDI_SUCCESS;
+ /*
+ * Hold the vnode. Note that this hold will not
+ * prevent the device stream associated with the
+ * vnode from being closed. (We protect against
+ * that by pushing our streams redirection module
+ * onto the stream to intercept close requests.)
+ */
+ VN_HOLD(lp->wl_vp);
+ lp->wl_is_console = B_FALSE;
}
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = (void *)0;
- error = DDI_SUCCESS;
- break;
- default:
- error = DDI_FAILURE;
}
- return (error);
-}
+ /*
+ * Note that if this vnode was already somewhere on the redirection
+ * list then we removed it above and are now bumping it up to the
+ * from of the redirection list.
+ */
+ lp->wl_next = iwscn_list;
+ iwscn_list = lp;
+}
-/* ARGSUSED */
-static int
-iwscnopen(
- dev_t *devp,
- int flag,
- int state, /* should be OTYP_CHR */
- cred_t *cred)
+/*
+ * srpop() - Remove redirection because the target stream is being closed.
+ * Called from wcmclose().
+ */
+void
+srpop(vnode_t *vp)
{
- minor_t unit = getminor(*devp);
- wcd_data_t *wd;
- int err = 0;
- struct wcrlist *wwd;
-
- if (state != OTYP_CHR)
- return (ENXIO);
- rw_enter(&iwscn_lock, RW_READER);
- mutex_enter(&iwscn_open_lock);
- if ((wd = srilookup(unit)) == NULL) {
- vnode_t *vp;
-
- /*
- * First open for this instance; get a state structure for it.
- */
- wd = srialloc(unit);
+ mutex_enter(&iwscn_list_lock);
+ (void) srrm(vp, B_TRUE);
+ mutex_exit(&iwscn_list_lock);
+}
- /*
- * Call the client driver to obtain a held vnode for the
- * underlying "real" device instance.
- *
- * XXX: There's wired in knowledge of the client driver here.
- */
- err = wscons_srvnops.svn_get(unit, &vp);
- if (err != 0) {
- sridealloc(wd);
- mutex_exit(&iwscn_open_lock);
- rw_exit(&iwscn_lock);
- return (err);
- }
- wd->wd_vp = vp;
- }
+/* Get a hold on the current target */
+static iwscn_list_t *
+srhold()
+{
+ iwscn_list_t *lp;
- /*
- * Reinitalize the list if necessary.
- *
- * XXX: Is it possible for the list to empty completely while this
- * instance is still open? If not, this if should be coalesced
- * with the previous one.
- */
- if (wd->wd_list == NULL) {
- wcrlist_t *e = srpush(&wd->wd_list, wd->wd_vp);
+ mutex_enter(&iwscn_list_lock);
+ ASSERT(iwscn_list != NULL);
+ lp = iwscn_list;
+ ASSERT(lp->wl_ref_cnt >= 0);
+ lp->wl_ref_cnt++;
+ mutex_exit(&iwscn_list_lock);
- /*
- * There's no corresponding redirecting module instance for
- * the underlying device.
- */
- e->wl_data = NULL;
- }
+ return (lp);
+}
- err = srreset(wd, flag, cred);
- /*
- * XXX cleanup the sig list. Hook for console driver.
- */
- for (wwd = wd->wd_list; wwd != NULL; wwd = wwd->wl_next) {
- ASSERT(wwd->wl_vp->v_stream != NULL);
- str_cn_clean(wwd->wl_vp);
- }
- mutex_exit(&iwscn_open_lock);
- rw_exit(&iwscn_lock);
- return (err);
+/* Release a hold on an entry from the redirection list */
+static void
+srrele(iwscn_list_t *lp)
+{
+ ASSERT(lp != NULL);
+ mutex_enter(&iwscn_list_lock);
+ ASSERT(lp->wl_ref_cnt > 0);
+ lp->wl_ref_cnt--;
+ cv_broadcast(&iwscn_list_cv);
+ mutex_exit(&iwscn_list_lock);
}
-/* ARGSUSED */
static int
-iwscnclose(
- dev_t dev,
- int flag,
- int state, /* should be OTYP_CHR */
- cred_t *cred)
+iwscnread(dev_t dev, uio_t *uio, cred_t *cred)
{
- wcd_data_t *wd;
- int err = 0;
-
- if (state != OTYP_CHR)
- return (ENXIO);
- rw_enter(&iwscn_lock, RW_WRITER);
- wd = srilookup(getminor(dev));
- /*
- * Remove all outstanding redirections for this instance.
- */
- while (wd->wd_list != NULL)
- (void) srrm(&wd->wd_list, wd->wd_list->wl_vp, 1);
+ iwscn_list_t *lp;
+ int error;
- /*
- * Since this is the _last_ close, it's our last chance to close the
- * underlying device. (Note that if someone else has the underlying
- * workstation console device open, we won't get here, since
- * spec_close will see s_count > 1.)
- */
- while ((wd->wd_wsconsopen != 0) && (!err)) {
- err = VOP_CLOSE(wd->wd_vp, flag, 1, (offset_t)0, cred);
- if (!err)
- wd->wd_wsconsopen--;
- }
- if (!err)
- wd->wd_vp->v_stream = NULL;
+ ASSERT(getminor(dev) == 0);
- /*
- * We don't need the vnode that the client driver gave us any more.
- *
- * XXX: There's wired in knowledge of the client driver here.
- */
- wscons_srvnops.svn_rele(wd->wd_unit, wd->wd_vp);
- sridealloc(wd);
+ lp = srhold();
+ error = strread(lp->wl_vp, uio, cred);
+ srrele(lp);
- rw_exit(&iwscn_lock);
- return (err);
+ return (error);
}
static int
-iwscnread(dev_t dev, uio_t *uio, cred_t *cred)
+iwscnwrite(dev_t dev, uio_t *uio, cred_t *cred)
{
- wcd_data_t *wd;
- int error;
- vnode_t *vp;
+ iwscn_list_t *lp;
+ int error;
+
+ ASSERT(getminor(dev) == 0);
+
+ lp = srhold();
+ error = strwrite(lp->wl_vp, uio, cred);
+ srrele(lp);
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
- /*
- * We don't need to hold iwscn_lock while waiting for the read to
- * complete, but the vnode must not be destroyed.
- */
- vp = wd->wd_list->wl_vp;
- VN_HOLD(vp);
- rw_exit(&iwscn_lock);
- error = strread(vp, uio, cred);
- VN_RELE(vp);
return (error);
}
static int
-iwscnwrite(dev_t dev, uio_t *uio, cred_t *cred)
+iwscnpoll(dev_t dev, short events, int anyyet, short *reventsp,
+ struct pollhead **phpp)
{
- wcd_data_t *wd;
- int error;
+ iwscn_list_t *lp;
+ int error;
+
+ ASSERT(getminor(dev) == 0);
+
+ lp = srhold();
+ error = VOP_POLL(lp->wl_vp, events, anyyet, reventsp, phpp);
+ srrele(lp);
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
- error = strwrite(wd->wd_list->wl_vp, uio, cred);
- rw_exit(&iwscn_lock);
return (error);
}
@@ -443,372 +327,369 @@ static int
iwscnioctl(dev_t dev, int cmd, intptr_t arg, int flag,
cred_t *cred, int *rvalp)
{
- wcd_data_t *wd;
- int err = 0;
- file_t *f;
+ iwscn_list_t *lp;
+ file_t *f;
+ char modname[FMNAMESZ + 1] = " ";
+ int error = 0;
+
+ ASSERT(getminor(dev) == 0);
switch (cmd) {
- case SRIOCSREDIR: {
- wcrlist_t *wlp;
- wcm_data_t *mdp;
+ case SRIOCSREDIR:
+ /* Serialize all pushes of the redirection module */
+ mutex_enter(&iwscn_redirect_lock);
- if (!rw_tryenter(&iwscn_lock, RW_WRITER)) {
- return (EBUSY);
- }
- wd = srilookup(getminor(dev));
/*
* Find the vnode corresponding to the file descriptor
* argument and verify that it names a stream.
*/
if ((f = getf((int)arg)) == NULL) {
- err = EBADF;
- break;
+ mutex_exit(&iwscn_redirect_lock);
+ return (EBADF);
}
if (f->f_vnode->v_stream == NULL) {
- err = ENOSTR;
releasef((int)arg);
- break;
+ mutex_exit(&iwscn_redirect_lock);
+ return (ENOSTR);
}
- /*
- * allocate the private data for redirmod, and pass it through
- * a global to wcmopen(). This is all protected by iwscn_lock.
- */
- mdp = kmem_alloc(sizeof (*mdp), KM_SLEEP);
- iwscn_wcm_data = mdp;
- iwscn_thread = curthread;
/*
- * Push a new instance of the redirecting module onto the
- * stream, so that its close routine can notify us when the
- * overall stream is closed. (In turn, we'll then remove it
- * from the redirection list.)
+ * If the user is trying to redirect console output
+ * back to the underlying console via SRIOCSREDIR
+ * then they are evil and we'll stop them here.
*/
- if ((err = VOP_IOCTL(f->f_vnode, I_PUSH, (intptr_t)"redirmod",
- (FREAD | FKIOCTL), cred, rvalp)) != 0) {
- iwscn_thread = NULL;
- kmem_free(mdp, sizeof (*mdp));
+ if (str_vp(f->f_vnode) == str_vp(rwsconsvp)) {
releasef((int)arg);
- break;
+ mutex_exit(&iwscn_redirect_lock);
+ return (EINVAL);
}
- iwscn_thread = NULL; /* clear authorization for wcmopen() */
/*
- * Push it onto the redirection stack.
+ * Check if this stream already has the redirection
+ * module pushed onto it. I_LOOK returns an error
+ * if there are no modules pushed onto the stream.
*/
- wlp = srpush(&wd->wd_list, f->f_vnode);
- /*
- * Fill in the redirecting module instance's private data with
- * information to let it get to our redirection list when its
- * close routine is called. Cross-link it with the
- * redirection list entry.
- */
- mdp->wm_wd = wd;
- mdp->wm_entry = wlp;
- wlp->wl_data = mdp;
- releasef((int)arg);
+ (void) strioctl(f->f_vnode, I_LOOK, (intptr_t)modname,
+ FKIOCTL, K_TO_K, cred, rvalp);
+ if (strcmp(modname, STRREDIR_MOD) != 0) {
+
+ /*
+ * Push a new instance of the redirecting module onto
+ * the stream, so that its close routine can notify
+ * us when the overall stream is closed. (In turn,
+ * we'll then remove it from the redirection list.)
+ */
+ error = strioctl(f->f_vnode, I_PUSH,
+ (intptr_t)STRREDIR_MOD, FKIOCTL, K_TO_K,
+ cred, rvalp);
+
+ if (error != 0) {
+ releasef((int)arg);
+ mutex_exit(&iwscn_redirect_lock);
+ return (error);
+ }
+ }
- break;
- }
+ /* Push it onto the redirection stack */
+ mutex_enter(&iwscn_list_lock);
+ srpush(f->f_vnode, B_FALSE);
+ mutex_exit(&iwscn_list_lock);
+
+ releasef((int)arg);
+ mutex_exit(&iwscn_redirect_lock);
+ return (0);
case SRIOCISREDIR:
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
+ /*
+ * Find the vnode corresponding to the file descriptor
+ * argument and verify that it names a stream.
+ */
if ((f = getf((int)arg)) == NULL) {
- err = EBADF;
- break;
+ return (EBADF);
+ }
+ if (f->f_vnode->v_stream == NULL) {
+ releasef((int)arg);
+ return (ENOSTR);
}
+
+ lp = srhold();
+ *rvalp = (str_vp(f->f_vnode) == lp->wl_vp);
+ srrele(lp);
+ releasef((int)arg);
+ return (0);
+
+ case I_POP:
/*
- * Return value is 1 if the argument descriptor is the current
- * redirection target, and 0 otherwise.
+ * We need to serialize I_POP operations with
+ * SRIOCSREDIR operations so we don't accidently
+ * remove the redirection module from a stream.
*/
- *rvalp = (f->f_vnode == wd->wd_list->wl_vp) ? 1 : 0;
- releasef((int)arg);
- break;
+ mutex_enter(&iwscn_redirect_lock);
+ lp = srhold();
- case I_POP: {
/*
- * XXX - This is a big kludge the handles a deadlock case
- * when we are trying to pop off the redirection
- * module. Since this should only happen on a close
- * of the device, and since it hangs the system, just
- * do not allow a pop of the redirection module to happen.
- * Popping other modules is allowed.
+ * Here we need to protect against process that might
+ * try to pop off the redirection module from the
+ * redirected stream. Popping other modules is allowed.
+ *
+ * It's ok to hold iwscn_list_lock while doing the
+ * I_LOOK since it's such a simple operation.
*/
- struct stdata *stp;
- char modname[FMNAMESZ + 1] = " ";
-
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
- (void) strioctl(wd->wd_list->wl_vp, I_LOOK, (intptr_t)modname,
- flag, K_TO_K, cred, rvalp);
- if (strcmp("redirmod", modname) == 0) {
- if ((f = getf((int)arg)) == NULL) {
- err = EBADF;
- break;
- }
- if ((stp = f->f_vnode->v_stream) == NULL) {
- err = ENOSTR;
- releasef((int)arg);
- break;
- }
- if (!(stp->sd_flag & STRCLOSE)) {
- releasef((int)arg);
- rw_exit(&iwscn_lock);
- cmn_err(CE_WARN, "Popping of redirection "
- "module not allowed");
- return (EINVAL);
- }
+ (void) strioctl(lp->wl_vp, I_LOOK, (intptr_t)modname,
+ FKIOCTL, K_TO_K, cred, rvalp);
- releasef((int)arg);
+ if (strcmp(STRREDIR_MOD, modname) == 0) {
+ srrele(lp);
+ mutex_exit(&iwscn_redirect_lock);
+ return (EINVAL);
}
- /* Process ioctl normally */
- err = strioctl(wd->wd_list->wl_vp, cmd, arg, flag, U_TO_K,
- cred, rvalp);
- break;
- }
+ /* Process the ioctl normally */
+ error = VOP_IOCTL(lp->wl_vp, cmd, arg, flag, cred, rvalp);
- default:
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
- err = strioctl(wd->wd_list->wl_vp, cmd, arg, flag, U_TO_K,
- cred, rvalp);
- break;
+ srrele(lp);
+ mutex_exit(&iwscn_redirect_lock);
+ return (error);
}
- rw_exit(&iwscn_lock);
- return (err);
+ /* Process the ioctl normally */
+ lp = srhold();
+ error = VOP_IOCTL(lp->wl_vp, cmd, arg, flag, cred, rvalp);
+ srrele(lp);
+ return (error);
}
+/* ARGSUSED */
static int
-iwscnpoll(
- dev_t dev,
- short events,
- int anyyet,
- short *reventsp,
- struct pollhead **phpp)
+iwscnopen(dev_t *devp, int flag, int state, cred_t *cred)
{
- wcd_data_t *wd;
- int error;
-
- rw_enter(&iwscn_lock, RW_READER);
- wd = srilookup(getminor(dev));
- error = strpoll(wd->wd_list->wl_vp->v_stream, events, anyyet,
- reventsp, phpp);
- rw_exit(&iwscn_lock);
- return (error);
-}
-
-
-/*
- * Auxiliary routines.
- */
+ iwscn_list_t *lp;
+ vnode_t *vp = rwsconsvp;
-/*
- * Additional public interfaces.
- */
+ if (state != OTYP_CHR)
+ return (ENXIO);
-/*
- * Reset the current workstation console designee to the device denoted by the
- * wl_vp field of the first entry in the redirection list. Called from
- * iwscnopen and from the SRIOCSREDIR case of iwscnioctl, in both cases after
- * the target vp has been set to its new value.
- */
-static int
-srreset(wcd_data_t *wd, int flag, cred_t *cred)
-{
- wcrlist_t *wlp;
- int err = 0;
+ if (getminor(*devp) != 0)
+ return (ENXIO);
- ASSERT(RW_WRITE_HELD(&iwscn_lock) || MUTEX_HELD(&iwscn_open_lock));
- wlp = wd->wd_list; /* first entry */
+ /*
+ * You can't really open us until the console subsystem
+ * has been configured.
+ */
+ if (rwsconsvp == NULL)
+ return (ENXIO);
/*
- * If we're reverting back to the workstation console, make sure it's
- * open.
+ * Check if this is the first open of this device or if
+ * there is currently no redirection going on. (Ie, we're
+ * sending output to underlying console device.)
*/
- if (wlp != NULL && wlp->wl_vp == wd->wd_vp) {
- vnode_t *vp = wd->wd_vp; /* underlying device's vp */
+ mutex_enter(&iwscn_list_lock);
+ if ((iwscn_list == NULL) || (iwscn_list->wl_vp == str_vp(vp))) {
+ int error = 0;
+
+ /* Don't hold the list lock across an VOP_OPEN */
+ mutex_exit(&iwscn_list_lock);
- err = VOP_OPEN(&vp, flag, cred);
/*
- * The underlying driver is not allowed to have cloned itself
- * for this open.
+ * There is currently no redirection going on.
+ * pass this open request onto the console driver
*/
- if (vp != wd->wd_vp) {
- panic("srreset: Illegal clone");
- /*NOTREACHED*/
- }
- if (!err)
- wd->wd_wsconsopen++;
- }
- return (err);
-}
-
-/*
- * Remove vp from the redirection list rooted at *rwlp, should it be there.
- * If zap is nonzero, deallocate the entry and remove dangling references to
- * the it from the corresponding redirecting module instance's wcm_data
- * structure.
- *
- * If the entry doesn't exist upon completion, return NULL; otherwise return a
- * pointer to it.
- */
-static wcrlist_t *
-srrm(wcrlist_t **rwlp, vnode_t *vp, int zap)
-{
- wcrlist_t **delwlp;
- wcrlist_t *wlp;
- wcm_data_t *mdp;
+ error = VOP_OPEN(&vp, flag, cred);
+ if (error != 0)
+ return (error);
- ASSERT(RW_WRITE_HELD(&iwscn_lock) || MUTEX_HELD(&iwscn_open_lock));
- for (delwlp = rwlp; (wlp = *delwlp) != NULL; delwlp = &wlp->wl_next)
- if (wlp->wl_vp == vp)
- break;
- if (wlp == NULL)
- return (NULL);
- *delwlp = wlp->wl_next;
+ /* Re-aquire the list lock */
+ mutex_enter(&iwscn_list_lock);
- if (zap == 0)
- return (wlp);
+ if (iwscn_list == NULL) {
+ /* Save this vnode on the redirection list */
+ srpush(vp, B_TRUE);
+ } else {
+ /*
+ * In this case there must already be a copy of
+ * this vnode on the list, so we can free up this one.
+ */
+ (void) VOP_CLOSE(vp, flag, 1, (offset_t)0, cred);
+ }
+ }
- if (wlp->wl_vp == vp)
- VN_RELE(vp);
/*
- * Make sure there are no dangling references leading to the entry
- * from the corresponding redirecting module instance.
+ * XXX This is an ugly legacy hack that has been around
+ * forever. This code is here because this driver (the
+ * iwscn driver) is a character driver layered over a
+ * streams driver.
+ *
+ * Normally streams recieve notification whenever a process
+ * closes its last reference to that stream so that it can
+ * clean up any signal handling related configuration. (Ie,
+ * when a stream is configured to deliver a signal to a
+ * process upon certain events.) This is a feature supported
+ * by the streams framework.
+ *
+ * But character/block drivers don't recieve this type
+ * of notification. A character/block driver's close routine
+ * is only invoked upon the last close of the device. This
+ * is an artifact of the multiple open/single close driver
+ * model currently supported by solaris.
+ *
+ * So a problem occurs when a character driver layers itself
+ * on top of a streams driver. Since this driver doesn't always
+ * receive a close notification when a process closes its
+ * last reference to it, this driver can't tell the stream
+ * it's layered upon to clean up any signal handling
+ * configuration for that process.
+ *
+ * So here we hack around that by manually cleaning up the
+ * signal handling list upon each open. It doesn't guarantee
+ * that the signaling handling data stored in the stream will
+ * always be up to date, but it'll be more up to date than
+ * it would be if we didn't do this.
+ *
+ * The real way to solve this problem would be to change
+ * the device framework from an multiple open/single close
+ * model to a multiple open/multiple close model. Then
+ * character/block drivers could pass on close requests
+ * to streams layered underneath.
*/
- if ((mdp = wlp->wl_data) != NULL) {
- mdp->wm_wd = NULL;
- mdp->wm_entry = NULL;
+ str_cn_clean(VTOS(rwsconsvp)->s_commonvp);
+ for (lp = iwscn_list; lp != NULL; lp = lp->wl_next) {
+ ASSERT(lp->wl_vp->v_stream != NULL);
+ str_cn_clean(lp->wl_vp);
}
- kmem_free(wlp, sizeof (*wlp));
- return (NULL);
+ mutex_exit(&iwscn_list_lock);
+ return (0);
}
-/*
- * srpop - remove redirection because the target stream is being closed.
- * Called from wcmclose().
- */
-void
-srpop(wcm_data_t *mdp, int flag, cred_t *cred)
+/* ARGSUSED */
+static int
+iwscnclose(dev_t dev, int flag, int state, cred_t *cred)
{
- wcd_data_t *ddp;
-
- rw_enter(&iwscn_lock, RW_WRITER);
- if ((ddp = mdp->wm_wd) != NULL) {
- ASSERT(mdp->wm_entry != NULL);
- (void) srrm(&ddp->wd_list, mdp->wm_entry->wl_vp, 1);
- (void) srreset(ddp, flag, cred);
- }
- rw_exit(&iwscn_lock);
-}
+ ASSERT(getminor(dev) == 0);
-/*
- * Routines for allocating, deallocating, and finding wcd_data structures.
- *
- * For a given instantiation of the driver, its open instance structures are
- * linked together into a list, on the assumption that there will never be
- * enough open instances to make search efficiency a serious concern.
- */
+ if (state != OTYP_CHR)
+ return (ENXIO);
-/*
- * Look up the instance structure denoted by unit.
- */
-static wcd_data_t *
-srilookup(minor_t unit)
-{
- wcd_data_t *wd = wcddata;
+ mutex_enter(&iwscn_list_lock);
- ASSERT(RW_LOCK_HELD(&iwscn_lock));
- for (; wd != NULL && wd->wd_unit != unit; wd = wd->wd_next)
- continue;
+ /* Remove all outstanding redirections */
+ while (iwscn_list != NULL)
+ (void) srrm(iwscn_list->wl_vp, B_TRUE);
+ iwscn_list = NULL;
- return (wd);
+ mutex_exit(&iwscn_list_lock);
+ return (0);
}
-/*
- * Allocate a wcd_data structure for the instance denoted by unit, link it in
- * place, and return a pointer to it. If it's already allocated, simply
- * return a pointer to it.
- */
-static wcd_data_t *
-srialloc(minor_t unit)
+/*ARGSUSED*/
+static int
+iwscnattach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
- wcd_data_t *wdp;
- wcd_data_t **wdpp;
-
- ASSERT(MUTEX_HELD(&iwscn_open_lock));
- for (wdpp = &wcddata; (wdp = *wdpp) != NULL; wdpp = &wdp->wd_next) {
- if (unit < wdp->wd_unit)
- break;
- if (unit == wdp->wd_unit) {
- /* Already allocated and in place. */
- return (wdp);
- }
- }
/*
- * wdpp now points to the proper insertion point for unit's
- * per-instance structure.
+ * This is a pseudo device so there will never be more than
+ * one instance attached at a time
*/
- wdp = kmem_zalloc(sizeof (*wdp), KM_SLEEP);
- wdp->wd_unit = unit;
- wdp->wd_next = *wdpp;
- *wdpp = wdp;
+ ASSERT(iwscn_dip == NULL);
+
+ if (ddi_create_minor_node(devi, "iwscn", S_IFCHR,
+ 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
+ return (DDI_FAILURE);
+ }
+
+ iwscn_dip = devi;
+ mutex_init(&iwscn_list_lock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&iwscn_redirect_lock, NULL, MUTEX_DRIVER, NULL);
+ cv_init(&iwscn_list_cv, NULL, CV_DRIVER, NULL);
- return (wdp);
+ return (DDI_SUCCESS);
}
-/*
- * Deallocate the wcd_data structure denoted by wd and unlink it from the
- * list of open instances.
- */
-static void
-sridealloc(wcd_data_t *wd)
+/* ARGSUSED */
+static int
+iwscninfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
{
- wcd_data_t *wdp;
- wcd_data_t **wdpp;
+ int error;
- ASSERT(RW_WRITE_HELD(&iwscn_lock) || MUTEX_HELD(&iwscn_open_lock));
- for (wdpp = &wcddata; (wdp = *wdpp) != NULL; wdpp = &wdp->wd_next)
- if (wd == wdp)
- break;
- if (wdp == NULL) {
- /*
- * Not there. This should probably be a panic.
- */
- return;
+ switch (infocmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ if (iwscn_dip == NULL) {
+ error = DDI_FAILURE;
+ } else {
+ *result = (void *)iwscn_dip;
+ error = DDI_SUCCESS;
+ }
+ break;
+ case DDI_INFO_DEVT2INSTANCE:
+ *result = (void *)0;
+ error = DDI_SUCCESS;
+ break;
+ default:
+ error = DDI_FAILURE;
}
- *wdpp = wdp->wd_next;
- kmem_free(wdp, sizeof (*wdp));
+ return (error);
}
+struct cb_ops iwscn_cb_ops = {
+ iwscnopen, /* open */
+ iwscnclose, /* close */
+ nodev, /* strategy */
+ nodev, /* print */
+ nodev, /* dump */
+ iwscnread, /* read */
+ iwscnwrite, /* write */
+ iwscnioctl, /* ioctl */
+ nodev, /* devmap */
+ nodev, /* mmap */
+ nodev, /* segmap */
+ iwscnpoll, /* poll */
+ ddi_prop_op, /* cb_prop_op */
+ NULL, /* streamtab */
+ D_MP /* Driver compatibility flag */
+};
+
+struct dev_ops iwscn_ops = {
+ DEVO_REV, /* devo_rev, */
+ 0, /* refcnt */
+ iwscninfo, /* info */
+ nulldev, /* identify */
+ nulldev, /* probe */
+ iwscnattach, /* attach */
+ nodev, /* detach */
+ nodev, /* reset */
+ &iwscn_cb_ops, /* driver operations */
+ NULL /* bus operations */
+};
/*
- * Push vp onto the redirection list rooted at *wlpp. If it's already there,
- * move it to the front position. Return a pointer to its list entry.
- *
- * N.B.: It is the caller's responsibility to initialize all fields in the
- * entry other than the wl_next and wl_vp fields.
+ * Module linkage information for the kernel.
*/
-static wcrlist_t *
-srpush(wcrlist_t **wlpp, vnode_t *vp)
+static struct modldrv modldrv = {
+ &mod_driverops, /* Type of module. This one is a pseudo driver */
+ "Workstation Redirection driver %I%",
+ &iwscn_ops, /* driver ops */
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ &modldrv,
+ NULL
+};
+
+int
+_init(void)
{
- wcrlist_t *nwlp;
+ return (mod_install(&modlinkage));
+}
- ASSERT(RW_WRITE_HELD(&iwscn_lock) || MUTEX_HELD(&iwscn_open_lock));
- if ((nwlp = srrm(wlpp, vp, 0)) == NULL) {
- nwlp = kmem_zalloc(sizeof (*nwlp), KM_SLEEP);
- nwlp->wl_vp = vp;
- /*
- * The hold will prevent underlying device from closing
- * while this vnode is still on the redirection list.
- */
- VN_HOLD(vp);
- }
- nwlp->wl_next = *wlpp;
- *wlpp = nwlp;
+int
+_fini(void)
+{
+ return (EBUSY);
+}
- return (nwlp);
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
}
diff --git a/usr/src/uts/common/io/strredirm.c b/usr/src/uts/common/io/strredirm.c
index 9ae5d0e804..9c9a5d1433 100644
--- a/usr/src/uts/common/io/strredirm.c
+++ b/usr/src/uts/common/io/strredirm.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,21 +33,17 @@
* redirection driver. Its purpose in life is to detect when the stream that
* it's pushed on is closed, thereupon calling back into the redirection
* driver so that the driver can cancel redirection to the stream.
+ * It passes all messages on unchanged, in both directions.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
-#include <sys/kmem.h>
-
#include <sys/stream.h>
#include <sys/stropts.h>
-
#include <sys/debug.h>
-
#include <sys/strredir.h>
-#include <sys/thread.h>
-
+#include <sys/strsubr.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
@@ -61,8 +57,8 @@ static int wcmclose(queue_t *, int, cred_t *);
static int wcmput(queue_t *, mblk_t *);
static struct module_info wcminfo = {
- _STRREDIR_MODID,
- "redirmod",
+ STRREDIR_MODID,
+ STRREDIR_MOD,
0,
INFPSZ,
5120,
@@ -70,23 +66,23 @@ static struct module_info wcminfo = {
};
static struct qinit wcmrinit = {
- wcmput, /* put */
- NULL, /* service */
- wcmopen, /* open */
- wcmclose, /* close */
- NULL, /* qadmin */
+ (int (*)())putnext, /* put */
+ NULL, /* service */
+ wcmopen, /* open */
+ wcmclose, /* close */
+ NULL, /* qadmin */
&wcminfo,
- NULL /* mstat */
+ NULL /* mstat */
};
static struct qinit wcmwinit = {
- wcmput, /* put */
- NULL, /* service */
- wcmopen, /* open */
- wcmclose, /* close */
- NULL, /* qadmin */
+ (int (*)())putnext, /* put */
+ NULL, /* service */
+ wcmopen, /* open */
+ wcmclose, /* close */
+ NULL, /* qadmin */
&wcminfo,
- NULL /* mstat */
+ NULL /* mstat */
};
static struct streamtab redirminfo = {
@@ -99,7 +95,7 @@ static struct streamtab redirminfo = {
static struct fmodsw fsw = {
"redirmod",
&redirminfo,
- D_NEW | D_MP
+ D_MP
};
static struct modlstrmod modlstrmod = {
@@ -134,27 +130,8 @@ _info(struct modinfo *modinfop)
static int
wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
{
- extern kthread_t *iwscn_thread;
- extern wcm_data_t *iwscn_wcm_data;
-
if (sflag != MODOPEN)
return (EINVAL);
-
- /*
- * There's nothing to do if we're already open.
- */
- if (q->q_ptr == NULL) {
- /*
- * Attach the per open instance state structure.
- * Its fields were * initialized elsewhere (from the
- * SRIOCSREDIR case of of the redirection driver's ioctl
- * routine).
- * To prevent other threads from getting this, check thread_id.
- */
- if (curthread != iwscn_thread)
- return (EINVAL);
- q->q_ptr = WR(q)->q_ptr = iwscn_wcm_data;
- }
qprocson(q);
return (0);
}
@@ -163,23 +140,7 @@ wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
static int
wcmclose(queue_t *q, int flag, cred_t *cred)
{
- wcm_data_t *mdp = (wcm_data_t *)q->q_ptr;
-
qprocsoff(q);
- srpop(mdp, flag, cred);
- WR(q)->q_ptr = q->q_ptr = NULL;
- kmem_free(mdp, sizeof (*mdp));
-
- return (0);
-}
-
-/*
- * This module's only purpose in life is to intercept closes on the stream
- * it's pushed on. It passes all messages on unchanged, in both directions.
- */
-static int
-wcmput(queue_t *q, mblk_t *mp)
-{
- putnext(q, mp);
+ srpop(q->q_stream->sd_vnode);
return (0);
}
diff --git a/usr/src/uts/common/io/wscons.c b/usr/src/uts/common/io/wscons.c
index 6ec7797b89..f5c1a4bbed 100644
--- a/usr/src/uts/common/io/wscons.c
+++ b/usr/src/uts/common/io/wscons.c
@@ -1299,51 +1299,9 @@ wclrput(queue_t *q, mblk_t *mp)
}
/*
- * Auxiliary routines, for allowing the workstation console to be redirected.
- */
-
-/*
- * Given a minor device number for a wscons instance, return a held vnode for
- * it.
- *
- * We currently support only one instance, for the "workstation console".
- */
-int
-wcvnget(minor_t unit, vnode_t **vpp)
-{
- if (unit != 0 || rwsconsvp == NULL)
- return (ENXIO);
-
- /*
- * rwsconsvp is already held, so we don't have to do it here.
- */
- *vpp = rwsconsvp;
- return (0);
-}
-
-/*
- * Release the vnode that wcvnget returned.
- */
-/* ARGSUSED */
-void
-wcvnrele(minor_t unit, vnode_t *vp)
-{
- /*
- * Nothing to do, since we only support the workstation console
- * instance that's held throughout the system's lifetime.
- */
-}
-
-/*
- * The declaration and initialization of the wscons_srvnops has been
- * moved to space.c to allow "wc" to become a loadable module.
- */
-
-/*
* These are for systems without OBP, and for devices that cannot be
* shared between Solaris and the OBP.
*/
-
static void
wc_polled_putchar(cons_polledio_arg_t arg, unsigned char c)
{
diff --git a/usr/src/uts/common/os/space.c b/usr/src/uts/common/os/space.c
index d062e13e34..c91cd5c8be 100644
--- a/usr/src/uts/common/os/space.c
+++ b/usr/src/uts/common/os/space.c
@@ -244,20 +244,9 @@ int consmode = CONS_FW;
int cons_tem_disable;
/*
- * Moved here from wscons.c
- * Package the redirection-related routines into an ops vector of the form
- * that the redirecting driver expects.
- */
-srvnops_t wscons_srvnops = {
- wcvnget,
- wcvnrele
-};
-
-/*
* consconfig() in autoconf.c sets this; it's the vnode of the distinguished
* keyboard/frame buffer combination, aka the workstation console.
*/
-
vnode_t *rwsconsvp;
dev_t rwsconsdev;
@@ -268,11 +257,6 @@ dev_t rwsconsdev;
*/
int abort_enable = KIOCABORTENABLE;
-/* from iwscons.c */
-
-kthread_id_t iwscn_thread; /* thread that is allowed to push redirm */
-wcm_data_t *iwscn_wcm_data; /* allocated data for redirm */
-
/* from cpc.c */
uint_t kcpc_key; /* TSD key for CPU performance counter context */
diff --git a/usr/src/uts/common/os/streamio.c b/usr/src/uts/common/os/streamio.c
index ab61c5896b..ffa676604f 100644
--- a/usr/src/uts/common/os/streamio.c
+++ b/usr/src/uts/common/os/streamio.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -24,7 +23,7 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -592,20 +591,6 @@ strclose(struct vnode *vp, int flag, cred_t *crp)
mutex_exit(&stp->sd_lock);
/*
- * Since we call pollwakeup in close() now, the poll list should
- * be empty in most cases. The only exception is the layered devices
- * (e.g. the console drivers with redirection modules pushed on top
- * of it).
- */
- if (stp->sd_pollist.ph_list != NULL) {
- pollwakeup(&stp->sd_pollist, POLLERR);
- pollhead_clean(&stp->sd_pollist);
- }
- ASSERT(stp->sd_pollist.ph_list == NULL);
- ASSERT(stp->sd_sidp == NULL);
- ASSERT(stp->sd_pgidp == NULL);
-
- /*
* If the registered process or process group did not have an
* open instance of this stream then strclean would not be
* called. Thus at the time of closing all remaining siglist entries
@@ -697,6 +682,22 @@ strclose(struct vnode *vp, int flag, cred_t *crp)
qdetach(_RD(rmq), 1, flag, crp, B_FALSE);
}
+ /*
+ * Since we call pollwakeup in close() now, the poll list should
+ * be empty in most cases. The only exception is the layered devices
+ * (e.g. the console drivers with redirection modules pushed on top
+ * of it). We have to do this after calling qdetach() because
+ * the redirection module won't have torn down the console
+ * redirection until after qdetach() has been invoked.
+ */
+ if (stp->sd_pollist.ph_list != NULL) {
+ pollwakeup(&stp->sd_pollist, POLLERR);
+ pollhead_clean(&stp->sd_pollist);
+ }
+ ASSERT(stp->sd_pollist.ph_list == NULL);
+ ASSERT(stp->sd_sidp == NULL);
+ ASSERT(stp->sd_pgidp == NULL);
+
/* Prevent qenable from re-enabling the stream head queue */
disable_svc(_RD(qp));
diff --git a/usr/src/uts/common/sys/strredir.h b/usr/src/uts/common/sys/strredir.h
index 30b6e8c8b2..82d9bf5904 100644
--- a/usr/src/uts/common/sys/strredir.h
+++ b/usr/src/uts/common/sys/strredir.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,10 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright (c) 1990-1998 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#ifndef _SYS_STRREDIR_H
@@ -46,13 +46,13 @@ extern "C" {
* be so bad except that the DKI now suggests that ioctl cookie values
* should be based on module id to make them unique...
*/
-#define _STRREDIR_MODID 7326
+#define STRREDIR_MODID 7326
/*
* Redirection ioctls:
*/
-#define SRIOCSREDIR ((_STRREDIR_MODID<<16) | 1) /* set redir target */
-#define SRIOCISREDIR ((_STRREDIR_MODID<<16) | 2) /* is redir target? */
+#define SRIOCSREDIR ((STRREDIR_MODID<<16) | 1) /* set redir target */
+#define SRIOCISREDIR ((STRREDIR_MODID<<16) | 2) /* is redir target? */
/*
@@ -60,78 +60,10 @@ extern "C" {
*/
#ifdef _KERNEL
-#include <sys/types.h>
-#include <sys/cred.h>
-#include <sys/vnode.h>
-
-/*
- * Per-open instance driver state information.
- *
- * The underlying device potentially can be opened through (at least) two
- * paths: through this driver and through the underlying device's driver. To
- * ensure that reference counts are meaningful and therefore that close
- * routines are called at the right time, it's important to make sure that the
- * snode for the underlying device instance never has a contribution of more
- * than one through this driver, regardless of how many times this driver's
- * been opened. The wd_wsconsopen field keeps track of the necessary
- * information to ensure this property.
- *
- * The structure also contains copies of the flag and cred values supplied
- * when the device instance was first opened, so that it's possible to reopen
- * the underlying device in srreset.
- */
-typedef struct wcd_data {
- struct wcd_data *wd_next; /* link to next open instance */
- minor_t wd_unit; /* minor device # for this instance */
- struct wcrlist *wd_list; /* the head of the redirection list */
- vnode_t *wd_vp; /* underlying device instance vnode */
- int wd_wsconsopen; /* see above */
- int wd_flag; /* see above */
- cred_t *wd_cred; /* see above */
-} wcd_data_t;
-
-/*
- * Per-open instance module state information.
- *
- * An invariant: when wm_wd is non-NULL, wm_entry is also non-NULL and is on
- * the list rooted at wm_wd->wd_list.
- */
-typedef struct wcm_data {
- struct wcd_data *wm_wd; /* Xref to redir driver data */
- struct wcrlist *wm_entry; /* Redir entry that refers to us */
-} wcm_data_t;
-
-/*
- * We record the list of redirections as a linked list of wcrlist
- * structures.
- *
- * We need to keep track of:
- * 1) The target's vp, so that we can vector reads, writes, etc. off to the
- * current designee.
- * 2) The per-open instance private data structure of the redirmod module
- * instance we push onto the target stream, so that we can clean up there
- * when we go away. (I'm not sure that this is actually necessary.)
- */
-typedef struct wcrlist {
- struct wcrlist *wl_next; /* next entry */
- vnode_t *wl_vp; /* target's vnode */
- struct wcm_data *wl_data; /* target's redirmod private data */
-} wcrlist_t;
-
-/*
- * A given instance of the redirection driver must be able to open the
- * corresponding instance of the underlying device when the redirection list
- * empties. To do so it needs a vnode for the underlying instance. The
- * underlying driver is responsible for supplying routines for producing and
- * disposing of this vnode. The get routine must return a held vnode, so that
- * it can't vanish while the redirecting driver is using it.
- */
-typedef struct srvnops {
- int (*svn_get)(); /* (minor #, vpp) --> errno value */
- void (*svn_rele)(); /* (minor #, vp) */
-} srvnops_t;
+/* name of the module used to detect closes on redirected streams */
+#define STRREDIR_MOD "redirmod"
-extern void srpop(wcm_data_t *, int, cred_t *);
+extern void srpop(vnode_t *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s
index 3c41110cdc..1187bd8551 100644
--- a/usr/src/uts/intel/ia32/ml/modstubs.s
+++ b/usr/src/uts/intel/ia32/ml/modstubs.s
@@ -985,13 +985,6 @@ fcnname/**/_info: \
END_MODULE(pciehpc);
#endif
-#ifndef WC_MODULE
- MODULE(wc,drv);
- STUB(wc, wcvnget, 0);
- STUB(wc, wcvnrele, 0);
- END_MODULE(wc);
-#endif
-
#ifndef IWSCN_MODULE
MODULE(iwscn,drv);
STUB(iwscn, srpop, 0);
diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s
index b7177e8003..5ed4b88ae9 100644
--- a/usr/src/uts/sparc/ml/modstubs.s
+++ b/usr/src/uts/sparc/ml/modstubs.s
@@ -894,13 +894,6 @@ stubs_base:
END_MODULE(sad);
#endif
-#ifndef WC_MODULE
- MODULE(wc,drv);
- STUB(wc, wcvnget, 0);
- STUB(wc, wcvnrele, 0);
- END_MODULE(wc);
-#endif
-
#ifndef IWSCN_MODULE
MODULE(iwscn,drv);
STUB(iwscn, srpop, 0);