Mercurial > illumos > illumos-gate
changeset 10192:aed5e9f98d69
6850754 flow-control does not get cleared on icmp socket, messing up rdisc.
author | Rao Shoaib <Rao.Shoaib@Sun.COM> |
---|---|
date | Tue, 28 Jul 2009 13:53:49 -0700 |
parents | 5a6814ac93b6 |
children | 379fb17bd79a |
files | usr/src/uts/common/fs/sockfs/sockcommon_subr.c |
diffstat | 1 files changed, 45 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/sockfs/sockcommon_subr.c Tue Jul 28 12:45:46 2009 -0400 +++ b/usr/src/uts/common/fs/sockfs/sockcommon_subr.c Tue Jul 28 13:53:49 2009 -0700 @@ -651,6 +651,33 @@ } } +/* + * Check flow control on a given sonode. Must have so_lock held, and + * this function will release the hold. + */ + +static void +so_check_flow_control(struct sonode *so) +{ + ASSERT(MUTEX_HELD(&so->so_lock)); + + if (so->so_flowctrld && so->so_rcv_queued < so->so_rcvlowat) { + so->so_flowctrld = B_FALSE; + mutex_exit(&so->so_lock); + /* + * Open up flow control. SCTP does not have any downcalls, and + * it will clr flow ctrl in sosctp_recvmsg(). + */ + if (so->so_downcalls != NULL && + so->so_downcalls->sd_clr_flowctrl != NULL) { + (*so->so_downcalls->sd_clr_flowctrl) + (so->so_proto_handle); + } + } else { + mutex_exit(&so->so_lock); + } +} + int so_dequeue_msg(struct sonode *so, mblk_t **mctlp, struct uio *uiop, rval_t *rvalp, int flags) @@ -829,37 +856,30 @@ so->so_state |= SS_RCVATMARK; } } - if (so->so_flowctrld && so->so_rcv_queued < - so->so_rcvlowat) { - so->so_flowctrld = B_FALSE; - mutex_exit(&so->so_lock); - /* - * Open up flow control. SCTP does - * not have any downcalls, and it will - * clr flow ctrl in sosctp_recvmsg(). - */ - if (so->so_downcalls != NULL && - so->so_downcalls->sd_clr_flowctrl != - NULL) { - (*so->so_downcalls-> - sd_clr_flowctrl) - (so->so_proto_handle); - } - } else { - mutex_exit(&so->so_lock); - } + /* + * so_check_flow_control() will drop + * so->so_lock. + */ + so_check_flow_control(so); } } if (mp != NULL) { /* more data blocks in msg */ more |= MOREDATA; if ((flags & (MSG_PEEK|MSG_TRUNC))) { - if (flags & MSG_TRUNC && - ((flags & MSG_PEEK) == 0)) { + if (flags & MSG_PEEK) { + freemsg(mp); + } else { + unsigned int msize = msgdsize(mp); + + freemsg(mp); mutex_enter(&so->so_lock); - so->so_rcv_queued -= msgdsize(mp); - mutex_exit(&so->so_lock); + so->so_rcv_queued -= msize; + /* + * so_check_flow_control() will drop + * so->so_lock. + */ + so_check_flow_control(so); } - freemsg(mp); } else if (partial_read && !somsghasdata(mp)) { /* * Avoid queuing a zero-length tail part of @@ -1012,6 +1032,7 @@ } #endif rvalp->r_val1 = more; + ASSERT(MUTEX_NOT_HELD(&so->so_lock)); return (error); }