* Re: [PATCH] arch/tile: fix rwlock so would-be write lockers don't block new readers
From: Chris Metcalf @ 2010-11-22 13:35 UTC (permalink / raw)
To: Cypher Wu; +Cc: linux-kernel, Américo Wang, Eric Dumazet, netdev
In-Reply-To: <AANLkTikGj+zG9OqVJseKh4fGqQNnqnJpHgcaaXOL8nNi@mail.gmail.com>
On 11/22/2010 12:39 AM, Cypher Wu wrote:
> 2010/11/15 Chris Metcalf <cmetcalf@tilera.com>:
>> This avoids a deadlock in the IGMP code where one core gets a read
>> lock, another core starts trying to get a write lock (thus blocking
>> new readers), and then the first core tries to recursively re-acquire
>> the read lock.
>>
>> We still try to preserve some degree of balance by giving priority
>> to additional write lockers that come along while the lock is held
>> for write, so they can all complete quickly and return the lock to
>> the readers.
>>
>> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
>> ---
>> This should apply relatively cleanly to 2.6.26.7 source code too.
>> [...]
>
> I've finished my business trip and tested that patch for more than an
> hour and it works. The test is still running now.
>
> But it seems there still has a potential problem: we used ticket lock
> for write_lock(), and if there are so many write_lock() occurred, is
> 256 ticket enough for 64 or even more cores to avoiding overflow?
> Since is we try to write_unlock() and there's already write_lock()
> waiting we'll only adding current ticket.
This is OK, since each core can issue at most one (blocking) write_lock(),
and we have only 64 cores. Future >256 core machines will be based on
TILE-Gx anyway, which doesn't have the 256-core limit since it doesn't use
the spinlock_32.c implementation.
--
Chris Metcalf, Tilera Corp.
http://www.tilera.com
^ permalink raw reply
* Re: [PATCN net-next-2.6] drivers/net: use vzalloc()
From: Jon Mason @ 2010-11-22 14:42 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1290420906.2811.14.camel@edumazet-laptop>
On Mon, Nov 22, 2010 at 02:15:06AM -0800, Eric Dumazet wrote:
> Use vzalloc() and vzalloc_node() in net drivers
>
Acking the vxge portions.
Acked-by: Jon Mason <jon.mason@exar.com>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> ---
> People, I hope you dont mind if I make a single patch, and dont Cc all
> maintainers, for such trivial change.
>
> drivers/net/bnx2.c | 9 +------
> drivers/net/cxgb3/cxgb3_offload.c | 6 +---
> drivers/net/cxgb4/cxgb4_main.c | 6 +---
> drivers/net/e1000/e1000_main.c | 6 +---
> drivers/net/e1000e/netdev.c | 6 +---
> drivers/net/ehea/ehea_main.c | 4 ---
> drivers/net/igb/igb_main.c | 6 +---
> drivers/net/igbvf/netdev.c | 6 +---
> drivers/net/ixgb/ixgb_main.c | 6 +---
> drivers/net/ixgbe/ixgbe_main.c | 10 +++-----
> drivers/net/ixgbevf/ixgbevf_main.c | 6 +---
> drivers/net/netxen/netxen_nic_init.c | 6 +---
> drivers/net/pch_gbe/pch_gbe_main.c | 6 +---
> drivers/net/pptp.c | 3 --
> drivers/net/qlcnic/qlcnic_init.c | 6 +---
> drivers/net/sfc/filter.c | 3 --
> drivers/net/vxge/vxge-config.c | 31 ++++++-------------------
> 17 files changed, 39 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
> index 062600b..0de196d 100644
> --- a/drivers/net/bnx2.c
> +++ b/drivers/net/bnx2.c
> @@ -766,13 +766,10 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
> int j;
>
> rxr->rx_buf_ring =
> - vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
> + vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
> if (rxr->rx_buf_ring == NULL)
> return -ENOMEM;
>
> - memset(rxr->rx_buf_ring, 0,
> - SW_RXBD_RING_SIZE * bp->rx_max_ring);
> -
> for (j = 0; j < bp->rx_max_ring; j++) {
> rxr->rx_desc_ring[j] =
> dma_alloc_coherent(&bp->pdev->dev,
> @@ -785,13 +782,11 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
> }
>
> if (bp->rx_pg_ring_size) {
> - rxr->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
> + rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
> bp->rx_max_pg_ring);
> if (rxr->rx_pg_ring == NULL)
> return -ENOMEM;
>
> - memset(rxr->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
> - bp->rx_max_pg_ring);
> }
>
> for (j = 0; j < bp->rx_max_pg_ring; j++) {
> diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
> index bcf0753..ef02aa6 100644
> --- a/drivers/net/cxgb3/cxgb3_offload.c
> +++ b/drivers/net/cxgb3/cxgb3_offload.c
> @@ -1164,12 +1164,10 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
> */
> void *cxgb_alloc_mem(unsigned long size)
> {
> - void *p = kmalloc(size, GFP_KERNEL);
> + void *p = kzalloc(size, GFP_KERNEL);
>
> if (!p)
> - p = vmalloc(size);
> - if (p)
> - memset(p, 0, size);
> + p = vzalloc(size);
> return p;
> }
>
> diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
> index f50bc98..848f89d 100644
> --- a/drivers/net/cxgb4/cxgb4_main.c
> +++ b/drivers/net/cxgb4/cxgb4_main.c
> @@ -868,12 +868,10 @@ out: release_firmware(fw);
> */
> void *t4_alloc_mem(size_t size)
> {
> - void *p = kmalloc(size, GFP_KERNEL);
> + void *p = kzalloc(size, GFP_KERNEL);
>
> if (!p)
> - p = vmalloc(size);
> - if (p)
> - memset(p, 0, size);
> + p = vzalloc(size);
> return p;
> }
>
> diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
> index 4686c39..dcb7f82 100644
> --- a/drivers/net/e1000/e1000_main.c
> +++ b/drivers/net/e1000/e1000_main.c
> @@ -1425,13 +1425,12 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
> int size;
>
> size = sizeof(struct e1000_buffer) * txdr->count;
> - txdr->buffer_info = vmalloc(size);
> + txdr->buffer_info = vzalloc(size);
> if (!txdr->buffer_info) {
> e_err(probe, "Unable to allocate memory for the Tx descriptor "
> "ring\n");
> return -ENOMEM;
> }
> - memset(txdr->buffer_info, 0, size);
>
> /* round up to nearest 4K */
>
> @@ -1621,13 +1620,12 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
> int size, desc_len;
>
> size = sizeof(struct e1000_buffer) * rxdr->count;
> - rxdr->buffer_info = vmalloc(size);
> + rxdr->buffer_info = vzalloc(size);
> if (!rxdr->buffer_info) {
> e_err(probe, "Unable to allocate memory for the Rx descriptor "
> "ring\n");
> return -ENOMEM;
> }
> - memset(rxdr->buffer_info, 0, size);
>
> desc_len = sizeof(struct e1000_rx_desc);
>
> diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> index 9b3f0a9..0adcb79 100644
> --- a/drivers/net/e1000e/netdev.c
> +++ b/drivers/net/e1000e/netdev.c
> @@ -2059,10 +2059,9 @@ int e1000e_setup_tx_resources(struct e1000_adapter *adapter)
> int err = -ENOMEM, size;
>
> size = sizeof(struct e1000_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
> @@ -2095,10 +2094,9 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
> int i, size, desc_len, err = -ENOMEM;
>
> size = sizeof(struct e1000_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> for (i = 0; i < rx_ring->count; i++) {
> buffer_info = &rx_ring->buffer_info[i];
> diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
> index 182b2a7..a84c389 100644
> --- a/drivers/net/ehea/ehea_main.c
> +++ b/drivers/net/ehea/ehea_main.c
> @@ -1496,12 +1496,10 @@ static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
> {
> int arr_size = sizeof(void *) * max_q_entries;
>
> - q_skba->arr = vmalloc(arr_size);
> + q_skba->arr = vzalloc(arr_size);
> if (!q_skba->arr)
> return -ENOMEM;
>
> - memset(q_skba->arr, 0, arr_size);
> -
> q_skba->len = max_q_entries;
> q_skba->index = 0;
> q_skba->os_skbs = 0;
> diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
> index 892d196..67ea262 100644
> --- a/drivers/net/igb/igb_main.c
> +++ b/drivers/net/igb/igb_main.c
> @@ -2436,10 +2436,9 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
> int size;
>
> size = sizeof(struct igb_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
> @@ -2587,10 +2586,9 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
> int size, desc_len;
>
> size = sizeof(struct igb_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> desc_len = sizeof(union e1000_adv_rx_desc);
>
> diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
> index 4c998b7..8dbde23 100644
> --- a/drivers/net/igbvf/netdev.c
> +++ b/drivers/net/igbvf/netdev.c
> @@ -430,10 +430,9 @@ int igbvf_setup_tx_resources(struct igbvf_adapter *adapter,
> int size;
>
> size = sizeof(struct igbvf_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
> @@ -470,10 +469,9 @@ int igbvf_setup_rx_resources(struct igbvf_adapter *adapter,
> int size, desc_len;
>
> size = sizeof(struct igbvf_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> desc_len = sizeof(union e1000_adv_rx_desc);
>
> diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
> index caa8192..211a169 100644
> --- a/drivers/net/ixgb/ixgb_main.c
> +++ b/drivers/net/ixgb/ixgb_main.c
> @@ -669,13 +669,12 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
> int size;
>
> size = sizeof(struct ixgb_buffer) * txdr->count;
> - txdr->buffer_info = vmalloc(size);
> + txdr->buffer_info = vzalloc(size);
> if (!txdr->buffer_info) {
> netif_err(adapter, probe, adapter->netdev,
> "Unable to allocate transmit descriptor ring memory\n");
> return -ENOMEM;
> }
> - memset(txdr->buffer_info, 0, size);
>
> /* round up to nearest 4K */
>
> @@ -759,13 +758,12 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
> int size;
>
> size = sizeof(struct ixgb_buffer) * rxdr->count;
> - rxdr->buffer_info = vmalloc(size);
> + rxdr->buffer_info = vzalloc(size);
> if (!rxdr->buffer_info) {
> netif_err(adapter, probe, adapter->netdev,
> "Unable to allocate receive descriptor ring\n");
> return -ENOMEM;
> }
> - memset(rxdr->buffer_info, 0, size);
>
> /* Round up to nearest 4K */
>
> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
> index 5409af3..4249b51 100644
> --- a/drivers/net/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ixgbe/ixgbe_main.c
> @@ -5181,12 +5181,11 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
> int size;
>
> size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
> - tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node);
> + tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node);
> if (!tx_ring->tx_buffer_info)
> - tx_ring->tx_buffer_info = vmalloc(size);
> + tx_ring->tx_buffer_info = vzalloc(size);
> if (!tx_ring->tx_buffer_info)
> goto err;
> - memset(tx_ring->tx_buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
> @@ -5246,12 +5245,11 @@ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)
> int size;
>
> size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
> - rx_ring->rx_buffer_info = vmalloc_node(size, rx_ring->numa_node);
> + rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node);
> if (!rx_ring->rx_buffer_info)
> - rx_ring->rx_buffer_info = vmalloc(size);
> + rx_ring->rx_buffer_info = vzalloc(size);
> if (!rx_ring->rx_buffer_info)
> goto err;
> - memset(rx_ring->rx_buffer_info, 0, size);
>
> /* Round up to nearest 4K */
> rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
> diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
> index 5b8063c..2216a3c 100644
> --- a/drivers/net/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ixgbevf/ixgbevf_main.c
> @@ -2489,10 +2489,9 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter,
> int size;
>
> size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count;
> - tx_ring->tx_buffer_info = vmalloc(size);
> + tx_ring->tx_buffer_info = vzalloc(size);
> if (!tx_ring->tx_buffer_info)
> goto err;
> - memset(tx_ring->tx_buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
> @@ -2556,14 +2555,13 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
> int size;
>
> size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count;
> - rx_ring->rx_buffer_info = vmalloc(size);
> + rx_ring->rx_buffer_info = vzalloc(size);
> if (!rx_ring->rx_buffer_info) {
> hw_dbg(&adapter->hw,
> "Unable to vmalloc buffer memory for "
> "the receive descriptor ring\n");
> goto alloc_failed;
> }
> - memset(rx_ring->rx_buffer_info, 0, size);
>
> /* Round up to nearest 4K */
> rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
> diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
> index 95fe552..f946de2 100644
> --- a/drivers/net/netxen/netxen_nic_init.c
> +++ b/drivers/net/netxen/netxen_nic_init.c
> @@ -214,13 +214,12 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
> tx_ring->num_desc = adapter->num_txd;
> tx_ring->txq = netdev_get_tx_queue(netdev, 0);
>
> - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
> + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
> if (cmd_buf_arr == NULL) {
> dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
> netdev->name);
> goto err_out;
> }
> - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
> tx_ring->cmd_buf_arr = cmd_buf_arr;
>
> recv_ctx = &adapter->recv_ctx;
> @@ -280,7 +279,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
>
> }
> rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
> - vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
> + vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
> if (rds_ring->rx_buf_arr == NULL) {
> printk(KERN_ERR "%s: Failed to allocate "
> "rx buffer ring %d\n",
> @@ -288,7 +287,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
> /* free whatever was already allocated */
> goto err_out;
> }
> - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
> INIT_LIST_HEAD(&rds_ring->free_list);
> /*
> * Now go through all of them, set reference handles
> diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
> index 472056b..afb7506 100644
> --- a/drivers/net/pch_gbe/pch_gbe_main.c
> +++ b/drivers/net/pch_gbe/pch_gbe_main.c
> @@ -1523,12 +1523,11 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
> int desNo;
>
> size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info) {
> pr_err("Unable to allocate memory for the buffer infomation\n");
> return -ENOMEM;
> }
> - memset(tx_ring->buffer_info, 0, size);
>
> tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
>
> @@ -1573,12 +1572,11 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
> int desNo;
>
> size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info) {
> pr_err("Unable to allocate memory for the receive descriptor ring\n");
> return -ENOMEM;
> }
> - memset(rx_ring->buffer_info, 0, size);
> rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
> rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
> &rx_ring->dma, GFP_KERNEL);
> diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
> index ccbc913..7556a92 100644
> --- a/drivers/net/pptp.c
> +++ b/drivers/net/pptp.c
> @@ -673,8 +673,7 @@ static int __init pptp_init_module(void)
> int err = 0;
> pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
>
> - callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *),
> - GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
> + callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
> if (!callid_sock) {
> pr_err("PPTP: cann't allocate memory\n");
> return -ENOMEM;
> diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
> index 0d180c6..3f97018 100644
> --- a/drivers/net/qlcnic/qlcnic_init.c
> +++ b/drivers/net/qlcnic/qlcnic_init.c
> @@ -236,12 +236,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
> tx_ring->num_desc = adapter->num_txd;
> tx_ring->txq = netdev_get_tx_queue(netdev, 0);
>
> - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
> + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
> if (cmd_buf_arr == NULL) {
> dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n");
> goto err_out;
> }
> - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
> tx_ring->cmd_buf_arr = cmd_buf_arr;
>
> recv_ctx = &adapter->recv_ctx;
> @@ -276,13 +275,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
> break;
> }
> rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
> - vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
> + vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
> if (rds_ring->rx_buf_arr == NULL) {
> dev_err(&netdev->dev, "Failed to allocate "
> "rx buffer ring %d\n", ring);
> goto err_out;
> }
> - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
> INIT_LIST_HEAD(&rds_ring->free_list);
> /*
> * Now go through all of them, set reference handles
> diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
> index 52cb608..44500b5 100644
> --- a/drivers/net/sfc/filter.c
> +++ b/drivers/net/sfc/filter.c
> @@ -428,10 +428,9 @@ int efx_probe_filters(struct efx_nic *efx)
> GFP_KERNEL);
> if (!table->used_bitmap)
> goto fail;
> - table->spec = vmalloc(table->size * sizeof(*table->spec));
> + table->spec = vzalloc(table->size * sizeof(*table->spec));
> if (!table->spec)
> goto fail;
> - memset(table->spec, 0, table->size * sizeof(*table->spec));
> }
>
> return 0;
> diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
> index 409c2e6..44d3ddd 100644
> --- a/drivers/net/vxge/vxge-config.c
> +++ b/drivers/net/vxge/vxge-config.c
> @@ -1220,13 +1220,12 @@ vxge_hw_device_initialize(
> goto exit;
>
> hldev = (struct __vxge_hw_device *)
> - vmalloc(sizeof(struct __vxge_hw_device));
> + vzalloc(sizeof(struct __vxge_hw_device));
> if (hldev == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
>
> - memset(hldev, 0, sizeof(struct __vxge_hw_device));
> hldev->magic = VXGE_HW_DEVICE_MAGIC;
>
> vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL);
> @@ -2064,15 +2063,12 @@ __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate,
> * allocate new memblock and its private part at once.
> * This helps to minimize memory usage a lot. */
> mempool->memblocks_priv_arr[i] =
> - vmalloc(mempool->items_priv_size * n_items);
> + vzalloc(mempool->items_priv_size * n_items);
> if (mempool->memblocks_priv_arr[i] == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
>
> - memset(mempool->memblocks_priv_arr[i], 0,
> - mempool->items_priv_size * n_items);
> -
> /* allocate DMA-capable memblock */
> mempool->memblocks_arr[i] =
> __vxge_hw_blockpool_malloc(mempool->devh,
> @@ -2145,12 +2141,11 @@ __vxge_hw_mempool_create(
> }
>
> mempool = (struct vxge_hw_mempool *)
> - vmalloc(sizeof(struct vxge_hw_mempool));
> + vzalloc(sizeof(struct vxge_hw_mempool));
> if (mempool == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
> - memset(mempool, 0, sizeof(struct vxge_hw_mempool));
>
> mempool->devh = devh;
> mempool->memblock_size = memblock_size;
> @@ -2170,31 +2165,27 @@ __vxge_hw_mempool_create(
>
> /* allocate array of memblocks */
> mempool->memblocks_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
> + (void **) vzalloc(sizeof(void *) * mempool->memblocks_max);
> if (mempool->memblocks_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_arr, 0,
> - sizeof(void *) * mempool->memblocks_max);
>
> /* allocate array of private parts of items per memblocks */
> mempool->memblocks_priv_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
> + (void **) vzalloc(sizeof(void *) * mempool->memblocks_max);
> if (mempool->memblocks_priv_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_priv_arr, 0,
> - sizeof(void *) * mempool->memblocks_max);
>
> /* allocate array of memblocks DMA objects */
> mempool->memblocks_dma_arr = (struct vxge_hw_mempool_dma *)
> - vmalloc(sizeof(struct vxge_hw_mempool_dma) *
> + vzalloc(sizeof(struct vxge_hw_mempool_dma) *
> mempool->memblocks_max);
>
> if (mempool->memblocks_dma_arr == NULL) {
> @@ -2203,20 +2194,16 @@ __vxge_hw_mempool_create(
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_dma_arr, 0,
> - sizeof(struct vxge_hw_mempool_dma) *
> - mempool->memblocks_max);
>
> /* allocate hash array of items */
> mempool->items_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->items_max);
> + (void **) vzalloc(sizeof(void *) * mempool->items_max);
> if (mempool->items_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->items_arr, 0, sizeof(void *) * mempool->items_max);
>
> /* calculate initial number of memblocks */
> memblocks_to_allocate = (mempool->items_initial +
> @@ -4272,14 +4259,12 @@ vxge_hw_vpath_open(struct __vxge_hw_device *hldev,
> goto vpath_open_exit1;
>
> vp = (struct __vxge_hw_vpath_handle *)
> - vmalloc(sizeof(struct __vxge_hw_vpath_handle));
> + vzalloc(sizeof(struct __vxge_hw_vpath_handle));
> if (vp == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto vpath_open_exit2;
> }
>
> - memset(vp, 0, sizeof(struct __vxge_hw_vpath_handle));
> -
> vp->vpath = vpath;
>
> if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
The information and any attached documents contained in this message
may be confidential and/or legally privileged. The message is
intended solely for the addressee(s). If you are not the intended
recipient, you are hereby notified that any use, dissemination, or
reproduction is strictly prohibited and may be unlawful. If you are
not the intended recipient, please contact the sender immediately by
return e-mail and destroy all copies of the original message.
^ permalink raw reply
* Re: iwl3945: regression - unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
From: David Miller @ 2010-11-22 15:36 UTC (permalink / raw)
To: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w
Cc: mhocko-AlSwsSmVLrQ, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
reinette.chatre-ral2JQCrhuEAvxtiuMwx3w,
wey-yi.w.guy-ral2JQCrhuEAvxtiuMwx3w, ilw-VuQAYsv1563Yd54FQh9/CA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1290424776.2811.32.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Mon, 22 Nov 2010 12:19:36 +0100
> Oh well, it seems David put the fix in net-next-2.6 instead of net-2.6
>
> Please try :
>
> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=9d82ca98f71fd686ef2f3017c5e3e6a4871b6e46
My bad, I'll toss this into net-2.6
Thanks for catching this Eric.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 56/62] iwlwifi: Use static const
From: Guy, Wey-Yi @ 2010-11-22 15:37 UTC (permalink / raw)
To: Joe Perches
Cc: Stefano Brivio, Chatre, Reinette, Intel Linux Wireless,
John W. Linville,
linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <2773a20a26f4e326f0849e8ae8fb4f347d6a6ecb.1290305776.git.joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
Hi Joe,
On Sat, 2010-11-20 at 18:38 -0800, Joe Perches wrote:
> Using static const generally increases object text and decreases data size.
> It also generally decreases overall object size.
>
> text data bss dec hex filename
> 48644 57 12120 60821 ed95 drivers/net/wireless/b43/phy_n.o.new
> 48661 57 12120 60838 eda6 drivers/net/wireless/b43/phy_n.o.old
> 37906 86 7904 45896 b348 drivers/net/wireless/iwlwifi/iwl-agn-lib.o.new
> 37937 86 7904 45927 b367 drivers/net/wireless/iwlwifi/iwl-agn-lib.o.old
> 37781 523 6752 45056 b000 drivers/net/wireless/iwlwifi/iwl-3945.o.new
> 37781 523 6752 45056 b000 drivers/net/wireless/iwlwifi/iwl-3945.o.old
>
> Changed b43_nphy_write_clip_detection to take a const u16 *
>
> Signed-off-by: Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
> ---
I don't see size difference on 3945, otherwise the patch looks ok to me
Wey
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 00/00] Remove deprecated items from Makefiles
From: David Miller @ 2010-11-22 16:17 UTC (permalink / raw)
To: tdent48227
Cc: marcel, padovan, linux-bluetooth, netdev, sjur.brandeland,
socketcan, urs.thuermann, socketcan-core, sage, ceph-devel,
wang840925, jlayton, kaber, pekkas, linux-kernel, netfilter-devel,
netfilter, samuel
In-Reply-To: <1290387808-2239-1-git-send-email-tdent48227@gmail.com>
From: Tracey Dent <tdent48227@gmail.com>
Date: Sun, 21 Nov 2010 20:03:11 -0500
> I changed Makefiles to use <modules>-y instead of <modules>-objs because -objs
> is deprecated and not even mentioned in Documentation/kbuild/makefiles.txt.
>
> Also, remove some if-conditional statments because I used the ccflags-$ flag
> instead of EXTRA_CFLAGS because EXTRA_CFLAGS.
All applied, thanks Tracey.
^ permalink raw reply
* Re: linux-next: Tree for November 18 (netfilter)
From: Randy Dunlap @ 2010-11-22 16:19 UTC (permalink / raw)
To: KOVACS Krisztian
Cc: Patrick McHardy, Stephen Rothwell, netfilter-devel, linux-next,
LKML, netdev, Balazs Scheidler
In-Reply-To: <1290428929.726241.1.camel@nienna.balabit>
On 11/22/10 04:28, KOVACS Krisztian wrote:
> Hi,
>
> On Mon, 2010-11-22 at 13:14 +0100, KOVACS Krisztian wrote:
>> Indeed, we were missing quite a few of those ifdefs... The patch below
>> seems to fix the issue for me.
>>
>> commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
>> Author: KOVACS Krisztian <hidden@balabit.hu>
>> Date: Mon Nov 22 13:07:15 2010 +0100
>
> Bah, it seems the patch got line-wrapped by my MUA, here it is again.
> Let's hope I got it right this time...
>
> commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
> Author: KOVACS Krisztian <hidden@balabit.hu>
> Date: Mon Nov 22 13:07:15 2010 +0100
>
> netfilter: fix compilation when conntrack is disabled but tproxy is enabled
>
> The IPv6 tproxy patches split IPv6 defragmentation off of conntrack, but
> failed to update the #ifdef stanzas guarding the defragmentation related
> fields and code in skbuff and conntrack related code in nf_defrag_ipv6.c.
>
> This patch adds the required #ifdefs so that IPv6 tproxy can truly be used
> without connection tracking.
>
> Original report:
> http://marc.info/?l=linux-netdev&m=129010118516341&w=2
>
> Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
> Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
That builds. Thanks.
Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index e6ba898..4f2db79 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -255,6 +255,11 @@ typedef unsigned int sk_buff_data_t;
> typedef unsigned char *sk_buff_data_t;
> #endif
>
> +#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
> + defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
> +#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
> +#endif
> +
> /**
> * struct sk_buff - socket buffer
> * @next: Next buffer in list
> @@ -362,6 +367,8 @@ struct sk_buff {
> void (*destructor)(struct sk_buff *skb);
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> struct nf_conntrack *nfct;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> struct sk_buff *nfct_reasm;
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> @@ -2051,6 +2058,8 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
> if (nfct)
> atomic_inc(&nfct->use);
> }
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
> {
> if (skb)
> @@ -2079,6 +2088,8 @@ static inline void nf_reset(struct sk_buff *skb)
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(skb->nfct);
> skb->nfct = NULL;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(skb->nfct_reasm);
> skb->nfct_reasm = NULL;
> #endif
> @@ -2095,6 +2106,8 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
> dst->nfct = src->nfct;
> nf_conntrack_get(src->nfct);
> dst->nfctinfo = src->nfctinfo;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> dst->nfct_reasm = src->nfct_reasm;
> nf_conntrack_get_reasm(src->nfct_reasm);
> #endif
> @@ -2108,6 +2121,8 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
> {
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(dst->nfct);
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(dst->nfct_reasm);
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> index 1ee717e..a4c9936 100644
> --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> @@ -7,16 +7,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
> extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
> extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
>
> -extern int nf_ct_frag6_init(void);
> -extern void nf_ct_frag6_cleanup(void);
> -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
> -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
> - struct net_device *in,
> - struct net_device *out,
> - int (*okfn)(struct sk_buff *));
> -
> -struct inet_frags_ctl;
> -
> #include <linux/sysctl.h>
> extern struct ctl_table nf_ct_ipv6_sysctl_table[];
>
> diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> index 94dd54d..fd79c9a 100644
> --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> @@ -3,4 +3,14 @@
>
> extern void nf_defrag_ipv6_enable(void);
>
> +extern int nf_ct_frag6_init(void);
> +extern void nf_ct_frag6_cleanup(void);
> +extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
> +extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
> + struct net_device *in,
> + struct net_device *out,
> + int (*okfn)(struct sk_buff *));
> +
> +struct inet_frags_ctl;
> +
> #endif /* _NF_DEFRAG_IPV6_H */
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 104f844..74ebf4b 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -380,6 +380,8 @@ static void skb_release_head_state(struct sk_buff *skb)
> }
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(skb->nfct);
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(skb->nfct_reasm);
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> index 99abfb5..97c5b21 100644
> --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> @@ -19,13 +19,15 @@
>
> #include <linux/netfilter_ipv6.h>
> #include <linux/netfilter_bridge.h>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> #include <net/netfilter/nf_conntrack.h>
> #include <net/netfilter/nf_conntrack_helper.h>
> #include <net/netfilter/nf_conntrack_l4proto.h>
> #include <net/netfilter/nf_conntrack_l3proto.h>
> #include <net/netfilter/nf_conntrack_core.h>
> -#include <net/netfilter/nf_conntrack_zones.h>
> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
> +#endif
> +#include <net/netfilter/nf_conntrack_zones.h>
> #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
>
> static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
> @@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
> {
> u16 zone = NF_CT_DEFAULT_ZONE;
>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> if (skb->nfct)
> zone = nf_ct_zone((struct nf_conn *)skb->nfct);
> +#endif
>
> #ifdef CONFIG_BRIDGE_NETFILTER
> if (skb->nf_bridge &&
> @@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
> {
> struct sk_buff *reasm;
>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> /* Previously seen (loopback)? */
> if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
> return NF_ACCEPT;
> +#endif
>
> reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
> /* queued */
>
>
--
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [PATCH] macvlan: Introduce 'passthru' mode to takeover the underlying device
From: David Miller @ 2010-11-22 16:24 UTC (permalink / raw)
To: sri; +Cc: arnd, kaber, shemminger, mst, netdev, kvm
In-Reply-To: <1288307450.30131.82.camel@sridhar.beaverton.ibm.com>
From: Sridhar Samudrala <sri@us.ibm.com>
Date: Thu, 28 Oct 2010 16:10:50 -0700
> With the current default 'vepa' mode, a KVM guest using virtio with
> macvtap backend has the following limitations.
> - cannot change/add a mac address on the guest virtio-net
> - cannot create a vlan device on the guest virtio-net
> - cannot enable promiscuous mode on guest virtio-net
>
> To address these limitations, this patch introduces a new mode called
> 'passthru' when creating a macvlan device which allows takeover of the
> underlying device and passing it to a guest using virtio with macvtap
> backend.
>
> Only one macvlan device is allowed in passthru mode and it inherits
> the mac address from the underlying device and sets it in promiscuous
> mode to receive and forward all the packets.
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Applied, thanks Sridhar.
^ permalink raw reply
* Re: [PATCH] qlge: Fix incorrect usage of module parameters and netdev msg level
From: David Miller @ 2010-11-22 16:29 UTC (permalink / raw)
To: sonnyrao; +Cc: netdev, miltonm, ron.mercer, linux-driver, linux-kernel
In-Reply-To: <1290075903-3038-1-git-send-email-sonnyrao@linux.vnet.ibm.com>
From: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
Date: Thu, 18 Nov 2010 04:25:03 -0600
> Driver appears to be mistaking the permission field with default value
> in the case of debug and qlge_irq_type.
>
> Driver is also passing debug as a bitmask into netif_msg_init()
> which really wants a number of bits, so fix that.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
Applied, thanks Sonny.
^ permalink raw reply
* Re: [PATCH 0/2] phylib: Cleanup marvell.c and add 88E1149R support.
From: David Miller @ 2010-11-22 16:34 UTC (permalink / raw)
To: ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, cyril-l0cyMroinI0,
arnaud.patard-dQbF7i+pzddAfugRpC6u6w
In-Reply-To: <1290203933-28251-1-git-send-email-ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
From: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Date: Fri, 19 Nov 2010 13:58:51 -0800
> This is the second iteration of this patch. I have split out the
> device tree support from the first version to a different patch set.
> The 88E1149R support is useful 'stand alone', so if it is acceptable,
> it can be merged first.
>
> The first patch is a small cleanup suggested by Cyril Chemparathy, the
> second one adds basic 88E1149R support.
All applied to net-2.6, thanks.
^ permalink raw reply
* Re: [PATCH v2] of/phylib: Use device tree properties to initialize Marvell PHYs.
From: David Miller @ 2010-11-22 16:35 UTC (permalink / raw)
To: grant.likely-s3s/WqlpOiPyB63q8FvJNQ
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, cyril-l0cyMroinI0,
arnaud.patard-dQbF7i+pzddAfugRpC6u6w
In-Reply-To: <20101120042848.GB7005-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Date: Fri, 19 Nov 2010 21:28:49 -0700
> On Fri, Nov 19, 2010 at 02:13:18PM -0800, David Daney wrote:
>> Some aspects of PHY initialization are board dependent, things like
>> indicator LED connections and some clocking modes cannot be determined
>> by probing. The dev_flags element of struct phy_device can be used to
>> control these things if an appropriate value can be passed from the
>> Ethernet driver. We run into problems however if the PHY connections
>> are specified by the device tree. There is no way for the Ethernet
>> driver to know what flags it should pass.
>>
>> If we are using the device tree, the struct phy_device will be
>> populated with the device tree node corresponding to the PHY, and we
>> can extract extra configuration information from there.
>>
>> The next question is what should the format of that information be?
>> It is highly device specific, and the device tree representation
>> should not be tied to any arbitrary kernel defined constants. A
>> straight forward representation is just to specify the exact bits that
>> should be set using the "marvell,reg-init" property:
>>
>> phy5: ethernet-phy@5 {
>> reg = <5>;
>> compatible = "marvell,88e1149r";
>> marvell,reg-init =
>> /* led[0]:1000, led[1]:100, led[2]:10, led[3]:tx */
>> <3 0x10 0 0x5777>, /* Reg 3,16 <- 0x5777 */
>> /* mix %:0, led[0123]:drive low off hiZ */
>> <3 0x11 0 0x00aa>, /* Reg 3,17 <- 0x00aa */
>> /* default blink periods. */
>> <3 0x12 0 0x4105>, /* Reg 3,18 <- 0x4105 */
>> /* led[4]:rx, led[5]:dplx, led[45]:drive low off hiZ */
>> <3 0x13 0 0x0a60>; /* Reg 3,19 <- 0x0a60 */
>> };
>>
>> phy6: ethernet-phy@6 {
>> reg = <6>;
>> compatible = "marvell,88e1118";
>> marvell,reg-init =
>> /* Fix rx and tx clock transition timing */
>> <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
>> /* Adjust LED drive. */
>> <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
>> /* irq, blink-activity, blink-link */
>> <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
>> };
>>
>> The Marvell PHYs have a page select register at register 22 (0x16), we
>> can specify any register by its page and register number. These are
>> the first and second word. The third word contains a mask to be ANDed
>> with the existing register value, and the fourth word is ORed with the
>> result to yield the new register value. The new marvell_of_reg_init
>> function leaves the page select register unchanged, so a call to it
>> can be dropped into the .config_init functions without unduly
>> affecting the state of the PHY.
>>
>> If CONFIG_OF_MDIO is not set, there is no of_node, or no
>> "marvell,reg-init" property, the PHY initialization is unchanged.
>>
>> Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
>> Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
>> Cc: Cyril Chemparathy <cyril-l0cyMroinI0@public.gmane.org>
>> Cc: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
>> Cc: Arnaud Patard <arnaud.patard-dQbF7i+pzddAfugRpC6u6w@public.gmane.org>
>> Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
>
> Untested/compiled, but looks good to me.
>
> Reviewed-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Also applied, thanks everyone.
^ permalink raw reply
* Re: [PATCH 14/62] cxgb4vf: Use static const
From: Casey Leedom @ 2010-11-22 17:42 UTC (permalink / raw)
To: Joe Perches; +Cc: netdev, linux-kernel
In-Reply-To: <d0a433aa6bbe20dfe4fd4f3ca9aec50f97601403.1290305776.git.joe@perches.com>
| From: Joe Perches <joe@perches.com>
| Date: Saturday, November 20, 2010 06:38 pm
|
| Using static const generally increases object text and decreases data size.
| It also generally decreases overall object size.
|
| text data bss dec hex filename
| 10179 56 2216 12451 30a3 drivers/net/cxgb4vf/t4vf_hw.o.new
| 10179 56 2216 12451 30a3 drivers/net/cxgb4vf/t4vf_hw.o.old
|
| Signed-off-by: Joe Perches <joe@perches.com>
| ---
| drivers/net/cxgb4vf/t4vf_hw.c | 2 +-
| 1 files changed, 1 insertions(+), 1 deletions(-)
|
| diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c
| index f7d7f97..daedf6e 100644
| --- a/drivers/net/cxgb4vf/t4vf_hw.c
| +++ b/drivers/net/cxgb4vf/t4vf_hw.c
| @@ -116,7 +116,7 @@ static void dump_mbox(struct adapter *adapter, const
| char *tag, u32 mbox_data) int t4vf_wr_mbox_core(struct adapter *adapter,
| const void *cmd, int size, void *rpl, bool sleep_ok)
| {
| - static int delay[] = {
| + static const int delay[] = {
| 1, 1, 3, 5, 10, 10, 20, 50, 100
| };
Looks okay to me. Thanks!
Casey
^ permalink raw reply
* [PATCH 1/9] AF_UNIX: Add constant for Unix socket options level
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
Assign the next free socket options level to be used by the Unix
protocol and address family.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
include/linux/socket.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 86b652f..7c5a4da 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -307,6 +307,7 @@ struct ucred {
#define SOL_RDS 276
#define SOL_IUCV 277
#define SOL_CAIF 278
+#define SOL_UNIX 279
/* IPX options */
#define IPX_TYPE 1
--
1.7.1
^ permalink raw reply related
* [PATCH 2/9] AF_UNIX: add setsockopt on Unix sockets
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
net/unix/af_unix.c | 15 ++++++++++++---
1 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 7ff31c6..6eca106 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -512,6 +512,8 @@ static unsigned int unix_dgram_poll(struct file *, struct socket *,
poll_table *);
static int unix_ioctl(struct socket *, unsigned int, unsigned long);
static int unix_shutdown(struct socket *, int);
+static int unix_setsockopt(struct socket *, int, int,
+ char __user *, unsigned int);
static int unix_stream_sendmsg(struct kiocb *, struct socket *,
struct msghdr *, size_t);
static int unix_stream_recvmsg(struct kiocb *, struct socket *,
@@ -538,7 +540,7 @@ static const struct proto_ops unix_stream_ops = {
.ioctl = unix_ioctl,
.listen = unix_listen,
.shutdown = unix_shutdown,
- .setsockopt = sock_no_setsockopt,
+ .setsockopt = unix_setsockopt,
.getsockopt = sock_no_getsockopt,
.sendmsg = unix_stream_sendmsg,
.recvmsg = unix_stream_recvmsg,
@@ -559,7 +561,7 @@ static const struct proto_ops unix_dgram_ops = {
.ioctl = unix_ioctl,
.listen = sock_no_listen,
.shutdown = unix_shutdown,
- .setsockopt = sock_no_setsockopt,
+ .setsockopt = unix_setsockopt,
.getsockopt = sock_no_getsockopt,
.sendmsg = unix_dgram_sendmsg,
.recvmsg = unix_dgram_recvmsg,
@@ -580,7 +582,7 @@ static const struct proto_ops unix_seqpacket_ops = {
.ioctl = unix_ioctl,
.listen = unix_listen,
.shutdown = unix_shutdown,
- .setsockopt = sock_no_setsockopt,
+ .setsockopt = unix_setsockopt,
.getsockopt = sock_no_getsockopt,
.sendmsg = unix_seqpacket_sendmsg,
.recvmsg = unix_dgram_recvmsg,
@@ -1533,6 +1535,13 @@ out:
}
+static int unix_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
+{
+ return -EOPNOTSUPP;
+}
+
+
static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
--
1.7.1
^ permalink raw reply related
* [PATCH 3/9] AF_UNIX: create, join and leave multicast groups with setsockopt
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
Multicast is implemented on SOCK_DGRAM and SOCK_SEQPACKET Unix sockets.
An userspace application can create a multicast group with:
struct unix_mreq mreq;
mreq.address.sun_family = AF_UNIX;
mreq.address.sun_path[0] = '\0';
strcpy(mreq.address.sun_path + 1, "socket-address");
mreq.flags = 0;
sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
ret = setsockopt(sockfd, SOL_UNIX, UNIX_CREATE_GROUP, &mreq, sizeof(mreq));
Then a multicast group can be joined and left with:
ret = setsockopt(sockfd, SOL_UNIX, UNIX_JOIN_GROUP, &mreq, sizeof(mreq));
ret = setsockopt(sockfd, SOL_UNIX, UNIX_LEAVE_GROUP, &mreq, sizeof(mreq));
A socket can be a member of several multicast group.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
include/net/af_unix.h | 31 +++++++
net/unix/af_unix.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 247 insertions(+), 1 deletions(-)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 90c9e28..bf114d5 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -40,6 +40,18 @@ struct unix_skb_parms {
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
+#define UNIX_MREQ_LOOPBACK 0x01
+struct unix_mreq
+{
+ struct sockaddr_un address;
+ unsigned int flags;
+};
+
+/* UNIX socket options */
+#define UNIX_CREATE_GROUP 1
+#define UNIX_JOIN_GROUP 2
+#define UNIX_LEAVE_GROUP 3
+
#ifdef __KERNEL__
/* The AF_UNIX socket */
struct unix_sock {
@@ -56,8 +68,27 @@ struct unix_sock {
spinlock_t lock;
unsigned int gc_candidate : 1;
unsigned int gc_maybe_cycle : 1;
+ unsigned int is_mcast_addr : 1;
+
+ /* These multicast fields are protected by the global spinlock
+ * unix_multicast_lock */
+ struct hlist_head mcast_subscriptions;
+ struct hlist_head mcast_members;
+ int mcast_subscriptions_cnt;
+ int mcast_members_cnt;
+
struct socket_wq peer_wq;
};
+
+struct unix_mcast
+{
+ struct unix_sock *member;
+ struct unix_sock *addr;
+ unsigned int flags;
+ struct hlist_node subscription_node;
+ struct hlist_node member_node;
+};
+
#define unix_sk(__sk) ((struct unix_sock *)__sk)
#define peer_wait peer_wq.wait
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6eca106..2278829 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -379,6 +379,9 @@ static int unix_release_sock(struct sock *sk, int embrion)
struct sock *skpair;
struct sk_buff *skb;
int state;
+ struct unix_mcast *node;
+ struct hlist_node *pos;
+ struct hlist_node *pos_tmp;
unix_remove_socket(sk);
@@ -392,6 +395,24 @@ static int unix_release_sock(struct sock *sk, int embrion)
u->mnt = NULL;
state = sk->sk_state;
sk->sk_state = TCP_CLOSE;
+ spin_lock(&unix_multicast_lock);
+ hlist_for_each_entry_safe(node, pos, pos_tmp, &u->mcast_subscriptions,
+ subscription_node) {
+ hlist_del(&node->member_node);
+ hlist_del(&node->subscription_node);
+ node->addr->mcast_members_cnt--;
+ node->member->mcast_subscriptions_cnt--;
+ kfree(node);
+ }
+ hlist_for_each_entry_safe(node, pos, pos_tmp, &u->mcast_members,
+ member_node) {
+ hlist_del(&node->member_node);
+ hlist_del(&node->subscription_node);
+ node->addr->mcast_members_cnt--;
+ node->member->mcast_subscriptions_cnt--;
+ kfree(node);
+ }
+ spin_unlock(&unix_multicast_lock);
unix_state_unlock(sk);
wake_up_interruptible_all(&u->peer_wait);
@@ -631,6 +652,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock)
atomic_long_set(&u->inflight, 0);
INIT_LIST_HEAD(&u->link);
mutex_init(&u->readlock); /* single task reading lock */
+ INIT_HLIST_HEAD(&u->mcast_subscriptions);
+ INIT_HLIST_HEAD(&u->mcast_members);
init_waitqueue_head(&u->peer_wait);
unix_insert_socket(unix_sockets_unbound, sk);
out:
@@ -1535,10 +1558,202 @@ out:
}
+static int unix_mc_create(struct socket *sock, struct unix_mreq *mreq)
+{
+ struct sock *other;
+ int err;
+ unsigned hash;
+ int namelen;
+
+ if (mreq->address.sun_family != AF_UNIX ||
+ mreq->address.sun_path[0] != '\0')
+ return -EINVAL;
+
+ err = unix_mkname(&mreq->address, sizeof(struct sockaddr_un), &hash);
+ if (err < 0)
+ return err;
+
+ namelen = err;
+ other = unix_find_other(sock_net(sock->sk), &mreq->address, namelen,
+ sock->type, hash, &err);
+ if (other)
+ return -EADDRINUSE;
+
+ err = sock->ops->bind(sock,
+ (struct sockaddr*)&mreq->address,
+ sizeof(struct sockaddr_un));
+ if (err < 0)
+ return err;
+
+ unix_state_lock(sock->sk);
+ unix_sk(sock->sk)->is_mcast_addr = 1;
+ unix_state_unlock(sock->sk);
+
+ return 0;
+}
+
+
+static int unix_mc_join(struct socket *sock, struct unix_mreq *mreq)
+{
+ struct unix_sock *u = unix_sk(sock->sk);
+ struct sock *other;
+ struct unix_sock *otheru;
+ struct unix_mcast *node;
+ int err;
+ unsigned hash;
+ int namelen;
+
+ if (mreq->address.sun_family != AF_UNIX ||
+ mreq->address.sun_path[0] != '\0')
+ return -EINVAL;
+
+ err = unix_autobind(sock);
+ if (err < 0)
+ return err;
+
+ err = unix_mkname(&mreq->address, sizeof(struct sockaddr_un), &hash);
+ if (err < 0)
+ return err;
+
+ namelen = err;
+ other = unix_find_other(sock_net(sock->sk), &mreq->address, namelen,
+ sock->type, hash, &err);
+ if (!other)
+ return -EINVAL;
+
+ if (other && !unix_sk(other)->is_mcast_addr) {
+ err = -EADDRINUSE;
+ goto sock_put_out;
+ }
+
+ otheru = unix_sk(other);
+
+ node = kmalloc(sizeof(struct unix_mcast), GFP_KERNEL);
+ if (!node) {
+ err = -ENOMEM;
+ goto sock_put_out;
+ }
+ node->member = u;
+ node->addr = otheru;
+ node->flags = mreq->flags;
+
+ spin_lock(&unix_multicast_lock);
+ hlist_add_head(&node->member_node, &otheru->mcast_members);
+ hlist_add_head(&node->subscription_node, &u->mcast_subscriptions);
+ otheru->mcast_members_cnt++;
+ u->mcast_subscriptions_cnt++;
+ spin_unlock(&unix_multicast_lock);
+
+ return 0;
+
+sock_put_out:
+ sock_put(other);
+ return err;
+}
+
+
+static int unix_mc_leave(struct socket *sock, struct unix_mreq *mreq)
+{
+ struct unix_sock *u = unix_sk(sock->sk);
+ struct sock *other;
+ struct unix_sock *otheru;
+ struct unix_mcast *node;
+ struct hlist_node *pos;
+ int err;
+ unsigned hash;
+ int namelen;
+
+ if (mreq->address.sun_family != AF_UNIX ||
+ mreq->address.sun_path[0] != '\0')
+ return -EINVAL;
+
+ err = unix_mkname(&mreq->address, sizeof(struct sockaddr_un), &hash);
+ if (err < 0)
+ return err;
+
+ namelen = err;
+ other = unix_find_other(sock_net(sock->sk), &mreq->address, namelen,
+ sock->type, hash, &err);
+ if (!other)
+ return -EINVAL;
+
+ otheru = unix_sk(other);
+
+ if (!otheru->is_mcast_addr) {
+ err = -EINVAL;
+ goto sock_put_out;
+ }
+
+ spin_lock(&unix_multicast_lock);
+
+ hlist_for_each_entry(node, pos, &u->mcast_subscriptions,
+ subscription_node) {
+ if (node->addr == otheru)
+ break;
+ }
+
+ if (!pos) {
+ spin_unlock(&unix_multicast_lock);
+ err = -EINVAL;
+ goto sock_put_out;
+ }
+
+ hlist_del(&node->member_node);
+ hlist_del(&node->subscription_node);
+ otheru->mcast_members_cnt--;
+ u->mcast_subscriptions_cnt--;
+ spin_unlock(&unix_multicast_lock);
+ kfree(node);
+ err = 0;
+
+sock_put_out:
+ sock_put(other);
+ return err;
+}
+
+
static int unix_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
- return -EOPNOTSUPP;
+ struct unix_mreq mreq;
+ int err = 0;
+
+ if (level != SOL_UNIX)
+ return -ENOPROTOOPT;
+
+ switch (optname) {
+ case UNIX_CREATE_GROUP:
+ case UNIX_JOIN_GROUP:
+ case UNIX_LEAVE_GROUP:
+ if (optlen < sizeof(struct unix_mreq))
+ return -EINVAL;
+ if (copy_from_user(&mreq, optval, sizeof(struct unix_mreq)))
+ return -EFAULT;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (optname) {
+ case UNIX_CREATE_GROUP:
+ err = unix_mc_create(sock, &mreq);
+ break;
+
+ case UNIX_JOIN_GROUP:
+ err = unix_mc_join(sock, &mreq);
+ break;
+
+ case UNIX_LEAVE_GROUP:
+ err = unix_mc_leave(sock, &mreq);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ return err;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 5/9] AF_UNIX: Deliver message to several recipients in case of multicast
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
unix_dgram_sendmsg() implements the delivery both for SOCK_DGRAM and
SOCK_SEQPACKET Unix sockets.
The delivery is done in an atomic way: either the message is delivered to all
recipients or none, even in case of interruptions or errors.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
net/unix/af_unix.c | 247 +++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 188 insertions(+), 59 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3cc9695..9207393 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1553,16 +1553,17 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
{
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct sock *sk = sock->sk;
- struct net *net = sock_net(sk);
struct unix_sock *u = unix_sk(sk);
struct sockaddr_un *sunaddr = msg->msg_name;
- struct sock *other = NULL;
+ struct sock_set *others_set = NULL;
int namelen = 0; /* fake GCC */
int err;
unsigned hash;
struct sk_buff *skb;
+ int i;
long timeo;
struct scm_cookie tmp_scm;
+ int multicast_delivery = !!u->mcast_subscriptions_cnt;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
@@ -1580,12 +1581,30 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (err < 0)
goto out;
namelen = err;
- } else {
+ } else if (!multicast_delivery) {
+ struct sock *other;
sunaddr = NULL;
err = -ENOTCONN;
other = unix_peer_get(sk);
if (!other)
goto out;
+ err = -ENOMEM;
+ others_set = kmalloc(sizeof(struct sock_set)
+ + sizeof(struct sock_item),
+ GFP_KERNEL);
+ if (!others_set)
+ goto out;
+ others_set->cnt = 1;
+ sock_hold(other);
+ others_set->items[0].s = other;
+ others_set->items[0].skb = NULL;
+ others_set->items[0].to_deliver = 1;
+ } else {
+ sunaddr = NULL;
+ err = -ENOTCONN;
+ others_set = unix_find_multicast_recipients(sk, NULL, &err);
+ if (!others_set)
+ goto out;
}
if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
@@ -1613,90 +1632,200 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
restart:
- if (!other) {
+ if (!others_set) {
+ struct sock *other;
+ struct unix_sock *otheru;
err = -ECONNRESET;
if (sunaddr == NULL)
goto out_free;
- other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
- hash, &err);
- if (other == NULL)
+ other = unix_find_other(sock_net(sk), sunaddr, namelen,
+ sk->sk_type, hash, &err);
+ if (!other)
goto out_free;
+ otheru = unix_sk(other);
+
+ if (otheru->is_mcast_addr) {
+ /* FIXME: we should send to the requested recipient
+ * specified in sendto(...dest_addr) instead of the
+ * recipient specified by setsockopt... */
+ sock_put(other);
+ others_set = unix_find_multicast_recipients(sk, other,
+ &err);
+ if (!others_set)
+ goto out_free;
+ } else {
+ others_set = kmalloc(sizeof(struct sock_set)
+ + sizeof(struct sock_item),
+ GFP_KERNEL);
+ if (!others_set)
+ goto out_free;
+ others_set->cnt = 1;
+ others_set->items[0].s = other;
+ others_set->items[0].skb = NULL;
+ others_set->items[0].to_deliver = 1;
+ }
}
- unix_state_lock(other);
- err = -EPERM;
- if (!unix_may_send(sk, other))
- goto out_unlock;
+ for (i = 0 ; i < others_set->cnt ; i++) {
+ struct sock *cur = others_set->items[i].s;
- if (sock_flag(other, SOCK_DEAD)) {
- /*
- * Check with 1003.1g - what should
- * datagram error
- */
- unix_state_unlock(other);
- sock_put(other);
+ others_set->items[i].skb = skb_clone(skb, GFP_KERNEL);
+ if (!others_set->items[i].skb) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+ skb_set_owner_w(others_set->items[i].skb, sk);
+ }
- err = 0;
- unix_state_lock(sk);
- if (unix_peer(sk) == other) {
- unix_peer(sk) = NULL;
- unix_state_unlock(sk);
+ for (i = 0 ; i < others_set->cnt ; i++) {
+ struct sock *cur = others_set->items[i].s;
- unix_dgram_disconnected(sk, other);
- sock_put(other);
- err = -ECONNREFUSED;
- } else {
- unix_state_unlock(sk);
+ if (!others_set->items[i].to_deliver)
+ continue;
+
+ unix_state_lock(cur);
+ err = -EPERM;
+ if (!multicast_delivery && !unix_may_send(sk, cur)) {
+ others_set->items[i].to_deliver = 0;
+ unix_state_unlock(cur);
+ kfree_skb(others_set->items[i].skb);
+ if (multicast_delivery)
+ continue;
+ else
+ goto out_free;
}
- other = NULL;
- if (err)
- goto out_free;
- goto restart;
+ if (sock_flag(cur, SOCK_DEAD)) {
+ /*
+ * Check with 1003.1g - what should
+ * datagram error
+ */
+ unix_state_unlock(cur);
+
+ err = 0;
+ unix_state_lock(sk);
+ if (unix_peer(sk) == cur) {
+ unix_peer(sk) = NULL;
+ unix_state_unlock(sk);
+
+ unix_dgram_disconnected(sk, cur);
+ sock_put(cur);
+ err = -ECONNREFUSED;
+ } else {
+ unix_state_unlock(sk);
+ }
+
+ kfree_skb(others_set->items[i].skb);
+ if (err)
+ goto out_free;
+
+ if (multicast_delivery) {
+ others_set->items[i].to_deliver = 0;
+ continue;
+ } else {
+ kfree_sock_set(others_set);
+ others_set = NULL;
+ goto restart;
+ }
+ }
+
+ err = -EPIPE;
+ if (cur->sk_shutdown & RCV_SHUTDOWN) {
+ unix_state_unlock(cur);
+ kfree_skb(others_set->items[i].skb);
+ if (multicast_delivery) {
+ others_set->items[i].to_deliver = 0;
+ continue;
+ } else {
+ goto out_free;
+ }
+ }
+
+ if (sk->sk_type != SOCK_SEQPACKET) {
+ err = security_unix_may_send(sk->sk_socket,
+ cur->sk_socket);
+ if (err) {
+ unix_state_unlock(cur);
+ kfree_skb(others_set->items[i].skb);
+ if (multicast_delivery) {
+ others_set->items[i].to_deliver = 0;
+ continue;
+ } else {
+ goto out_free;
+ }
+ }
+ }
+
+ if (unix_peer(cur) != sk && unix_recvq_full(cur)) {
+ kfree_skb(others_set->items[i].skb);
+
+ if (multicast_delivery) {
+ unix_state_unlock(cur);
+ others_set->items[i].to_deliver = 0;
+ continue;
+ } else {
+ if (!timeo) {
+ unix_state_unlock(cur);
+ err = -EAGAIN;
+ goto out_free;
+ }
+
+ timeo = unix_wait_for_peer(cur, timeo);
+
+ err = sock_intr_errno(timeo);
+ if (signal_pending(current))
+ goto out_free;
+
+ kfree_sock_set(others_set);
+ others_set = NULL;
+ goto restart;
+ }
+ }
}
- err = -EPIPE;
- if (other->sk_shutdown & RCV_SHUTDOWN)
- goto out_unlock;
+ for (i = 0 ; i < others_set->cnt ; i++) {
+ struct sock *cur = others_set->items[i].s;
- if (sk->sk_type != SOCK_SEQPACKET) {
- err = security_unix_may_send(sk->sk_socket, other->sk_socket);
- if (err)
- goto out_unlock;
+ if (!others_set->items[i].to_deliver)
+ continue;
+
+ if (sock_flag(cur, SOCK_RCVTSTAMP))
+ __net_timestamp(others_set->items[i].skb);
+
+ skb_queue_tail(&cur->sk_receive_queue,
+ others_set->items[i].skb);
}
- if (unix_peer(other) != sk && unix_recvq_full(other)) {
- if (!timeo) {
- err = -EAGAIN;
- goto out_unlock;
- }
+ for (i = 0 ; i < others_set->cnt ; i++) {
+ struct sock *cur = others_set->items[i].s;
- timeo = unix_wait_for_peer(other, timeo);
+ if (!others_set->items[i].to_deliver)
+ continue;
- err = sock_intr_errno(timeo);
- if (signal_pending(current))
- goto out_free;
+ unix_state_unlock(cur);
+ }
- goto restart;
+ for (i = 0 ; i < others_set->cnt ; i++) {
+ struct sock *cur = others_set->items[i].s;
+
+ if (!others_set->items[i].to_deliver)
+ continue;
+
+ cur->sk_data_ready(cur, len);
}
- if (sock_flag(other, SOCK_RCVTSTAMP))
- __net_timestamp(skb);
- skb_queue_tail(&other->sk_receive_queue, skb);
- unix_state_unlock(other);
- other->sk_data_ready(other, len);
- sock_put(other);
+ kfree_skb(skb);
scm_destroy(siocb->scm);
+ if (others_set)
+ kfree_sock_set(others_set);
return len;
-out_unlock:
- unix_state_unlock(other);
out_free:
kfree_skb(skb);
out:
- if (other)
- sock_put(other);
+ if (others_set)
+ kfree_sock_set(others_set);
scm_destroy(siocb->scm);
return err;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 6/9] AF_UNIX: Apply Linux Socket Filtering to Unix sockets
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
Linux Socket Filters can already be attached to Unix sockets with
setsockopt(sockfd, SOL_SOCKET, SO_{ATTACH,DETACH}_FILTER, ...) But the filter
was never used in Unix sockets so it did not work. This patch uses sk_filter()
to filter buffers before delivery.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
net/unix/af_unix.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 9207393..52e2aa2 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1669,6 +1669,7 @@ restart:
for (i = 0 ; i < others_set->cnt ; i++) {
struct sock *cur = others_set->items[i].s;
+ unsigned int pkt_len;
others_set->items[i].skb = skb_clone(skb, GFP_KERNEL);
if (!others_set->items[i].skb) {
@@ -1676,6 +1677,13 @@ restart:
goto out_free;
}
skb_set_owner_w(others_set->items[i].skb, sk);
+
+ pkt_len = sk_filter(cur, others_set->items[i].skb);
+ if (pkt_len != 0) {
+ others_set->items[i].to_deliver = 0;
+ kfree_skb(others_set->items[i].skb);
+ continue;
+ }
}
for (i = 0 ; i < others_set->cnt ; i++) {
--
1.7.1
^ permalink raw reply related
* [PATCH 7/9] AF_UNIX: Documentation on multicast Unix Sockets
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
.../networking/multicast-unix-sockets.txt | 76 ++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
create mode 100644 Documentation/networking/multicast-unix-sockets.txt
diff --git a/Documentation/networking/multicast-unix-sockets.txt b/Documentation/networking/multicast-unix-sockets.txt
new file mode 100644
index 0000000..b9882a1
--- /dev/null
+++ b/Documentation/networking/multicast-unix-sockets.txt
@@ -0,0 +1,76 @@
+Multicast Unix sockets
+======================
+
+Multicast group memberships are stored in struct unix_mcast nodes. An Unix
+socket can join several multicast groups. Struct unix_mcast nodes are doubly
+linked:
+- In (struct unix_sock)->mcast_subscriptions
+- In (struct unix_sock)->mcast_members
+
+Example
+=======
+
+ Addr1 Addr2
+ | |
+ v v
+Socket1 ----> mcast node ----> mcast node
+ |
+ v
+Socket2 ----> mcast node
+ |
+ v
+Socket3 ----> mcast node
+
+
+Addr1 and Addr2 are struct unix_sock with is_mcast_addr set to 1. They are
+bount to a multicast address with:
+ setsockopt(sockfd, SOL_UNIX, UNIX_CREATE_GROUP, ...).
+
+Socket1, Socket2 and Socket3 are also struct unix_sock. They are associated to
+a multicast address with:
+ setsockopt(sockfd, SOL_UNIX, UNIX_JOIN_GROUP, ...).
+
+Socket1 joined two multicast groups. Socket2 and Socket3 joined one multicast
+group. The multicast group Addr1 has 3 members. Addr2 has one member.
+
+Atomic delivery and ordering
+============================
+
+Each message sent is delivered atomically to either none of the recipients or
+all the recipients, even with interruptions and errors.
+
+The locking is done to keep the ordering consistent on all recipients. We want
+to avoid the following scenario. Two emitters A and B, and 2 recipients C and
+D:
+
+ C D
+A -------->| | Step 1: A's message is delivered to C
+B -------->| | Step 2: B's message is delivered to C
+B ---------|--->| Step 3: B's message is delivered to D
+A ---------|--->| Step 4: A's message is delivered to D
+
+Although A and B had a list of recipients (C, D) in the same order, C and D
+received the messages in a different order.
+
+
+SOCK_SEQPACKET semantics
+========================
+
+When a connection is performed on a SOCK_SEQPACKET multicast socket, a new
+socket is created and its file descriptor is received with accept(). The new
+socket could join the multicast group from userspace with setsockopt() but
+there would be race: it could lose the first messages sent by an application
+after connect() returns but before setsockopt() is executed.
+
+To avoid that race, the application should use the flag UNIX_MREQ_AUTOJOIN when
+creating the multicast group.
+
+When several connections are established to a SOCK_SEQPACKET multicast socket,
+the creator of the multicast group using UNIX_MREQ_AUTOJOIN would receive the
+messages several times: one time on each accepted socket. To avoid that, the
+creator of the group may prefer to use UNIX_MREQ_SEND_TO_PEER. Then, the
+accepted socket will not be part of the group but will still receive messages
+from its peer.
+
+
+
--
1.7.1
^ permalink raw reply related
* [PATCH 8/9] AF_UNIX: add options on multicast connected socket
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
autojoin and send-to-peer
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
include/net/af_unix.h | 27 +++++++++++++++++++++------
net/unix/af_unix.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index bf114d5..c82b5f8 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -40,18 +40,31 @@ struct unix_skb_parms {
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
-#define UNIX_MREQ_LOOPBACK 0x01
+/* UNIX socket options */
+#define UNIX_CREATE_GROUP 1
+#define UNIX_JOIN_GROUP 2
+#define UNIX_LEAVE_GROUP 3
+
+/* Flags on unix_mreq */
+
+/* On UNIX_JOIN_GROUP: the socket will receive its own messages
+ * On UNIX_CREATE_GROUP: the accepted sockets will receive their own messages
+ */
+#define UNIX_MREQ_LOOPBACK 0x01
+
+/* On UNIX_CREATE_GROUP: the accepted socket will be member of the multicast
+ * group */
+#define UNIX_MREQ_AUTOJOIN 0x02
+
+/* ON UNIX_JOIN_GROUP: the messages will also be received by the peer */
+#define UNIX_MREQ_SEND_TO_PEER 0x04
+
struct unix_mreq
{
struct sockaddr_un address;
unsigned int flags;
};
-/* UNIX socket options */
-#define UNIX_CREATE_GROUP 1
-#define UNIX_JOIN_GROUP 2
-#define UNIX_LEAVE_GROUP 3
-
#ifdef __KERNEL__
/* The AF_UNIX socket */
struct unix_sock {
@@ -69,6 +82,8 @@ struct unix_sock {
unsigned int gc_candidate : 1;
unsigned int gc_maybe_cycle : 1;
unsigned int is_mcast_addr : 1;
+ unsigned int mcast_auto_join : 1;
+ unsigned int mcast_send_to_peer : 1;
/* These multicast fields are protected by the global spinlock
* unix_multicast_lock */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 52e2aa2..d3d6270 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -878,6 +878,17 @@ static int unix_find_multicast_members(struct sock_set *set,
set->items[set->cnt].to_deliver = 1;
set->cnt++;
}
+
+ if (unix_peer(sender) && unix_sk(sender)->mcast_send_to_peer) {
+ if (set->cnt + 1 > recipient_cnt)
+ return -ENOMEM;
+ sock_hold(unix_peer(sender));
+ set->items[set->cnt].s = unix_peer(sender);
+ set->items[set->cnt].skb = NULL;
+ set->items[set->cnt].to_deliver = 1;
+ set->cnt++;
+ }
+
return 0;
}
@@ -1226,6 +1237,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int st;
int err;
long timeo;
+ struct unix_mcast *node = NULL;
err = unix_mkname(sunaddr, addr_len, &hash);
if (err < 0)
@@ -1245,6 +1257,12 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
err = -ENOMEM;
+ node = kmalloc(sizeof(struct unix_mcast), GFP_KERNEL);
+ if (!node) {
+ err = -ENOMEM;
+ goto out;
+ }
+
/* create new sock for complete connection */
newsk = unix_create1(sock_net(sk), NULL);
if (newsk == NULL)
@@ -1261,6 +1279,8 @@ restart:
if (!other)
goto out;
+ otheru = unix_sk(other);
+
/* Latch state of peer */
unix_state_lock(other);
@@ -1332,6 +1352,21 @@ restart:
goto out_unlock;
}
+ /* Multicast sockets */
+ spin_lock(&unix_multicast_lock);
+ if (otheru->is_mcast_addr && otheru->mcast_auto_join) {
+ node->member = unix_sk(newsk);
+ node->addr = otheru;
+ node->flags = 0;
+
+ hlist_add_head(&node->member_node, &otheru->mcast_members);
+ hlist_add_head(&node->subscription_node,
+ &unix_sk(newsk)->mcast_subscriptions);
+ otheru->mcast_members_cnt++;
+ u->mcast_subscriptions_cnt++;
+ }
+ spin_unlock(&unix_multicast_lock);
+
/* The way is open! Fastly set all the necessary fields... */
sock_hold(sk);
@@ -1341,7 +1376,6 @@ restart:
init_peercred(newsk);
newu = unix_sk(newsk);
newsk->sk_wq = &newu->peer_wq;
- otheru = unix_sk(other);
/* copy address information from listening to new sock*/
if (otheru->addr) {
@@ -1380,6 +1414,8 @@ out_unlock:
out:
kfree_skb(skb);
+ if (node)
+ kfree(node);
if (newsk)
unix_release_sock(newsk, 0);
if (other)
@@ -1868,6 +1904,8 @@ static int unix_mc_create(struct socket *sock, struct unix_mreq *mreq)
unix_state_lock(sock->sk);
unix_sk(sock->sk)->is_mcast_addr = 1;
+ if (mreq->flags & UNIX_MREQ_AUTOJOIN)
+ unix_sk(sock->sk)->mcast_auto_join = 1;
unix_state_unlock(sock->sk);
return 0;
@@ -1918,6 +1956,10 @@ static int unix_mc_join(struct socket *sock, struct unix_mreq *mreq)
node->addr = otheru;
node->flags = mreq->flags;
+ unix_state_lock(sock->sk);
+ unix_sk(sock->sk)->mcast_send_to_peer = !!(mreq->flags & UNIX_MREQ_SEND_TO_PEER);
+ unix_state_unlock(sock->sk);
+
spin_lock(&unix_multicast_lock);
hlist_add_head(&node->member_node, &otheru->mcast_members);
hlist_add_head(&node->subscription_node, &u->mcast_subscriptions);
--
1.7.1
^ permalink raw reply related
* [PATCH 0/9] RFC v2: Multicast and filtering features on AF_UNIX
From: Alban Crequy @ 2010-11-22 18:34 UTC (permalink / raw)
To: Alban Crequy, David S. Miller, Eric Dumazet, Stephen Hemminger,
Cyrill
Hi,
This is a new serie of patches, following my first request for comments
here: http://marc.info/?l=linux-netdev&m=128534977610124
It implements a new multicast features on AF_UNIX datagram and
seqpacket sockets.
My motivation is to use it for D-Bus. The kernel code here does not
contain anything specific to D-Bus, so it could be used for other IPC
mechanisms too.
The patches apply on linux-next-20101122 and can be pulled from:
git://git.collabora.co.uk/git/user/alban/linux-2.6.35.y/.git unix-multicast5
Comments & questions welcome! I would appreciate a review on the design
and know if it goes in the right direction.
Regards,
Alban Crequy
^ permalink raw reply
* [PATCH 4/9] AF_UNIX: find the recipients for multicast messages
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
unix_find_multicast_recipients() builds an array of recipients. It can either
find the peers of a specific multicast address, or find all the peers of all
multicast group the sender is part of.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
net/unix/af_unix.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 144 insertions(+), 0 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2278829..3cc9695 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -114,15 +114,48 @@
#include <linux/mount.h>
#include <net/checksum.h>
#include <linux/security.h>
+#include <linux/sort.h>
static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
static DEFINE_SPINLOCK(unix_table_lock);
+static DEFINE_SPINLOCK(unix_multicast_lock);
static atomic_long_t unix_nr_socks;
#define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE])
#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
+struct sock_item {
+ struct sock *s;
+ struct sk_buff *skb;
+ int to_deliver;
+};
+
+struct sock_set {
+ int cnt;
+ struct sock_item items[0];
+};
+
+static void kfree_sock_set(struct sock_set *set)
+{
+ int i;
+ for (i = 0 ; i < set->cnt ; i++)
+ sock_put(set->items[i].s);
+ kfree(set);
+}
+
+static int sock_item_compare(const void *_a, const void *_b)
+{
+ const struct sock_item *a = _a;
+ const struct sock_item *b = _b;
+ if (a->s > b->s)
+ return 1;
+ else if (a->s < b->s)
+ return -1;
+ else
+ return 0;
+}
+
#ifdef CONFIG_SECURITY_NETWORK
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{
@@ -824,6 +857,117 @@ fail:
return NULL;
}
+static int unix_find_multicast_members(struct sock_set *set,
+ int recipient_cnt,
+ struct sock *sender,
+ struct hlist_head *list)
+{
+ struct unix_mcast *node;
+ struct hlist_node *pos;
+ hlist_for_each_entry(node, pos, list,
+ member_node) {
+ if (set->cnt + 1 > recipient_cnt)
+ return -ENOMEM;
+ if (node->member == unix_sk(sender) &&
+ !(node->flags & UNIX_MREQ_LOOPBACK))
+ continue;
+
+ sock_hold(&node->member->sk);
+ set->items[set->cnt].s = &node->member->sk;
+ set->items[set->cnt].skb = NULL;
+ set->items[set->cnt].to_deliver = 1;
+ set->cnt++;
+ }
+ return 0;
+}
+
+/* Find the recipients for a message sent by 'sender' to 'addr'. If 'dest' is
+ * NULL, the recipients are peers of all subscribed groups.
+ */
+static struct sock_set *unix_find_multicast_recipients(struct sock *sender,
+ struct sock *dest,
+ int *err)
+{
+ struct unix_sock *u = unix_sk(sender);
+ struct unix_mcast *node;
+ struct hlist_node *pos;
+ struct sock_set *set;
+ int recipient_cnt;
+
+ /* We cannot allocate in the spin lock. First, count the recipients */
+try_again:
+ spin_lock(&unix_multicast_lock);
+ if (dest != NULL) {
+ if (unix_sk(dest)->is_mcast_addr) {
+ recipient_cnt = unix_sk(dest)->mcast_members_cnt;
+ } else {
+ recipient_cnt = 1;
+ }
+ } else {
+ recipient_cnt = 0;
+ hlist_for_each_entry(node, pos, &u->mcast_subscriptions,
+ subscription_node) {
+ recipient_cnt += node->addr->mcast_members_cnt;
+ }
+ }
+ spin_unlock(&unix_multicast_lock);
+
+ /* Allocate for the set and hope the number of recipients does not
+ * change while the lock is released. If it changes, we have to try
+ * again... We allocate a bit more than needed, so if a _few_ members
+ * are added in a multicast group meanwhile, we don't always need to
+ * try again. */
+ recipient_cnt += 5;
+
+ set = kmalloc(sizeof(struct sock_set)
+ + sizeof(struct sock_item) * recipient_cnt,
+ GFP_KERNEL);
+ if (!set) {
+ *err = -ENOMEM;
+ return NULL;
+ }
+ set->cnt = 0;
+
+ spin_lock(&unix_multicast_lock);
+ if (dest && unix_sk(dest)->is_mcast_addr) {
+ /* Message sent to a multicast address */
+ if (unix_find_multicast_members(set, recipient_cnt,
+ sender,
+ &unix_sk(dest)->mcast_members)) {
+ spin_unlock(&unix_multicast_lock);
+ kfree_sock_set(set);
+ goto try_again;
+ }
+ } else if (!dest) {
+ /* Destination not specified, sending to all peers of
+ * subscribed groups */
+ hlist_for_each_entry(node, pos, &u->mcast_subscriptions,
+ subscription_node) {
+ if (unix_find_multicast_members(set, recipient_cnt,
+ sender,
+ &node->addr->mcast_members)) {
+ spin_unlock(&unix_multicast_lock);
+ kfree_sock_set(set);
+ goto try_again;
+ }
+ }
+ } else {
+ /* Message sent to a non-multicast address */
+ BUG_ON(recipient_cnt < 1);
+ set->cnt = 1;
+ sock_hold(dest);
+ set->items[0].s = dest;
+ set->items[0].skb = NULL;
+ set->items[0].to_deliver = 1;
+ }
+ spin_unlock(&unix_multicast_lock);
+
+ /* Keep the array ordered to prevent deadlocks on circular waits */
+ sort(set->items, set->cnt, sizeof(struct sock_item),
+ sock_item_compare, NULL);
+ return set;
+}
+
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
--
1.7.1
^ permalink raw reply related
* [PATCH 9/9] AF_UNIX: implement poll(POLLOUT) for multicast sockets
From: Alban Crequy @ 2010-11-22 18:36 UTC (permalink / raw)
To: Alban Crequy
Cc: David S. Miller, Eric Dumazet, Stephen Hemminger, Cyrill Gorcunov,
Alexey Dobriyan, Lennart Poettering, Kay Sievers, Ian Molton,
netdev, linux-kernel, Alban Crequy
In-Reply-To: <20101122183447.124afce5@chocolatine.cbg.collabora.co.uk>
When a socket subscribed to a multicast group has its incoming queue full, it
can either block the emission to the multicast group or let the messages be
dropped. The latter is useful to monitor all messages without slowing down the
traffic.
It is specified with the flag UNIX_MREQ_DROP_WHEN_FULL when the multicast group
is joined.
poll(POLLOUT) is implemented by checking all receiving queues of subscribed
sockets. If only one of them has its receiving queue full and does not have
UNIX_MREQ_DROP_WHEN_FULL, the multicast socket is not writeable.
Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
---
include/net/af_unix.h | 5 +++++
net/unix/af_unix.c | 38 ++++++++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index c82b5f8..d18499a 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -59,6 +59,10 @@ struct unix_skb_parms {
/* ON UNIX_JOIN_GROUP: the messages will also be received by the peer */
#define UNIX_MREQ_SEND_TO_PEER 0x04
+/* ON UNIX_JOIN_GROUP: just drop the message instead of blocking if the
+ * receiving queue is full */
+#define UNIX_MREQ_DROP_WHEN_FULL 0x08
+
struct unix_mreq
{
struct sockaddr_un address;
@@ -84,6 +88,7 @@ struct unix_sock {
unsigned int is_mcast_addr : 1;
unsigned int mcast_auto_join : 1;
unsigned int mcast_send_to_peer : 1;
+ unsigned int mcast_drop_when_peer_full : 1;
/* These multicast fields are protected by the global spinlock
* unix_multicast_lock */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d3d6270..36ee1fe 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -128,7 +128,8 @@ static atomic_long_t unix_nr_socks;
struct sock_item {
struct sock *s;
struct sk_buff *skb;
- int to_deliver;
+ unsigned int to_deliver : 1;
+ unsigned int drop_when_full : 1;
};
struct sock_set {
@@ -876,6 +877,8 @@ static int unix_find_multicast_members(struct sock_set *set,
set->items[set->cnt].s = &node->member->sk;
set->items[set->cnt].skb = NULL;
set->items[set->cnt].to_deliver = 1;
+ set->items[set->cnt].drop_when_full =
+ !!(node->flags & UNIX_MREQ_DROP_WHEN_FULL);
set->cnt++;
}
@@ -886,6 +889,8 @@ static int unix_find_multicast_members(struct sock_set *set,
set->items[set->cnt].s = unix_peer(sender);
set->items[set->cnt].skb = NULL;
set->items[set->cnt].to_deliver = 1;
+ set->items[set->cnt].drop_when_full =
+ unix_sk(sender)->mcast_drop_when_peer_full;
set->cnt++;
}
@@ -970,6 +975,7 @@ try_again:
set->items[0].s = dest;
set->items[0].skb = NULL;
set->items[0].to_deliver = 1;
+ set->items[0].drop_when_full = 0;
}
spin_unlock(&unix_multicast_lock);
@@ -1805,6 +1811,7 @@ restart:
kfree_skb(others_set->items[i].skb);
if (multicast_delivery) {
+ /* FIXME: check drop_when_full */
unix_state_unlock(cur);
others_set->items[i].to_deliver = 0;
continue;
@@ -1957,7 +1964,10 @@ static int unix_mc_join(struct socket *sock, struct unix_mreq *mreq)
node->flags = mreq->flags;
unix_state_lock(sock->sk);
- unix_sk(sock->sk)->mcast_send_to_peer = !!(mreq->flags & UNIX_MREQ_SEND_TO_PEER);
+ unix_sk(sock->sk)->mcast_send_to_peer =
+ !!(mreq->flags & UNIX_MREQ_SEND_TO_PEER);
+ unix_sk(sock->sk)->mcast_drop_when_peer_full =
+ !!(mreq->flags & UNIX_MREQ_DROP_WHEN_FULL);
unix_state_unlock(sock->sk);
spin_lock(&unix_multicast_lock);
@@ -2258,6 +2268,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
goto out_unlock;
}
+ /* FIXME: wake up peers on the multicast group too */
wake_up_interruptible_sync_poll(&u->peer_wait,
POLLOUT | POLLWRNORM | POLLWRBAND);
@@ -2613,6 +2624,9 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
{
struct sock *sk = sock->sk, *other;
unsigned int mask, writable;
+ struct sock_set *others;
+ int err = 0;
+ int i;
sock_poll_wait(file, sk_sleep(sk), wait);
mask = 0;
@@ -2652,6 +2666,26 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
}
sock_put(other);
}
+ /*
+ * 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.
+ */
+ others = unix_find_multicast_recipients(sk, NULL, &err);
+ if (!others)
+ goto skip_multicast;
+ for (i = 0 ; i < others->cnt ; i++) {
+ if (others->items[i].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;
+ }
+ }
+ kfree_sock_set(others);
+
+skip_multicast:
if (writable)
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 3/9] AF_UNIX: create, join and leave multicast groups with setsockopt
From: David Miller @ 2010-11-22 19:00 UTC (permalink / raw)
To: alban.crequy
Cc: eric.dumazet, shemminger, gorcunov, adobriyan, lennart,
kay.sievers, ian.molton, netdev, linux-kernel
In-Reply-To: <1290450982-17480-3-git-send-email-alban.crequy@collabora.co.uk>
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Mon, 22 Nov 2010 18:36:16 +0000
> + other = unix_find_other(sock_net(sock->sk), &mreq->address, namelen,
> + sock->type, hash, &err);
> + if (other)
> + return -EADDRINUSE;
Leaks 'other'.
^ permalink raw reply
* Re: [PATCH 4/9] AF_UNIX: find the recipients for multicast messages
From: David Miller @ 2010-11-22 19:05 UTC (permalink / raw)
To: alban.crequy
Cc: eric.dumazet, shemminger, gorcunov, adobriyan, lennart,
kay.sievers, ian.molton, netdev, linux-kernel
In-Reply-To: <1290450982-17480-4-git-send-email-alban.crequy@collabora.co.uk>
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Mon, 22 Nov 2010 18:36:17 +0000
> unix_find_multicast_recipients() builds an array of recipients. It can either
> find the peers of a specific multicast address, or find all the peers of all
> multicast group the sender is part of.
>
> Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
You really should use RCU to lock this stuff, this way sends run
lockless and have less worries wrt. the memory allocation. You'll
also only take a spinlock in the write paths which change the
multicast groups, which ought to be rare.
Although to be honest you should optimize the case of small numbers of
recipients, in the same way we optimize small numbers of iovecs on
sends. Have an on-stack array that holds a small number of entries
and use that if the set fits, otherwise dynamic allocation.
^ permalink raw reply
* Re: [PATCH 7/9] AF_UNIX: Documentation on multicast Unix Sockets
From: Rémi Denis-Courmont @ 2010-11-22 19:07 UTC (permalink / raw)
To: Alban Crequy, netdev; +Cc: linux-kernel
In-Reply-To: <1290450982-17480-7-git-send-email-alban.crequy@collabora.co.uk>
Le lundi 22 novembre 2010 20:36:20 Alban Crequy, vous avez écrit :
> +Multicast Unix sockets
> +======================
> +
> +Multicast group memberships are stored in struct unix_mcast nodes. An Unix
> +socket can join several multicast groups. Struct unix_mcast nodes are
> doubly +linked:
> +- In (struct unix_sock)->mcast_subscriptions
> +- In (struct unix_sock)->mcast_members
I may be stupid, but I found this whole documentation very confusing, and so
the API it tries to describe. Traditionally:
- Senders may or not may be part of the group and are not kept track of.
- Receivers join to the group then receive message sent to it.
- Loopback defines whether a sender receives its own echo if it sends to a
group that it has joined.
- If connected to a multicast group, messages from the socket are routed to
the group (in absence of a contradictoy socket address). This has no effect on
membership to the multicast group under any circumstance.
You cannot 'listen' or 'accept' on a multicast group.
So I am not entirely clear what semantics your patchset is following. But it
does not seem like "multicast" to me and therefore seems not very well
documented :-(
--
Rémi Denis-Courmont
http://www.remlab.net/
http://fi.linkedin.com/in/remidenis
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2010-11-22 20:10 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
1) Fix screaming IRQ in e1000, from Anupam Chanda.
2) Fix module parameter bustage in qlge, from Sonny Rao.
3) Interface address leak in ipv6, fix from John Fastabend.
This would have been merged sooner except that I erroneously
put this into my net-next-2.6 tree, oops.
4) Support for more Marvell PHY variants, from David Daney.
5) Chip variant checking fix in atl1c from Ben Hutchings.
6) Baud rate correction fix in SH-irda driver, from Nicolas Kaiser.
Please pull, thanks a lot!
The following changes since commit b86db4744230c94e480de56f1b7f31117edbf193:
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 (2010-11-19 19:46:45 -0800)
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master
Anupam Chanda (1):
e1000: fix screaming IRQ
Ben Hutchings (1):
atl1c: Fix hardware type check for enabling OTP CLK
David Daney (3):
phylib: Use common page register definition for Marvell PHYs.
phylib: Add support for Marvell 88E1149R devices.
of/phylib: Use device tree properties to initialize Marvell PHYs.
Eric Dumazet (1):
net: allow GFP_HIGHMEM in __vmalloc()
John Fastabend (1):
ipv6: fix missing in6_ifa_put in addrconf
Nicolas Kaiser (1):
SuperH IrDA: correct Baud rate error correction
Simon Horman (1):
bonding: change list contact to netdev@vger.kernel.org
Sonny Rao (1):
qlge: Fix incorrect usage of module parameters and netdev msg level
MAINTAINERS | 2 +-
drivers/net/atl1c/atl1c_hw.c | 2 +-
drivers/net/e1000/e1000_main.c | 12 ++-
drivers/net/irda/sh_sir.c | 2 +-
drivers/net/phy/marvell.c | 164 ++++++++++++++++++++++++++++++++++++---
drivers/net/qlge/qlge_main.c | 6 +-
include/linux/marvell_phy.h | 1 +
net/ceph/buffer.c | 2 +-
net/core/request_sock.c | 4 +-
net/ipv4/fib_trie.c | 2 +-
net/ipv6/addrconf.c | 6 +-
net/xfrm/xfrm_hash.c | 2 +-
12 files changed, 173 insertions(+), 32 deletions(-)
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox