]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/core/net-sysfs.c
net: zero kobject in rx_queue_release
[net-next-2.6.git] / net / core / net-sysfs.c
index b143173e3eb2bd9259e1c0122800848146b4c136..7abeb7ceaa4c8d73bfa326090323cee654491fab 100644 (file)
@@ -598,7 +598,8 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue,
        }
 
        spin_lock(&rps_map_lock);
-       old_map = queue->rps_map;
+       old_map = rcu_dereference_protected(queue->rps_map,
+                                           lockdep_is_held(&rps_map_lock));
        rcu_assign_pointer(queue->rps_map, map);
        spin_unlock(&rps_map_lock);
 
@@ -677,7 +678,8 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
                table = NULL;
 
        spin_lock(&rps_dev_flow_lock);
-       old_table = queue->rps_flow_table;
+       old_table = rcu_dereference_protected(queue->rps_flow_table,
+                                             lockdep_is_held(&rps_dev_flow_lock));
        rcu_assign_pointer(queue->rps_flow_table, table);
        spin_unlock(&rps_dev_flow_lock);
 
@@ -704,17 +706,24 @@ static struct attribute *rx_queue_default_attrs[] = {
 static void rx_queue_release(struct kobject *kobj)
 {
        struct netdev_rx_queue *queue = to_rx_queue(kobj);
-       struct netdev_rx_queue *first = queue->first;
+       struct rps_map *map;
+       struct rps_dev_flow_table *flow_table;
 
-       if (queue->rps_map)
-               call_rcu(&queue->rps_map->rcu, rps_map_release);
 
-       if (queue->rps_flow_table)
-               call_rcu(&queue->rps_flow_table->rcu,
-                   rps_dev_flow_table_release);
+       map = rcu_dereference_raw(queue->rps_map);
+       if (map) {
+               RCU_INIT_POINTER(queue->rps_map, NULL);
+               call_rcu(&map->rcu, rps_map_release);
+       }
+
+       flow_table = rcu_dereference_raw(queue->rps_flow_table);
+       if (flow_table) {
+               RCU_INIT_POINTER(queue->rps_flow_table, NULL);
+               call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
+       }
 
-       if (atomic_dec_and_test(&first->count))
-               kfree(first);
+       memset(kobj, 0, sizeof(*kobj));
+       dev_put(queue->dev);
 }
 
 static struct kobj_type rx_queue_ktype = {
@@ -726,7 +735,6 @@ static struct kobj_type rx_queue_ktype = {
 static int rx_queue_add_kobject(struct net_device *net, int index)
 {
        struct netdev_rx_queue *queue = net->_rx + index;
-       struct netdev_rx_queue *first = queue->first;
        struct kobject *kobj = &queue->kobj;
        int error = 0;
 
@@ -739,7 +747,7 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
        }
 
        kobject_uevent(kobj, KOBJ_ADD);
-       atomic_inc(&first->count);
+       dev_hold(queue->dev);
 
        return error;
 }