}
parent->sk_state = IUCV_CLOSED;
- sock_set_flag(parent, SOCK_ZAPPED);
}
-/* Kill socket */
+/* Kill socket (only if zapped and orphaned) */
static void iucv_sock_kill(struct sock *sk)
{
if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
skb_queue_purge(&iucv->send_skb_q);
skb_queue_purge(&iucv->backlog_skb_q);
-
- sock_set_flag(sk, SOCK_ZAPPED);
break;
default:
sock_set_flag(sk, SOCK_ZAPPED);
+ /* nothing to do here */
break;
}
+ /* mark socket for deletion by iucv_sock_kill() */
+ sock_set_flag(sk, SOCK_ZAPPED);
+
release_sock(sk);
- iucv_sock_kill(sk);
}
static void iucv_sock_init(struct sock *sk, struct sock *parent)
return err;
}
+/* iucv_fragment_skb() - Fragment a single IUCV message into multiple skb's
+ *
+ * Locking: must be called with message_q.lock held
+ */
static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
{
int dataleft, size, copied = 0;
return 0;
}
+/* iucv_process_message() - Receive a single outstanding IUCV message
+ *
+ * Locking: must be called with message_q.lock held
+ */
static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
struct iucv_path *path,
struct iucv_message *msg)
skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
}
+/* iucv_process_message_q() - Process outstanding IUCV messages
+ *
+ * Locking: must be called with message_q.lock held
+ */
static void iucv_process_message_q(struct sock *sk)
{
struct iucv_sock *iucv = iucv_sk(sk);
kfree_skb(skb);
/* Queue backlog skbs */
+ spin_lock_bh(&iucv->message_q.lock);
rskb = skb_dequeue(&iucv->backlog_skb_q);
while (rskb) {
if (sock_queue_rcv_skb(sk, rskb)) {
}
}
if (skb_queue_empty(&iucv->backlog_skb_q)) {
- spin_lock_bh(&iucv->message_q.lock);
if (!list_empty(&iucv->message_q.list))
iucv_process_message_q(sk);
- spin_unlock_bh(&iucv->message_q.lock);
}
+ spin_unlock_bh(&iucv->message_q.lock);
}
done: