diff options
author | Anil udupa <anil.udupa@sun.com> | 2008-09-19 11:14:29 -0700 |
---|---|---|
committer | Anil udupa <anil.udupa@sun.com> | 2008-09-19 11:14:29 -0700 |
commit | 9f7c4232898c7267aead321833a9ff322daa257d (patch) | |
tree | ab01e8b6356577fd048ae81e1a447f38c88e8e89 | |
parent | 6be03d0bfa1168f0c0751e49fa681e3c985251d1 (diff) | |
download | illumos-joyent-9f7c4232898c7267aead321833a9ff322daa257d.tar.gz |
6672579 sppp: ioctl for sppp would hang
-rw-r--r-- | usr/src/uts/common/io/ppp/sppp/sppp.c | 147 | ||||
-rw-r--r-- | usr/src/uts/common/io/ppp/sppp/sppp.h | 7 |
2 files changed, 126 insertions, 28 deletions
diff --git a/usr/src/uts/common/io/ppp/sppp/sppp.c b/usr/src/uts/common/io/ppp/sppp/sppp.c index d5884482a6..c854e2f8ae 100644 --- a/usr/src/uts/common/io/ppp/sppp/sppp.c +++ b/usr/src/uts/common/io/ppp/sppp/sppp.c @@ -1,7 +1,7 @@ /* * sppp.c - Solaris STREAMS PPP multiplexing pseudo-driver * - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Permission to use, copy, modify, and distribute this software and its @@ -45,7 +45,6 @@ * for improved performance and scalability. */ -#pragma ident "%Z%%M% %I% %E% SMI" #define RCSID "$Id: sppp.c,v 1.0 2000/05/08 01:10:12 masputra Exp $" #include <sys/types.h> @@ -574,14 +573,29 @@ sppp_ioctl(struct queue *q, mblk_t *mp) } else if ((ppa->ppa_lower_wq != NULL) && !IS_PPA_LASTMOD(ppa)) { mutex_enter(&ppa->ppa_sta_lock); - ppa->ppa_ioctlsfwd++; - mutex_exit(&ppa->ppa_sta_lock); /* - * Record the ioctl CMD & ID - this will be - * used to check the ACK or NAK responses - * coming from below. + * We match sps_ioc_id on the M_IOC{ACK,NAK}, + * so if the response hasn't come back yet, + * new ioctls must be queued instead. */ - sps->sps_ioc_id = iop->ioc_id; + if (IS_SPS_IOCQ(sps)) { + mutex_exit(&ppa->ppa_sta_lock); + if (!putq(q, mp)) { + error = EAGAIN; + break; + } + return; + } else { + ppa->ppa_ioctlsfwd++; + /* + * Record the ioctl CMD & ID - this will be + * used to check the ACK or NAK responses + * coming from below. + */ + sps->sps_ioc_id = iop->ioc_id; + sps->sps_flags |= SPS_IOCQ; + mutex_exit(&ppa->ppa_sta_lock); + } putnext(ppa->ppa_lower_wq, mp); return; /* don't ack or nak the request */ } @@ -615,14 +629,28 @@ sppp_ioctl(struct queue *q, mblk_t *mp) } else if ((ppa->ppa_lower_wq != NULL) && !IS_PPA_LASTMOD(ppa)) { mutex_enter(&ppa->ppa_sta_lock); - ppa->ppa_ioctlsfwd++; - mutex_exit(&ppa->ppa_sta_lock); /* - * Record the ioctl CMD & ID - this will be - * used to check the ACK or NAK responses - * coming from below. + * See comments in PPPIO_GETSTAT64 case + * in sppp_ioctl(). */ - sps->sps_ioc_id = iop->ioc_id; + if (IS_SPS_IOCQ(sps)) { + mutex_exit(&ppa->ppa_sta_lock); + if (!putq(q, mp)) { + error = EAGAIN; + break; + } + return; + } else { + ppa->ppa_ioctlsfwd++; + /* + * Record the ioctl CMD & ID - this will be + * used to check the ACK or NAK responses + * coming from below. + */ + sps->sps_ioc_id = iop->ioc_id; + sps->sps_flags |= SPS_IOCQ; + mutex_exit(&ppa->ppa_sta_lock); + } putnext(ppa->ppa_lower_wq, mp); return; /* don't ack or nak the request */ } @@ -759,13 +787,28 @@ sppp_uwput(queue_t *q, mblk_t *mp) break; /* return EINVAL */ } mutex_enter(&ppa->ppa_sta_lock); - ppa->ppa_ioctlsfwd++; - mutex_exit(&ppa->ppa_sta_lock); /* - * Record the ioctl CMD & ID - this will be used to - * check the ACK or NAK responses coming from below. + * See comments in PPPIO_GETSTAT64 case + * in sppp_ioctl(). */ - sps->sps_ioc_id = iop->ioc_id; + if (IS_SPS_IOCQ(sps)) { + mutex_exit(&ppa->ppa_sta_lock); + if (!putq(q, mp)) { + error = EAGAIN; + break; + } + return; + } else { + ppa->ppa_ioctlsfwd++; + /* + * Record the ioctl CMD & ID - + * this will be used to check the + * ACK or NAK responses coming from below. + */ + sps->sps_ioc_id = iop->ioc_id; + sps->sps_flags |= SPS_IOCQ; + mutex_exit(&ppa->ppa_sta_lock); + } putnext(ppa->ppa_lower_wq, mp); return; /* don't ack or nak the request */ } @@ -807,13 +850,42 @@ void sppp_uwsrv(queue_t *q) { spppstr_t *sps; + sppa_t *ppa; mblk_t *mp; queue_t *nextq; + struct iocblk *iop; ASSERT(q != NULL && q->q_ptr != NULL); sps = (spppstr_t *)q->q_ptr; + while ((mp = getq(q)) != NULL) { - if ((nextq = sppp_outpkt(q, &mp, msgdsize(mp), sps)) == NULL) { + if (MTYPE(mp) == M_IOCTL) { + ppa = sps->sps_ppa; + if ((ppa == NULL) || (ppa->ppa_lower_wq == NULL)) { + miocnak(q, mp, 0, EINVAL); + continue; + } + + iop = (struct iocblk *)mp->b_rptr; + mutex_enter(&ppa->ppa_sta_lock); + /* + * See comments in PPPIO_GETSTAT64 case + * in sppp_ioctl(). + */ + if (IS_SPS_IOCQ(sps)) { + mutex_exit(&ppa->ppa_sta_lock); + if (putbq(q, mp) == 0) + miocnak(q, mp, 0, EAGAIN); + break; + } else { + ppa->ppa_ioctlsfwd++; + sps->sps_ioc_id = iop->ioc_id; + sps->sps_flags |= SPS_IOCQ; + mutex_exit(&ppa->ppa_sta_lock); + putnext(ppa->ppa_lower_wq, mp); + } + } else if ((nextq = + sppp_outpkt(q, &mp, msgdsize(mp), sps)) == NULL) { if (mp != NULL) { if (putbq(q, mp) == 0) freemsg(mp); @@ -1074,13 +1146,28 @@ sppp_inner_ioctl(queue_t *q, mblk_t *mp) break; } mutex_enter(&ppa->ppa_sta_lock); - ppa->ppa_ioctlsfwd++; - mutex_exit(&ppa->ppa_sta_lock); /* - * Record the ioctl CMD & ID - this will be used to check the - * ACK or NAK responses coming from below. + * See comments in PPPIO_GETSTAT64 case + * in sppp_ioctl(). */ - sps->sps_ioc_id = iop->ioc_id; + if (IS_SPS_IOCQ(sps)) { + mutex_exit(&ppa->ppa_sta_lock); + if (!putq(q, mp)) { + error = EAGAIN; + break; + } + return; + } else { + ppa->ppa_ioctlsfwd++; + /* + * Record the ioctl CMD & ID - + * this will be used to check the + * ACK or NAK responses coming from below. + */ + sps->sps_ioc_id = iop->ioc_id; + sps->sps_flags |= SPS_IOCQ; + mutex_exit(&ppa->ppa_sta_lock); + } putnext(ppa->ppa_lower_wq, mp); return; /* don't ack or nak the request */ case PPPIO_DETACH: @@ -1785,7 +1872,17 @@ sppp_recv_nondata(queue_t *q, mblk_t *mp, spppstr_t *ctlsps) } mutex_enter(&ppa->ppa_sta_lock); ppa->ppa_ioctlsfwdok++; + + /* + * Clear SPS_IOCQ and enable the lower write side queue, + * this would allow the upper stream service routine + * to start processing the queue for pending messages. + * sppp_lwsrv -> sppp_uwsrv. + */ + destsps->sps_flags &= ~SPS_IOCQ; mutex_exit(&ppa->ppa_sta_lock); + qenable(WR(destsps->sps_rq)); + putnext(destsps->sps_rq, mp); break; case M_HANGUP: diff --git a/usr/src/uts/common/io/ppp/sppp/sppp.h b/usr/src/uts/common/io/ppp/sppp/sppp.h index 4987763943..2daa8aceac 100644 --- a/usr/src/uts/common/io/ppp/sppp/sppp.h +++ b/usr/src/uts/common/io/ppp/sppp/sppp.h @@ -1,7 +1,7 @@ /* * sppp.h - Solaris STREAMS PPP multiplexing pseudo-driver definitions * - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Permission to use, copy, modify, and distribute this software and its @@ -50,8 +50,6 @@ #ifndef __SPPP_H #define __SPPP_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/dlpi.h> #include <net/ppp_defs.h> @@ -219,6 +217,7 @@ typedef struct spppstr { #define SPS_PIOATTACH 0x00000020 /* attached using PPPIO_ATTACH */ #define SPS_KDEBUG 0x00000040 /* stream has kdebug turned on */ #define SPS_CACHED 0x00000080 /* network stream pointer is cached */ +#define SPS_IOCQ 0x00000100 /* queue ioctls */ #define IS_SPS_CONTROL(x) \ ((x)->sps_flags & SPS_CONTROL) @@ -234,6 +233,8 @@ typedef struct spppstr { ((x)->sps_flags & SPS_KDEBUG) #define IS_SPS_CACHED(x) \ ((x)->sps_flags & SPS_CACHED) +#define IS_SPS_IOCQ(x) \ + ((x)->sps_flags & SPS_IOCQ) /* * Bit format (octal based) string for cmn_err, which represents the flags. |