]> err.no Git - linux-2.6/blobdiff - net/ipv4/route.c
[IPV4]: Convert rt_check_expire() from softirq processing to workqueue.
[linux-2.6] / net / ipv4 / route.c
index df42b7fb3268bb119c64f4a94b7c24d68722ec10..006d6058a8063a7dcf31accaced70cbf8f1e2eac 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/workqueue.h>
 #include <linux/skbuff.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
@@ -91,6 +92,7 @@
 #include <linux/jhash.h>
 #include <linux/rcupdate.h>
 #include <linux/times.h>
+#include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 #include <net/route.h>
@@ -135,7 +137,8 @@ static unsigned long rt_deadline;
 #define RTprint(a...)  printk(KERN_DEBUG a)
 
 static struct timer_list rt_flush_timer;
-static struct timer_list rt_periodic_timer;
+static void rt_check_expire(struct work_struct *work);
+static DECLARE_DELAYED_WORK(expires_work, rt_check_expire);
 static struct timer_list rt_secret_timer;
 
 /*
@@ -374,8 +377,9 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct rt_cache_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct rt_cache_iter_state *s;
 
+       s = kzalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
                goto out;
        rc = seq_open(file, &rt_cache_seq_ops);
@@ -383,7 +387,6 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file)
                goto out_kfree;
        seq          = file->private_data;
        seq->private = s;
-       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree:
@@ -571,20 +574,19 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
                (fl1->iif ^ fl2->iif)) == 0;
 }
 
-/* This runs via a timer and thus is always in BH context. */
-static void rt_check_expire(unsigned long dummy)
+static void rt_check_expire(struct work_struct *work)
 {
        static unsigned int rover;
        unsigned int i = rover, goal;
        struct rtable *rth, **rthp;
-       unsigned long now = jiffies;
        u64 mult;
 
        mult = ((u64)ip_rt_gc_interval) << rt_hash_log;
        if (ip_rt_gc_timeout > 1)
                do_div(mult, ip_rt_gc_timeout);
        goal = (unsigned int)mult;
-       if (goal > rt_hash_mask) goal = rt_hash_mask + 1;
+       if (goal > rt_hash_mask)
+               goal = rt_hash_mask + 1;
        for (; goal > 0; goal--) {
                unsigned long tmo = ip_rt_gc_timeout;
 
@@ -593,11 +595,11 @@ static void rt_check_expire(unsigned long dummy)
 
                if (*rthp == 0)
                        continue;
-               spin_lock(rt_hash_lock_addr(i));
+               spin_lock_bh(rt_hash_lock_addr(i));
                while ((rth = *rthp) != NULL) {
                        if (rth->u.dst.expires) {
                                /* Entry is expired even if it is in use */
-                               if (time_before_eq(now, rth->u.dst.expires)) {
+                               if (time_before_eq(jiffies, rth->u.dst.expires)) {
                                        tmo >>= 1;
                                        rthp = &rth->u.dst.rt_next;
                                        continue;
@@ -612,14 +614,10 @@ static void rt_check_expire(unsigned long dummy)
                        *rthp = rth->u.dst.rt_next;
                        rt_free(rth);
                }
-               spin_unlock(rt_hash_lock_addr(i));
-
-               /* Fallback loop breaker. */
-               if (time_after(jiffies, now))
-                       break;
+               spin_unlock_bh(rt_hash_lock_addr(i));
        }
        rover = i;
-       mod_timer(&rt_periodic_timer, jiffies + ip_rt_gc_interval);
+       schedule_delayed_work(&expires_work, ip_rt_gc_interval);
 }
 
 /* This can run from both BH and non-BH contexts, the latter
@@ -2212,7 +2210,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
 
 
        if (oldflp->oif) {
-               dev_out = dev_get_by_index(oldflp->oif);
+               dev_out = dev_get_by_index(&init_net, oldflp->oif);
                err = -ENODEV;
                if (dev_out == NULL)
                        goto out;
@@ -2591,7 +2589,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
        if (iif) {
                struct net_device *dev;
 
-               dev = __dev_get_by_index(iif);
+               dev = __dev_get_by_index(&init_net, iif);
                if (dev == NULL) {
                        err = -ENODEV;
                        goto errout_free;
@@ -2992,17 +2990,14 @@ int __init ip_rt_init(void)
 
        init_timer(&rt_flush_timer);
        rt_flush_timer.function = rt_run_flush;
-       init_timer(&rt_periodic_timer);
-       rt_periodic_timer.function = rt_check_expire;
        init_timer(&rt_secret_timer);
        rt_secret_timer.function = rt_secret_rebuild;
 
        /* All the timers, started at system startup tend
           to synchronize. Perturb it a bit.
         */
-       rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval +
-                                       ip_rt_gc_interval;
-       add_timer(&rt_periodic_timer);
+       schedule_delayed_work(&expires_work,
+               net_random() % ip_rt_gc_interval + ip_rt_gc_interval);
 
        rt_secret_timer.expires = jiffies + net_random() % ip_rt_secret_interval +
                ip_rt_secret_interval;
@@ -3011,15 +3006,15 @@ int __init ip_rt_init(void)
 #ifdef CONFIG_PROC_FS
        {
        struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
-       if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
+       if (!proc_net_fops_create(&init_net, "rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
            !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
-                                            proc_net_stat))) {
+                                            init_net.proc_net_stat))) {
                return -ENOMEM;
        }
        rtstat_pde->proc_fops = &rt_cpu_seq_fops;
        }
 #ifdef CONFIG_NET_CLS_ROUTE
-       create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
+       create_proc_read_entry("rt_acct", 0, init_net.proc_net, ip_rt_acct_read, NULL);
 #endif
 #endif
 #ifdef CONFIG_XFRM