@@ -2974,6 +2974,11 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
{
struct sock *sk = sock->sk, *other;
unsigned int mask, writable;
+#ifdef CONFIG_UNIX_MULTICAST
+ struct sock_set *others;
+ int err = 0;
+ int i;
+#endif
sock_poll_wait(file, sk_sleep(sk), wait);
mask = 0;
@@ -3011,6 +3016,48 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
if (unix_recvq_full(other))
writable = 0;
}
+
+#ifdef CONFIG_UNIX_MULTICAST
+ /*
+ * On multicast sockets, we need to check if the receiving
+ * queue is full on all peers who don't have
+ * UNIX_MREQ_DROP_WHEN_FULL.
+ */
+
+ /* Don't let the group die under us */
+ unix_state_lock(other);
+ if (sock_flag(other, SOCK_DEAD)
+ || !unix_sk(other)->mcast_group) {
+ unix_state_unlock(other);
+ goto skip_multicast;
+ }
+ atomic_inc(&unix_sk(other)->mcast_group->refcnt);
+ unix_state_unlock(other);
+
+ others = unix_find_multicast_recipients(sk,
+ unix_sk(other)->mcast_group, &err);
+ if (!others)
+ goto skip_multicast_peers;
+ for (i = others->offset ; i < others->cnt ; i++) {
+ if (others->items[i].flags & UNIX_MREQ_DROP_WHEN_FULL)
+ continue;
+ if (unix_peer(others->items[i].s) != sk) {
+ sock_poll_wait(file,
+ &unix_sk(others->items[i].s)
+ ->peer_wait, wait);
+ if (unix_recvq_full(others->items[i].s)) {
+ writable = 0;
+ break;
+ }
+ }
+ }
+ up_sock_set(others);
+skip_multicast_peers:
+ if (atomic_dec_and_test(&unix_sk(other)->mcast_group->refcnt))
+ destroy_mcast_group(unix_sk(other)->mcast_group);
+
+skip_multicast:
+#endif
sock_put(other);
}