Merge to Fedora kernel-2.6.7-1.492
[linux-2.6.git] / net / sched / sch_api.c
index 432531d..575ca50 100644 (file)
@@ -433,7 +433,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
        sch->dequeue = ops->dequeue;
        sch->dev = dev;
        atomic_set(&sch->refcnt, 1);
-       sch->stats.lock = &dev->queue_lock;
+       sch->stats_lock = &dev->queue_lock;
        if (handle == 0) {
                handle = qdisc_alloc_handle(dev);
                err = -ENOMEM;
@@ -450,6 +450,9 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
        if (!try_module_get(ops->owner))
                goto err_out;
 
+       /* enqueue is accessed locklessly - make sure it's visible
+        * before we set a netdevice's qdisc pointer to sch */
+       smp_wmb();
        if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
                write_lock(&qdisc_tree_lock);
                sch->next = dev->qdisc_list;
@@ -457,7 +460,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
                write_unlock(&qdisc_tree_lock);
 #ifdef CONFIG_NET_ESTIMATOR
                if (tca[TCA_RATE-1])
-                       qdisc_new_estimator(&sch->stats, tca[TCA_RATE-1]);
+                       qdisc_new_estimator(&sch->stats, sch->stats_lock,
+                                           tca[TCA_RATE-1]);
 #endif
                return sch;
        }
@@ -484,7 +488,8 @@ static int qdisc_change(struct Qdisc *sch, struct rtattr **tca)
 #ifdef CONFIG_NET_ESTIMATOR
        if (tca[TCA_RATE-1]) {
                qdisc_kill_estimator(&sch->stats);
-               qdisc_new_estimator(&sch->stats, tca[TCA_RATE-1]);
+               qdisc_new_estimator(&sch->stats, sch->stats_lock,
+                                   tca[TCA_RATE-1]);
        }
 #endif
        return 0;
@@ -723,15 +728,15 @@ graft:
        return 0;
 }
 
-int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st)
+int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock)
 {
-       spin_lock_bh(st->lock);
-       RTA_PUT(skb, TCA_STATS, (char*)&st->lock - (char*)st, st);
-       spin_unlock_bh(st->lock);
+       spin_lock_bh(lock);
+       RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), st);
+       spin_unlock_bh(lock);
        return 0;
 
 rtattr_failure:
-       spin_unlock_bh(st->lock);
+       spin_unlock_bh(lock);
        return -1;
 }
 
@@ -755,7 +760,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
        if (q->ops->dump && q->ops->dump(q, skb) < 0)
                goto rtattr_failure;
        q->stats.qlen = q->q.qlen;
-       if (qdisc_copy_stats(skb, &q->stats))
+       if (qdisc_copy_stats(skb, &q->stats, q->stats_lock))
                goto rtattr_failure;
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
@@ -1095,6 +1100,7 @@ int psched_tod_diff(int delta_sec, int bound)
                delta = bound;
        return delta;
 }
+EXPORT_SYMBOL(psched_tod_diff);
 #endif
 
 psched_time_t psched_time_base;
@@ -1102,10 +1108,14 @@ psched_time_t psched_time_base;
 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
 psched_tdiff_t psched_clock_per_hz;
 int psched_clock_scale;
+EXPORT_SYMBOL(psched_clock_per_hz);
+EXPORT_SYMBOL(psched_clock_scale);
 #endif
 
 #ifdef PSCHED_WATCHER
 PSCHED_WATCHER psched_time_mark;
+EXPORT_SYMBOL(psched_time_mark);
+EXPORT_SYMBOL(psched_time_base);
 
 static void psched_tick(unsigned long);
 
@@ -1211,4 +1221,3 @@ EXPORT_SYMBOL(qdisc_get_rtab);
 EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(register_qdisc);
 EXPORT_SYMBOL(unregister_qdisc);
-PSCHED_EXPORTLIST;