summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnil udupa <anil.udupa@sun.com>2008-09-19 11:14:29 -0700
committerAnil udupa <anil.udupa@sun.com>2008-09-19 11:14:29 -0700
commit9f7c4232898c7267aead321833a9ff322daa257d (patch)
treeab01e8b6356577fd048ae81e1a447f38c88e8e89
parent6be03d0bfa1168f0c0751e49fa681e3c985251d1 (diff)
downloadillumos-joyent-9f7c4232898c7267aead321833a9ff322daa257d.tar.gz
6672579 sppp: ioctl for sppp would hang
-rw-r--r--usr/src/uts/common/io/ppp/sppp/sppp.c147
-rw-r--r--usr/src/uts/common/io/ppp/sppp/sppp.h7
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.