Le Mon, 22 Nov 2010 11:05:19 -0800 (PST),
David Miller <davem@davemloft.net> a écrit :
I understand the benefit to use RCU in order to have lockless sends.
But with RCU I will still have worries about the memory allocation:
- I cannot allocate inside a rcu_read_lock()-rcu_read_unlock() block.
- If I iterate locklessly over the multicast group members with
hlist_for_each_entry_rcu(), new members can be added, so the
array can be allocated with the wrong size and I have to try again
("goto try_again") when this rare case occurs.
- Another idea would be to avoid completely the allocation by inlining
unix_find_multicast_recipients() inside unix_dgram_sendmsg() and
delivering the messages to the recipients as long as the list is
being iterated locklessly. But I want to provide atomicity of
delivery: the message must be delivered with skb_queue_tail() either
to all the recipients or to none of them in case of interruption or
memory pressure. I don't see how I can achieve that without
iterating several times on the list of recipients, hence the
allocation and the copy in the array. I also want to guarantee the
order of delivery as described in multicast-unix-sockets.txt and for
this, I am taking lots of spinlocks anyway. I don't see how to avoid
that, but I would be happy to be wrong and have a better solution.
To give an idea of the number of members in a multicast group for the
D-Bus use case, I have 90 D-Bus connections on my session bus:
$ dbus-send --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep '":'|wc -l
90
In common cases, there should be only a few real recipients (1 or 2?)
after the socket filters eliminate most of them, but
unix_find_multicast_recipients() will still allocate an array of
about that size.
--