ir250_cache_wait_data-2.diff :
----------------------------
o [CRITICA] Fix one instance were we forgot to clear LSAP cache
o [CORRECT] Fix a bogus conversion to wait_event()
The socket closure would never propagate to the app
diff -u -p linux/net/irda/irlmp.d0.c linux/net/irda/irlmp.c
--- linux/net/irda/irlmp.d0.c Fri Jun 7 07:50:28 2002
+++ linux/net/irda/irlmp.c Fri Jun 7 15:06:25 2002
@@ -647,6 +647,9 @@ int irlmp_disconnect_request(struct lsap
ASSERT(self->lap->lsaps != NULL, return -1;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+ self->lap->cache.valid = FALSE;
+#endif
ASSERT(lsap != NULL, return -1;);
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
diff -u -p linux/net/irda/af_irda.d0.c linux/net/irda/af_irda.c
--- linux/net/irda/af_irda.d0.c Fri Jun 7 08:02:43 2002
+++ linux/net/irda/af_irda.c Mon Jun 10 11:12:48 2002
@@ -126,8 +126,10 @@ static void irda_disconnect_indication(v
dev_kfree_skb(skb);
sk = self->sk;
- if (sk == NULL)
+ if (sk == NULL) {
+ IRDA_DEBUG(0, __FUNCTION__ "(%p) : BUG : sk is NULL\n", self);
return;
+ }
/* Prevent race conditions with irda_release() and irda_shutdown() */
if ((!sk->dead) && (sk->state != TCP_CLOSE)) {
@@ -1306,12 +1308,12 @@ static int irda_sendmsg(struct socket *s
len = self->max_data_size;
}
- skb = sock_alloc_send_skb(sk, len + self->max_header_size,
+ skb = sock_alloc_send_skb(sk, len + self->max_header_size + 16,
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
return -ENOBUFS;
- skb_reserve(skb, self->max_header_size);
+ skb_reserve(skb, self->max_header_size + 16);
asmptr = skb->h.raw = skb_put(skb, len);
memcpy_fromiovec(asmptr, msg->msg_iov, len);
@@ -1384,30 +1386,6 @@ static int irda_recvmsg_dgram(struct soc
}
/*
- * Function irda_data_wait (sk)
- *
- * Sleep until data has arrive. But check for races..
- *
- * The caller is expected to deal with the situation when we return
- * due to pending signals. And even if not, the peeked skb might have
- * been already dequeued due to concurrent operation.
- * Currently irda_recvmsg_stream() is the only caller and is ok.
- * Return 0 if condition packet has arrived, -ERESTARTSYS if signal_pending()
- * Only used once in irda_recvmsg_stream() -> inline
- */
-static inline int irda_data_wait(struct sock *sk)
-{
- int ret = 0;
- if (!skb_peek(&sk->receive_queue)) {
- set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
- __wait_event_interruptible(*(sk->sleep),
- (skb_peek(&sk->receive_queue)!=NULL), ret);
- clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
- }
- return(ret);
-}
-
-/*
* Function irda_recvmsg_stream (sock, msg, size, flags, scm)
*
*
@@ -1421,6 +1399,7 @@ static int irda_recvmsg_stream(struct so
int noblock = flags & MSG_DONTWAIT;
int copied = 0;
int target = 1;
+ DECLARE_WAITQUEUE(waitq, current);
IRDA_DEBUG(3, __FUNCTION__ "()\n");
@@ -1443,25 +1422,43 @@ static int irda_recvmsg_stream(struct so
skb=skb_dequeue(&sk->receive_queue);
if (skb==NULL) {
+ int ret = 0;
+
if (copied >= target)
break;
+ /* The following code is a cut'n'paste of the
+ * wait_event_interruptible() macro.
+ * We don't us the macro because the test condition
+ * is messy. - Jean II */
+ set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+ add_wait_queue(sk->sleep, &waitq);
+ set_current_state(TASK_INTERRUPTIBLE);
+
/*
* POSIX 1003.1g mandates this order.
*/
-
- if (sk->err) {
- return sock_error(sk);
- }
+ if (sk->err)
+ ret = sock_error(sk);
+ else if (sk->shutdown & RCV_SHUTDOWN)
+ ;
+ else if (noblock)
+ ret = -EAGAIN;
+ else if (signal_pending(current))
+ ret = -ERESTARTSYS;
+ else if (skb_peek(&sk->receive_queue) == NULL)
+ /* Wait process until data arrives */
+ schedule();
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &waitq);
+ clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+ if(ret)
+ return(ret);
if (sk->shutdown & RCV_SHUTDOWN)
break;
- if (noblock)
- return -EAGAIN;
- /* Wait process until data arrives */
- if (irda_data_wait(sk))
- return -ERESTARTSYS;
continue;
}
@@ -2388,11 +2385,11 @@ bed:
"(), nothing discovered yet, going to sleep...\n");
/* Set watchdog timer to expire in <val> ms. */
+ self->errno = 0;
self->watchdog.function = irda_discovery_timeout;
self->watchdog.data = (unsigned long) self;
self->watchdog.expires = jiffies + (val * HZ/1000);
add_timer(&(self->watchdog));
- self->errno = 0;
/* Wait for IR-LMP to call us back */
__wait_event_interruptible(self->query_wait,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Jun 15 2002 - 22:00:20 EST