[ofa-general] Re: [openib-general] [RFC] [PATCH v2] IB/ipoib: Add bonding support to IPoIB
Moni Shoua
monisonlists at gmail.com
Mon Mar 5 06:35:50 PST 2007
Michael S. Tsirkin wrote:
> Some more issues:
>
>> This version of the patch tracks the allocs and releases of ipoib_neigh and
>> keeps a list of them. Before IPoIB net device unregisters the list is passed
>> to destroy ipoib_neighs that ride on on a bond neighbour.
>>
>> This is a replacement to the method of scanning the arp and ndisc
>> tables.
>>
>>
>> Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib.h
>> ===================================================================
>> --- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib.h 2007-03-04 12:20:54.749932751 +0200
>> +++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib.h 2007-03-04 12:21:58.547593677 +0200
>> @@ -218,6 +218,7 @@ struct ipoib_neigh {
>> struct neighbour *neighbour;
>> struct net_device *dev;
>>
>> + struct list_head all_neigh_list;
>> struct list_head list;
>> };
>>
>> Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_main.c
>> ===================================================================
>> --- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c 2007-03-04 12:21:52.720629356 +0200
>> +++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_main.c 2007-03-04 12:21:58.548593499 +0200
>> @@ -66,6 +66,7 @@ MODULE_PARM_DESC(recv_queue_size, "Numbe
>> #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
>> int ipoib_debug_level;
>>
>> +static int ipoib_at_exit = 0;
>> module_param_named(debug_level, ipoib_debug_level, int, 0644);
>> MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
>> #endif
>
> This at_exit trick looks ugly. Ideally, hotplug removing all devices and module
> removal should act identically. The fact that they do not is suspicious.
> Consider hotplug removing all devices. It seems no code will test
> ipoib_at_exit then. Is that right?
>
>
I still see a difference between removing all devices and unloading a module.
In the first case, the function ipoib_neigh_destructor is still accessible but not in the second.
I can't always set the neighbour destructor to NULL
because it is shared among other neighbours. I can do it only when I don't want the
destructor to be called ever (which is the case of module unloading)
>> @@ -85,6 +86,9 @@ struct workqueue_struct *ipoib_workqueue
>>
>> struct ib_sa_client ipoib_sa_client;
>>
>> +static DEFINE_SPINLOCK(ipoib_all_neigh_list_lock);
>> +static LIST_HEAD(ipoib_all_neigh_list);
>> +
>> static void ipoib_add_one(struct ib_device *device);
>> static void ipoib_remove_one(struct ib_device *device);
>>
>> @@ -792,6 +796,24 @@ static void ipoib_neigh_destructor(struc
>> ipoib_put_ah(ah);
>> }
>>
>> +static void ipoib_neigh_cleanup_bond(struct net_device* master,
>> + struct net_device* slave)
>> +{
>> + struct ipoib_neigh *nn, *tn;
>> +
>> + spin_lock(&ipoib_all_neigh_list_lock);
>> + list_for_each_entry_safe(nn, tn, &ipoib_all_neigh_list, all_neigh_list){
>> + if ((nn->neighbour->dev == master) && (nn->dev == slave)) {
>
> Extra ()'s not really needed here: logic ops have lower precedence than math
> (IIRC, only comma and assignments have lower precedence than logic).
>
>> + if (ipoib_at_exit)
>> + nn->neighbour->parms->neigh_destructor = NULL;
>
> Is it safe to do this without locking?
> Could the destructor be in progress when we do this?
I think you're right. Maybe I need to attack the issue in a different way.
I need to do some rethinking.
>
>> + spin_unlock(&ipoib_all_neigh_list_lock);
>> + ipoib_neigh_destructor(nn->neighbour);
>> + spin_lock(&ipoib_all_neigh_list_lock);
>> + }
>> + }
>> + spin_unlock(&ipoib_all_neigh_list_lock);
>> +}
>> +
>> struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
>> struct net_device *dev)
>> {
>> @@ -806,6 +828,9 @@ struct ipoib_neigh *ipoib_neigh_alloc(st
>> *to_ipoib_neigh(neighbour) = neigh;
>> skb_queue_head_init(&neigh->queue);
>>
>> + spin_lock(&ipoib_all_neigh_list_lock);
>> + list_add_tail(&neigh->all_neigh_list, &ipoib_all_neigh_list);
>> + spin_unlock(&ipoib_all_neigh_list_lock);
>> return neigh;
>> }
>>
>> @@ -818,6 +843,9 @@ void ipoib_neigh_free(struct net_device
>> ++priv->stats.tx_dropped;
>> dev_kfree_skb_any(skb);
>> }
>> + spin_lock(&ipoib_all_neigh_list_lock);
>> + list_del(&neigh->all_neigh_list);
>> + spin_unlock(&ipoib_all_neigh_list_lock);
>> kfree(neigh);
>> }
>>
>> @@ -874,6 +902,8 @@ void ipoib_dev_cleanup(struct net_device
>>
>> /* Delete any child interfaces first */
>> list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
>> + if (cpriv->dev->master)
>> + ipoib_neigh_cleanup_bond(cpriv->dev->master,priv->dev);
>
> whitespace broken here.
>
>> unregister_netdev(cpriv->dev);
>> ipoib_dev_cleanup(cpriv->dev);
>> free_netdev(cpriv->dev);
>> @@ -1158,6 +1188,8 @@ static void ipoib_remove_one(struct ib_d
>> list_for_each_entry_safe(priv, tmp, dev_list, list) {
>> ib_unregister_event_handler(&priv->event_handler);
>> flush_scheduled_work();
>> + if (priv->dev->master)
>> + ipoib_neigh_cleanup_bond(priv->dev->master,priv->dev);
>
> and here.
>
>>
>> unregister_netdev(priv->dev);
>> ipoib_dev_cleanup(priv->dev);
>> @@ -1217,6 +1249,7 @@ err_fs:
>>
>> static void __exit ipoib_cleanup_module(void)
>> {
>> + ipoib_at_exit = 1;
>> ib_unregister_client(&ipoib_client);
>> ib_sa_unregister_client(&ipoib_sa_client);
>> ipoib_unregister_debugfs();
More information about the general
mailing list