diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/iwscons.c | 1075 | ||||
-rw-r--r-- | usr/src/uts/common/io/strredirm.c | 83 | ||||
-rw-r--r-- | usr/src/uts/common/io/wscons.c | 42 | ||||
-rw-r--r-- | usr/src/uts/common/os/space.c | 16 | ||||
-rw-r--r-- | usr/src/uts/common/os/streamio.c | 37 | ||||
-rw-r--r-- | usr/src/uts/common/sys/strredir.h | 90 | ||||
-rw-r--r-- | usr/src/uts/intel/ia32/ml/modstubs.s | 7 | ||||
-rw-r--r-- | usr/src/uts/sparc/ml/modstubs.s | 7 |
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); |