Commit 39ac466e authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/network-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents d6d29b7d ebc68c9c
......@@ -797,6 +797,8 @@ extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_dointvec_userhz_jiffies(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_dointvec_ms_jiffies(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_doulongvec_minmax(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
......@@ -814,6 +816,7 @@ extern int do_sysctl_strategy (ctl_table *table,
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
extern ctl_handler sysctl_jiffies;
extern ctl_handler sysctl_ms_jiffies;
/*
......
......@@ -149,6 +149,8 @@ extern atomic_t inet6_sock_nr;
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
int snmp6_alloc_dev(struct inet6_dev *idev);
int snmp6_free_dev(struct inet6_dev *idev);
int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
void snmp6_mib_free(void *ptr[2]);
......
......@@ -1902,6 +1902,27 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
return 0;
}
static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
if (write) {
*valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
} else {
int val = *valp;
unsigned long lval;
if (val < 0) {
*negp = -1;
lval = (unsigned long)-val;
} else {
*negp = 0;
lval = (unsigned long)val;
}
*lvalp = jiffies_to_msecs(lval);
}
return 0;
}
/**
* proc_dointvec_jiffies - read a vector of integers as seconds
* @table: the sysctl table
......@@ -1946,6 +1967,28 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
do_proc_dointvec_userhz_jiffies_conv,NULL);
}
/**
* proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
* @table: the sysctl table
* @write: %TRUE if this is a write to the sysctl file
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
* The values read are assumed to be in 1/1000 seconds, and
* are converted into jiffies.
*
* Returns 0 on success.
*/
int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
do_proc_dointvec_ms_jiffies_conv, NULL);
}
#else /* CONFIG_PROC_FS */
int proc_dostring(ctl_table *table, int write, struct file *filp,
......@@ -1990,6 +2033,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
return -ENOSYS;
}
int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
......@@ -2119,6 +2168,33 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
return 1;
}
/* Strategy function to convert jiffies to seconds */
int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context)
{
if (oldval) {
size_t olen;
if (oldlenp) {
if (get_user(olen, oldlenp))
return -EFAULT;
if (olen!=sizeof(int))
return -EINVAL;
}
if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
(oldlenp && put_user(sizeof(int),oldlenp)))
return -EFAULT;
}
if (newval && newlen) {
int new;
if (newlen != sizeof(int))
return -EINVAL;
if (get_user(new, (int __user *)newval))
return -EFAULT;
*(int *)(table->data) = msecs_to_jiffies(new);
}
return 1;
}
#else /* CONFIG_SYSCTL */
......@@ -2149,6 +2225,13 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
return -ENOSYS;
}
int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context)
{
return -ENOSYS;
}
int proc_dostring(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
......@@ -2185,6 +2268,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
return -ENOSYS;
}
int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
......@@ -2219,11 +2308,13 @@ EXPORT_SYMBOL(proc_dointvec);
EXPORT_SYMBOL(proc_dointvec_jiffies);
EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring);
EXPORT_SYMBOL(proc_doulongvec_minmax);
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
EXPORT_SYMBOL(register_sysctl_table);
EXPORT_SYMBOL(sysctl_intvec);
EXPORT_SYMBOL(sysctl_jiffies);
EXPORT_SYMBOL(sysctl_ms_jiffies);
EXPORT_SYMBOL(sysctl_string);
EXPORT_SYMBOL(unregister_sysctl_table);
......@@ -104,6 +104,8 @@
* Corrections from Nikolai Malykh (nmalykh@bilim.com)
* Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
*
* interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
* 050103
*/
#include <linux/sys.h>
#include <linux/types.h>
......@@ -135,6 +137,7 @@
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/proc_fs.h>
#include <linux/wait.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
......@@ -148,7 +151,7 @@
#include <asm/timex.h>
#define VERSION "pktgen v2.56: Packet Generator for packet performance testing.\n"
#define VERSION "pktgen v2.58: Packet Generator for packet performance testing.\n"
/* #define PG_DEBUG(a) a */
#define PG_DEBUG(a)
......@@ -808,6 +811,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
char* pg_result = NULL;
int tmp = 0;
char buf[128];
pg_result = &(pkt_dev->result[0]);
......@@ -1068,7 +1072,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
if (len < 0) { return len; }
......@@ -1088,7 +1091,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst_max")) {
char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
if (len < 0) { return len; }
......@@ -1109,9 +1111,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6")) {
char buf[128];
len = strn_len(&user_buffer[i], 128 - 1);
len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
......@@ -1133,9 +1133,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6_min")) {
char buf[128];
len = strn_len(&user_buffer[i], 128 - 1);
len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
......@@ -1156,9 +1154,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6_max")) {
char buf[128];
len = strn_len(&user_buffer[i], 128 - 1);
len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
......@@ -1178,9 +1174,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src6")) {
char buf[128];
len = strn_len(&user_buffer[i], 128 - 1);
len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
......@@ -1202,7 +1196,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src_min")) {
char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
if (len < 0) { return len; }
if (copy_from_user(buf, &user_buffer[i], len))
......@@ -1221,7 +1214,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src_max")) {
char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
if (len < 0) { return len; }
if (copy_from_user(buf, &user_buffer[i], len))
......@@ -2402,16 +2394,14 @@ static int thread_is_running(struct pktgen_thread *t )
static int pktgen_wait_thread_run(struct pktgen_thread *t )
{
wait_queue_head_t queue;
init_waitqueue_head(&queue);
if_lock(t);
while(thread_is_running(t)) {
if_unlock(t);
interruptible_sleep_on_timeout(&queue, HZ/10);
msleep_interruptible(100);
if (signal_pending(current))
goto signal;
if_lock(t);
......@@ -2738,6 +2728,7 @@ __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
static void pktgen_thread_worker(struct pktgen_thread *t)
{
DEFINE_WAIT(wait);
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
sigset_t tmpsig;
......@@ -2805,9 +2796,11 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
do_softirq();
tx_since_softirq = 0;
}
} else {
prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
schedule_timeout(HZ/10);
finish_wait(&(t->queue), &wait);
}
else
interruptible_sleep_on_timeout(&(t->queue), HZ/10);
/*
* Back from sleep, either due to the timeout or signal.
......@@ -3117,8 +3110,7 @@ static void __exit pg_cleanup(void)
struct pktgen_thread *t = pktgen_threads;
pktgen_threads->control |= (T_TERMINATE);
while( t == pktgen_threads)
interruptible_sleep_on_timeout(&queue, HZ);
wait_event_interruptible_timeout(queue, (t != pktgen_threads), HZ);
}
/* Un-register us from receiving netdevice events */
......
......@@ -384,10 +384,12 @@ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
/* Previously seen (loopback)? Ignore. Do this before
fragment check. */
if ((*pskb)->nfct)
return NF_ACCEPT;
#endif
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
......
......@@ -98,6 +98,7 @@ struct ipt_hashlimit_htable {
};
static DECLARE_RWLOCK(hashlimit_lock); /* protects htables list */
static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static LIST_HEAD(hashlimit_htables);
static kmem_cache_t *hashlimit_cachep;
......@@ -531,10 +532,19 @@ hashlimit_checkentry(const char *tablename,
if (!r->cfg.expire)
return 0;
/* This is the best we've got: We cannot release and re-grab lock,
* since checkentry() is called before ip_tables.c grabs ipt_mutex.
* We also cannot grab the hashtable spinlock, since htable_create will
* call vmalloc, and that can sleep. And we cannot just re-search
* the list of htable's in htable_create(), since then we would
* create duplicate proc files. -HW */
down(&hlimit_mutex);
r->hinfo = htable_find_get(r->name);
if (!r->hinfo && (htable_create(r) != 0)) {
up(&hlimit_mutex);
return 0;
}
up(&hlimit_mutex);
/* Ugly hack: For SMP, we only want to use one set */
r->u.master = r;
......
......@@ -2545,10 +2545,10 @@ ctl_table ipv4_route_table[] = {
.ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS,
.procname = "gc_min_interval_ms",
.data = &ip_rt_gc_min_interval,
.maxlen = sizeof(unsigned long),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sysctl_jiffies,
.proc_handler = &proc_dointvec_ms_jiffies,
.strategy = &sysctl_ms_jiffies,
},
{
.ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
......
......@@ -308,7 +308,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
printk("Freeing alive inet6 device %p\n", idev);
return;
}
snmp6_unregister_dev(idev);
snmp6_free_dev(idev);
kfree(idev);
}
......@@ -339,6 +339,16 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* We refer to the device */
dev_hold(dev);
if (snmp6_alloc_dev(ndev) < 0) {
ADBG((KERN_WARNING
"%s(): cannot allocate memory for statistics; dev=%s.\n",
__FUNCTION__, dev->name));
neigh_parms_release(&nd_tbl, ndev->nd_parms);
ndev->dead = 1;
in6_dev_finish_destroy(ndev);
return NULL;
}
if (snmp6_register_dev(ndev) < 0) {
ADBG((KERN_WARNING
"%s(): cannot create /proc/net/dev_snmp6/%s\n",
......@@ -2013,6 +2023,10 @@ static int addrconf_ifdown(struct net_device *dev, int how)
dev->ip6_ptr = NULL;
idev->dead = 1;
write_unlock_bh(&addrconf_lock);
/* Step 1.5: remove snmp6 entry */
snmp6_unregister_dev(idev);
}
/* Step 2: clear hash table */
......
......@@ -652,7 +652,9 @@ snmp6_mib_free(void *ptr[2])
{
if (ptr == NULL)
return;
if (ptr[0])
free_percpu(ptr[0]);
if (ptr[1])
free_percpu(ptr[1]);
ptr[0] = ptr[1] = NULL;
}
......
......@@ -201,33 +201,23 @@ static struct file_operations snmp6_seq_fops = {
int snmp6_register_dev(struct inet6_dev *idev)
{
int err = -ENOMEM;
struct proc_dir_entry *p;
if (!idev || !idev->dev)
return -EINVAL;
if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
__alignof__(struct icmpv6_mib)) < 0)
goto err_icmp;
if (!proc_net_devsnmp6)
return -ENOENT;
if (!proc_net_devsnmp6) {
err = -ENOENT;
goto err_proc;
}
p = create_proc_entry(idev->dev->name, S_IRUGO, proc_net_devsnmp6);
if (!p)
goto err_proc;
return -ENOMEM;
p->data = idev;
p->proc_fops = &snmp6_seq_fops;
idev->stats.proc_dir_entry = p;
return 0;
err_proc:
snmp6_mib_free((void **)idev->stats.icmpv6);
err_icmp:
return err;
}
int snmp6_unregister_dev(struct inet6_dev *idev)
......@@ -238,8 +228,6 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
return -EINVAL;
remove_proc_entry(idev->stats.proc_dir_entry->name,
proc_net_devsnmp6);
snmp6_mib_free((void **)idev->stats.icmpv6);
return 0;
}
......@@ -279,6 +267,17 @@ void ipv6_misc_proc_exit(void)
int snmp6_register_dev(struct inet6_dev *idev)
{
return 0;
}
int snmp6_unregister_dev(struct inet6_dev *idev)
{
return 0;
}
#endif /* CONFIG_PROC_FS */
int snmp6_alloc_dev(struct inet6_dev *idev)
{
int err = -ENOMEM;
......@@ -295,11 +294,10 @@ int snmp6_register_dev(struct inet6_dev *idev)
return err;
}
int snmp6_unregister_dev(struct inet6_dev *idev)
int snmp6_free_dev(struct inet6_dev *idev)
{
snmp6_mib_free((void **)idev->stats.icmpv6);
return 0;
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment