* [PATCH] seq_file: add RCU versions of new hlist/list iterators
From: Stephen Hemminger @ 2010-02-18 23:30 UTC (permalink / raw)
To: David S. Miller, Paul E. McKenney; +Cc: netdev, linux-kernel
Many usages of seq_file use RCU protected lists, so non RCU
iterators will not work safely.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
fs/seq_file.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/rculist.h | 5 ++
include/linux/seq_file.h | 27 ++++++++++-----
3 files changed, 105 insertions(+), 9 deletions(-)
--- a/fs/seq_file.c 2010-02-18 15:08:53.228872265 -0800
+++ b/fs/seq_file.c 2010-02-18 15:26:21.157402219 -0800
@@ -695,6 +695,38 @@ struct list_head *seq_list_next(void *v,
}
EXPORT_SYMBOL(seq_list_next);
+struct list_head *seq_list_start_rcu(struct list_head *head, loff_t pos)
+{
+ struct list_head *lh;
+
+ __list_for_each_rcu(lh, head)
+ if (pos-- == 0)
+ return lh;
+
+ return NULL;
+}
+EXPORT_SYMBOL(seq_list_start_rcu);
+
+struct list_head *seq_list_start_head_rcu(struct list_head *head, loff_t pos)
+{
+ if (!pos)
+ return head;
+
+ return seq_list_start_rcu(head, pos - 1);
+}
+EXPORT_SYMBOL(seq_list_start_head_rcu);
+
+struct list_head *seq_list_next_rcu(void *v, struct list_head *head,
+ loff_t *ppos)
+{
+ struct list_head *lh = v;
+
+ lh = rcu_dereference(lh->next);
+ ++*ppos;
+ return lh == head ? NULL : lh;
+}
+EXPORT_SYMBOL(seq_list_next_rcu);
+
/**
* seq_hlist_start - start an iteration of a hlist
* @head: the head of the hlist
@@ -750,3 +782,53 @@ struct hlist_node *seq_hlist_next(void *
return node->next;
}
EXPORT_SYMBOL(seq_hlist_next);
+
+/**
+ * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
+ * @head: the head of the hlist
+ * @pos: the start position of the sequence
+ *
+ * Called at seq_file->op->start().
+ */
+struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, loff_t pos)
+{
+ struct hlist_node *node;
+
+ __hlist_for_each_rcu(node, head)
+ if (pos-- == 0)
+ return node;
+ return NULL;
+}
+EXPORT_SYMBOL(seq_hlist_start_rcu);
+
+/**
+ * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
+ * @head: the head of the hlist
+ * @pos: the start position of the sequence
+ *
+ * Called at seq_file->op->start(). Call this function if you want to
+ * print a header at the top of the output.
+ */
+struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, loff_t pos)
+{
+ if (!pos)
+ return SEQ_START_TOKEN;
+
+ return seq_hlist_start_rcu(head, pos - 1);
+}
+EXPORT_SYMBOL(seq_hlist_start_rcu);
+
+/**
+ * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
+ * @v: the current iterator
+ * @head: the head of the hlist
+ * @pos: the current posision
+ *
+ * Called at seq_file->op->next().
+ */
+struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head,
+ loff_t *ppos)
+{
+ return rcu_dereference(seq_hlist_next(v, head, ppos));
+}
+EXPORT_SYMBOL(seq_hlist_next_rcu);
--- a/include/linux/seq_file.h 2010-02-18 15:08:53.256872028 -0800
+++ b/include/linux/seq_file.h 2010-02-18 15:09:14.128997914 -0800
@@ -127,23 +127,32 @@ int seq_release_private(struct inode *,
/*
* Helpers for iteration over list_head-s in seq_files
*/
-
extern struct list_head *seq_list_start(struct list_head *head,
- loff_t pos);
+ loff_t pos);
extern struct list_head *seq_list_start_head(struct list_head *head,
- loff_t pos);
+ loff_t pos);
extern struct list_head *seq_list_next(void *v, struct list_head *head,
- loff_t *ppos);
-
+ loff_t *ppos);
+extern struct list_head *seq_list_start_rcu(struct list_head *head,
+ loff_t pos);
+extern struct list_head *seq_list_start_head_rcu(struct list_head *head,
+ loff_t pos);
+extern struct list_head *seq_list_next_rcu(void *v, struct list_head *head,
+ loff_t *ppos);
/*
* Helpers for iteration over hlist_head-s in seq_files
*/
-
extern struct hlist_node *seq_hlist_start(struct hlist_head *head,
- loff_t pos);
+ loff_t pos);
extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head,
- loff_t pos);
+ loff_t pos);
extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
- loff_t *ppos);
+ loff_t *ppos);
+extern struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
+ loff_t pos);
+extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
+ loff_t pos);
+extern struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head,
+ loff_t *ppos);
#endif
--- a/include/linux/rculist.h 2010-02-18 15:25:03.681496691 -0800
+++ b/include/linux/rculist.h 2010-02-18 15:26:13.909286656 -0800
@@ -406,6 +406,11 @@ static inline void hlist_add_after_rcu(s
n->next->pprev = &n->next;
}
+#define __hlist_for_each(pos, head) \
+ for (pos = rcu_dereference((head)->first); \
+ pos && ({ prefetch(pos->next); 1; }); \
+ pos = rcu_derference(pos->next))
+
/**
* hlist_for_each_entry_rcu - iterate over rcu list of given type
* @tpos: the type * to use as a loop cursor.
^ permalink raw reply
* Re: connect() sometimes succeeds when it shouldn't
From: Ilpo Järvinen @ 2010-02-18 23:09 UTC (permalink / raw)
To: Bruce Cran; +Cc: netdev
In-Reply-To: <201002181947.11125.bruce@cran.org.uk>
On Thu, 18 Feb 2010, Bruce Cran wrote:
> I've found that if I run a program that does lots of calls to connect() then
> it will eventually succeed when there's no server listening. For SCTP it takes
> a few thousand, for TCP up to a couple of million. I first came across the
> problem in Windows, where the connection was being processed so quickly that
> by the time the handler function had finished, the 'connecting' flag had
> already been reset, which wasn't expected. I've not checked the Linux sources
> to see if something similar is happening though.
>
> The machine I tested it on was running a 2.6.32 i686 kernel.
>
> The test code can be found at
> http://www.cran.org.uk/~brucec/linux/badconnect.c
Perhaps you just managed to dial your own number? ...Please try with
my improved version of badconnect.c below. :-)
--
i.
--
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <errno.h>
int main(void)
{
struct sockaddr_in sa;
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd <= 0)
err(1, "socket");
memset(&sa, 0, sizeof(sa));
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_family = AF_INET;
sa.sin_port = htons(60234);
if (bind(fd, (struct sockaddr*)&sa, sizeof(sa))) {
perror("bind");
exit(1);
}
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(60234);
if (inet_aton("127.0.0.1", &(sa.sin_addr)) != 1)
exit(1);
if (connect(fd, (struct sockaddr*)&sa, sizeof(sa)) == 0) {
printf("bad connect on iter %d\n", 1);
exit(1);
}
close(fd);
return 0;
}
^ permalink raw reply
* Re: [net-next-2.6 PATCH] staging: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-02-18 23:02 UTC (permalink / raw)
To: jpirko; +Cc: netdev
In-Reply-To: <20100218151014.GJ2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 16:10:14 +0100
> removed needless checks in arlan-main.c and slicoss.c
> fixed bug in et131x_netdev.c to actually fill addresses in.
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] net/usb: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-02-18 23:02 UTC (permalink / raw)
To: jpirko; +Cc: netdev
In-Reply-To: <20100218140226.GI2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 15:02:26 +0100
> also removed needless checks in smsc95xx
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] tulip: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: jpirko; +Cc: netdev, grundler, kyle
In-Reply-To: <20100218133453.GH2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 14:34:54 +0100
> also bug in de2104x.c was corrected:
> for (i = 0; i < 32; i++) loop should be outside mc_list iteration.
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] net: convert multiple drivers to use netdev_for_each_mc_addr, part2
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: jpirko; +Cc: netdev
In-Reply-To: <20100218104253.GE2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 11:42:54 +0100
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] smsc911x: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: jpirko; +Cc: netdev, steve.glendinning
In-Reply-To: <20100218092238.GD2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 10:22:38 +0100
> also removed unnecessary checks
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] 3c5xx: use netdev_mc_* helpers
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: jpirko; +Cc: netdev
In-Reply-To: <20100218091214.GC2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 10:12:15 +0100
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] depca: remove forgotten needless inicialization
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: jpirko; +Cc: netdev
In-Reply-To: <20100218085506.GB2772@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 18 Feb 2010 09:55:07 +0100
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Applied.
^ permalink raw reply
* Re: regression due to "flush SAD/SPD generate false events"
From: David Miller @ 2010-02-18 23:01 UTC (permalink / raw)
To: hadi; +Cc: adobriyan, netdev
In-Reply-To: <1266533561.3879.132.camel@bigi>
From: jamal <hadi@cyberus.ca>
Date: Thu, 18 Feb 2010 17:52:41 -0500
> I dont have time to fix it right now - but i will send a patch
> tommorow.
Ok, thanks for the update.
^ permalink raw reply
* Re: regression due to "flush SAD/SPD generate false events"
From: jamal @ 2010-02-18 22:52 UTC (permalink / raw)
To: David Miller; +Cc: adobriyan, netdev
In-Reply-To: <20100218.142735.230862605.davem@davemloft.net>
On Thu, 2010-02-18 at 14:27 -0800, David Miller wrote:
> Let's see how #2 works out, if we get any more breakage
> cases reported then we'll have to revert again and go with
> #1.
Actually, i think i found the root cause. The sequence should be:
1) pfkey->kernel: flush
kernel flushes SA/SPD
2)kernel->pfkey: respond to flush message
3)kernel->all user space listeners: i just flushed the SA/SPD
#2 is always needed.
#3 is wrong if SA/SPD is empty.
kernel unfortunately sends a single broadcast which combines
#2 and #3. So the proper fix is to break #2 and #3 into
separate messages. And follow the rules above.
I dont have time to fix it right now - but i will send a patch
tommorow.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH net-next-2.6] vhost: Restart tx poll when socket send queue is full
From: Michael S. Tsirkin @ 2010-02-18 22:30 UTC (permalink / raw)
To: Sridhar Samudrala; +Cc: David Miller, netdev
In-Reply-To: <1266526751.15681.71.camel@w-sridhar.beaverton.ibm.com>
On Thu, Feb 18, 2010 at 12:59:11PM -0800, Sridhar Samudrala wrote:
> When running guest to remote host TCP stream test using vhost-net
> via tap/macvtap, i am seeing network transmit hangs. This happens
> when handle_tx() returns because of the socket send queue full
> condition.
> This patch fixes this by restarting tx poll when hitting this
> condition.
Thanks! I would like to better understand what happens exactly.
Some questions below:
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 91a324c..82d4bbe 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -113,12 +113,16 @@ static void handle_tx(struct vhost_net *net)
> if (!sock)
> return;
>
> - wmem = atomic_read(&sock->sk->sk_wmem_alloc);
> - if (wmem >= sock->sk->sk_sndbuf)
> - return;
> -
The disadvantage here is that a spurious wakeup
when queue is still full becomes more expensive.
> use_mm(net->dev.mm);
> mutex_lock(&vq->mutex);
> +
> + wmem = atomic_read(&sock->sk->sk_wmem_alloc);
> + if (wmem >= sock->sk->sk_sndbuf) {
> + tx_poll_start(net, sock);
Hmm. We already do
if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
tx_poll_start(net, sock);
set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
break;
}
why does not this code trigger here?
> + set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
Isn't the bit already set? If not, why?
> + goto unlock;
> + }
> +
> vhost_disable_notify(vq);
>
> if (wmem < sock->sk->sk_sndbuf * 2)
> @@ -178,6 +182,7 @@ static void handle_tx(struct vhost_net *net)
> }
> }
>
> +unlock:
> mutex_unlock(&vq->mutex);
> unuse_mm(net->dev.mm);
> }
>
^ permalink raw reply
* [net-next PATCH v5 2/3] sysctl: add proc_do_large_bitmap
From: Octavian Purdila @ 2010-02-18 22:32 UTC (permalink / raw)
To: David Miller
Cc: Octavian Purdila, Linux Kernel Network Developers,
Linux Kernel Developers, WANG Cong, Eric W. Biederman
The new function can be used to read/write large bitmaps via /proc. A
comma separated range format is used for compact output and input
(e.g. 1,3-4,10-10).
Writing into the file will first reset the bitmap then update it
based on the given input.
Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
Cc: WANG Cong <amwang@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
---
include/linux/sysctl.h | 2 +
kernel/sysctl.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+), 0 deletions(-)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index f66014c..7bb5cb6 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -980,6 +980,8 @@ extern int proc_doulongvec_minmax(struct ctl_table *, int,
void __user *, size_t *, loff_t *);
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
void __user *, size_t *, loff_t *);
+extern int proc_do_large_bitmap(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
/*
* Register a set of sysctl names by calling register_sysctl_table
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5259727..ef2c13d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2635,6 +2635,128 @@ static int proc_do_cad_pid(struct ctl_table *table, int write,
return 0;
}
+/**
+ * proc_do_large_bitmap - read/write from/to a large bitmap
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ * @ppos: file position
+ *
+ * The bitmap is stored at table->data and the bitmap length (in bits)
+ * in table->maxlen.
+ *
+ * We use a range comma separated format (e.g. 1,3-4,10-10) so that
+ * large bitmaps may be represented in a compact manner. Writing into
+ * the file will clear the bitmap then update it with the given input.
+ *
+ * Returns 0 on success.
+ */
+int proc_do_large_bitmap(struct ctl_table *table, int write,
+ void __user *_buffer, size_t *lenp, loff_t *ppos)
+{
+ bool first = 1;
+ unsigned long *bitmap = (unsigned long *) table->data;
+ unsigned long bitmap_len = table->maxlen;
+ int left = *lenp, err = 0;
+ char __user *buffer = (char __user *) _buffer;
+ char tr_a[] = { '-', ',', 0 }, tr_b[] = { ',', 0 }, c;
+
+
+ if (!bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ if (write) {
+ bitmap_clear(bitmap, 0, bitmap_len);
+ err = proc_skip_wspace(&buffer, &left);
+ while (!err && left) {
+ unsigned long val_a, val_b;
+ bool neg;
+
+ err = proc_get_ulong(&buffer, &left, tr_a,
+ &val_a, &neg, &c);
+ if (err)
+ break;
+
+ if (val_a >= bitmap_len || neg) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (!left || c != '-') {
+ if (c == ',') {
+ buffer++;
+ left--;
+ }
+ val_b = val_a;
+ goto update;
+ }
+
+ /* skip the - */
+ buffer++; left--;
+
+ err = proc_get_ulong(&buffer, &left, tr_b,
+ &val_b, &neg, &c);
+ if (err)
+ break;
+
+ if (val_b >= bitmap_len || neg || val_a > val_b) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (left && c == ',') {
+ buffer++;
+ left--;
+ }
+
+update:
+ while (val_a <= val_b)
+ set_bit(val_a++, bitmap);
+
+ first = 0; val_b++;
+ }
+ if (!err)
+ err = proc_skip_wspace(&buffer, &left);
+ } else {
+ unsigned long bit_a, bit_b = 0;
+
+ while (left) {
+ bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
+ if (bit_a >= bitmap_len)
+ break;
+ bit_b = find_next_zero_bit(bitmap, bitmap_len,
+ bit_a + 1) - 1;
+
+ err = proc_put_ulong(&buffer, &left, bit_a, 0, first,
+ ',');
+ if (err)
+ break;
+ if (bit_a != bit_b) {
+ err = proc_put_char(&buffer, &left, '-');
+ if (err)
+ break;
+ err = proc_put_ulong(&buffer, &left, bit_b, 0,
+ 1, 0);
+ if (err)
+ break;
+ }
+
+ first = 0; bit_b++;
+ }
+ if (!err)
+ err = proc_put_char(&buffer, &left, '\n');
+ }
+
+ if (write && first)
+ return err;
+ *lenp -= left;
+ *ppos += *lenp;
+ return 0;
+}
+
#else /* CONFIG_PROC_FS */
int proc_dostring(struct ctl_table *table, int write,
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH] ipv6: drop unused "dev" arg of icmpv6_send()
From: David Miller @ 2010-02-18 22:30 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20100218182524.GD21184@x200>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 18 Feb 2010 20:25:24 +0200
> Dunno, what was the idea, it wasn't used for a long time.
>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] const: struct nla_policy
From: David Miller @ 2010-02-18 22:30 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20100218181431.GC21184@x200>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 18 Feb 2010 20:14:31 +0200
> Make remaining netlink policies as const.
> Fixup coding style where needed.
>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] ipv6: use standard lists for FIB walks
From: David Miller @ 2010-02-18 22:30 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20100218181330.GB21184@x200>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 18 Feb 2010 20:13:30 +0200
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Applied, thanks for doing this.
^ permalink raw reply
* Re: [PATCH] ipv6: remove stale MIB definitions
From: David Miller @ 2010-02-18 22:30 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20100218181220.GA21184@x200>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 18 Feb 2010 20:12:20 +0200
> ICMP6 MIB statistics was per-netns for quite a time.
>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Applied.
^ permalink raw reply
* [net-next PATCH v5 3/3] net: reserve ports for applications using fixed port numbers
From: Octavian Purdila @ 2010-02-18 22:30 UTC (permalink / raw)
To: David Miller
Cc: Octavian Purdila, Linux Kernel Network Developers,
Linux Kernel Developers, WANG Cong, Neil Horman, Eric Dumazet,
Eric W. Biederman
In-Reply-To: <1266532210-11536-1-git-send-email-opurdila@ixiacom.com>
This patch introduces /proc/sys/net/ipv4/ip_local_reserved_ports which
allows users to reserve ports for third-party applications.
The reserved ports will not be used by automatic port assignments
(e.g. when calling connect() or bind() with port number 0). Explicit
port allocation behavior is unchanged.
Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
Signed-off-by: WANG Cong <amwang@redhat.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
---
Documentation/networking/ip-sysctl.txt | 14 ++++++++++++++
drivers/infiniband/core/cma.c | 7 ++++++-
include/net/ip.h | 6 ++++++
net/ipv4/af_inet.c | 8 +++++++-
net/ipv4/inet_connection_sock.c | 6 ++++++
net/ipv4/inet_hashtables.c | 2 ++
net/ipv4/sysctl_net_ipv4.c | 17 +++++++++++++++++
net/ipv4/udp.c | 3 ++-
net/sctp/socket.c | 2 ++
9 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 2dc7a1d..6534ee7 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -564,6 +564,20 @@ ip_local_port_range - 2 INTEGERS
(i.e. by default) range 1024-4999 is enough to issue up to
2000 connections per second to systems supporting timestamps.
+ip_local_reserved_ports - list of comma separated ranges
+ Specify the ports which are reserved for known third-party
+ applications. These ports will not be used by automatic port
+ assignments (e.g. when calling connect() or bind() with port
+ number 0). Explicit port allocation behavior is unchanged.
+
+ The format used for both input and output is a comma separated
+ list of ranges (e.g. "1,2-4,10-10" for ports 1, 2, 3, 4 and
+ 10). Writing to the file will clear all previously reserved
+ ports and update the current list with the one given in the
+ input.
+
+ Default: Empty
+
ip_nonlocal_bind - BOOLEAN
If set, allows processes to bind() to non-local IP addresses,
which can be quite useful - but may break some applications.
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 875e34e..06c9fa5 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1979,6 +1979,8 @@ retry:
/* FIXME: add proper port randomization per like inet_csk_get_port */
do {
ret = idr_get_new_above(ps, bind_list, next_port, &port);
+ if (inet_is_reserved_local_port(port))
+ ret = -EAGAIN;
} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
if (ret)
@@ -2995,10 +2997,13 @@ static int __init cma_init(void)
{
int ret, low, high, remaining;
- get_random_bytes(&next_port, sizeof next_port);
inet_get_local_port_range(&low, &high);
+again:
+ get_random_bytes(&next_port, sizeof next_port);
remaining = (high - low) + 1;
next_port = ((unsigned int) next_port % remaining) + low;
+ if (inet_is_reserved_local_port(next_port))
+ goto again;
cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq)
diff --git a/include/net/ip.h b/include/net/ip.h
index 503994a..3da9004 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -184,6 +184,12 @@ extern struct local_ports {
} sysctl_local_ports;
extern void inet_get_local_port_range(int *low, int *high);
+extern unsigned long *sysctl_local_reserved_ports;
+static inline int inet_is_reserved_local_port(int port)
+{
+ return test_bit(port, sysctl_local_reserved_ports);
+}
+
extern int sysctl_ip_default_ttl;
extern int sysctl_ip_nonlocal_bind;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 33b7dff..e283fbe 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1546,9 +1546,13 @@ static int __init inet_init(void)
BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
+ sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
+ if (!sysctl_local_reserved_ports)
+ goto out;
+
rc = proto_register(&tcp_prot, 1);
if (rc)
- goto out;
+ goto out_free_reserved_ports;
rc = proto_register(&udp_prot, 1);
if (rc)
@@ -1647,6 +1651,8 @@ out_unregister_udp_proto:
proto_unregister(&udp_prot);
out_unregister_tcp_proto:
proto_unregister(&tcp_prot);
+out_free_reserved_ports:
+ kfree(sysctl_local_reserved_ports);
goto out;
}
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 8da6429..1acb462 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -37,6 +37,9 @@ struct local_ports sysctl_local_ports __read_mostly = {
.range = { 32768, 61000 },
};
+unsigned long *sysctl_local_reserved_ports;
+EXPORT_SYMBOL(sysctl_local_reserved_ports);
+
void inet_get_local_port_range(int *low, int *high)
{
unsigned seq;
@@ -108,6 +111,8 @@ again:
smallest_size = -1;
do {
+ if (inet_is_reserved_local_port(rover))
+ goto next_nolock;
head = &hashinfo->bhash[inet_bhashfn(net, rover,
hashinfo->bhash_size)];
spin_lock(&head->lock);
@@ -130,6 +135,7 @@ again:
break;
next:
spin_unlock(&head->lock);
+ next_nolock:
if (++rover > high)
rover = low;
} while (--remaining > 0);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 2b79377..d3e160a 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -456,6 +456,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
local_bh_disable();
for (i = 1; i <= remaining; i++) {
port = low + (i + offset) % remaining;
+ if (inet_is_reserved_local_port(port))
+ continue;
head = &hinfo->bhash[inet_bhashfn(net, port,
hinfo->bhash_size)];
spin_lock(&head->lock);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 7e3712c..072e193 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -298,6 +298,13 @@ static struct ctl_table ipv4_table[] = {
.mode = 0644,
.proc_handler = ipv4_local_port_range,
},
+ {
+ .procname = "ip_local_reserved_ports",
+ .data = NULL, /* initialized in sysctl_ipv4_init */
+ .maxlen = 65536,
+ .mode = 0644,
+ .proc_handler = proc_do_large_bitmap,
+ },
#ifdef CONFIG_IP_MULTICAST
{
.procname = "igmp_max_memberships",
@@ -721,6 +728,16 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
static __init int sysctl_ipv4_init(void)
{
struct ctl_table_header *hdr;
+ struct ctl_table *i;
+
+ for (i = ipv4_table; i->procname; i++) {
+ if (strcmp(i->procname, "ip_local_reserved_ports") == 0) {
+ i->data = sysctl_local_reserved_ports;
+ break;
+ }
+ }
+ if (!i->procname)
+ return -EINVAL;
hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table);
if (hdr == NULL)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 608a544..bfd0a6a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -232,7 +232,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
*/
do {
if (low <= snum && snum <= high &&
- !test_bit(snum >> udptable->log, bitmap))
+ !test_bit(snum >> udptable->log, bitmap) &&
+ !inet_is_reserved_local_port(snum))
goto found;
snum += rand;
} while (snum != first);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index f6d1e59..1f839d0 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5432,6 +5432,8 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
rover++;
if ((rover < low) || (rover > high))
rover = low;
+ if (inet_is_reserved_local_port(rover))
+ continue;
index = sctp_phashfn(rover);
head = &sctp_port_hashtable[index];
sctp_spin_lock(&head->lock);
--
1.5.6.5
^ permalink raw reply related
* [net-next PATCH v5 0/3] net: reserve ports for applications using fixed port numbers
From: Octavian Purdila @ 2010-02-18 22:30 UTC (permalink / raw)
To: David Miller
Cc: Octavian Purdila, Linux Kernel Network Developers,
Linux Kernel Developers, WANG Cong, Neil Horman, Eric Dumazet,
Eric W. Biederman
This patch introduces /proc/sys/net/ipv4/ip_local_reserved_ports which
allows users to reserve ports for third-party applications.
The reserved ports will not be used by automatic port assignments
(e.g. when calling connect() or bind() with port number 0). Explicit
port allocation behavior is unchanged.
Changes from the previous version:
- switch the /proc entry format to coma separated list of range ports
- treat -EFAULT just like any other error and acknowledge written values
- use isdigit() in proc_get_ulong
Octavian Purdila (3):
sysctl: refactor integer handling proc code
sysctl: add proc_do_large_bitmap
net: reserve ports for applications using fixed port numbers
Documentation/networking/ip-sysctl.txt | 14 +
drivers/infiniband/core/cma.c | 7 +-
include/linux/sysctl.h | 2 +
include/net/ip.h | 6 +
kernel/sysctl.c | 449 +++++++++++++++++++++-----------
net/ipv4/af_inet.c | 8 +-
net/ipv4/inet_connection_sock.c | 6 +
net/ipv4/inet_hashtables.c | 2 +
net/ipv4/sysctl_net_ipv4.c | 17 ++
net/ipv4/udp.c | 3 +-
net/sctp/socket.c | 2 +
11 files changed, 361 insertions(+), 155 deletions(-)
^ permalink raw reply
* Re: regression due to "flush SAD/SPD generate false events"
From: David Miller @ 2010-02-18 22:27 UTC (permalink / raw)
To: hadi; +Cc: adobriyan, netdev
In-Reply-To: <1266529558.3879.121.camel@bigi>
From: jamal <hadi@cyberus.ca>
Date: Thu, 18 Feb 2010 16:45:58 -0500
> The two options are: 1) Restore old behavior just for pfkey
> where bogus event is sent always or 2) return -ESRCH as I
> have done in the last patch.
> I think #2 is more accurate. But if that is going to break
> existing scripts then #1 is the way to go.
>
> Thoughts?
Let's see how #2 works out, if we get any more breakage
cases reported then we'll have to revert again and go with
#1.
^ permalink raw reply
* Re: [PATCH] AF_UNIX: update locking comment
From: David Miller @ 2010-02-18 22:12 UTC (permalink / raw)
To: shemminger; +Cc: netdev
In-Reply-To: <20100218093423.52165efd@nehalam>
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Thu, 18 Feb 2010 09:34:23 -0800
> The lock used in unix_state_lock() is a spin_lock not reader-writer.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 3/3] macvtap: add GSO/csum offload support
From: David Miller @ 2010-02-18 22:11 UTC (permalink / raw)
To: arnd; +Cc: sri, kaber, eswierk, netdev
In-Reply-To: <201002181648.17390.arnd@arndb.de>
From: Arnd Bergmann <arnd@arndb.de>
Date: Thu, 18 Feb 2010 16:48:17 +0100
> Added flags field to macvtap_queue to enable/disable processing of
> virtio_net_hdr via IFF_VNET_HDR. This flag is checked to prepend virtio_net_hdr
> in the receive path and process/skip virtio_net_hdr in the send path.
>
> Original patch by Sridhar, further changes by Arnd.
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Applied.
^ permalink raw reply
* Re: [PATCH 2/3] net/macvtap: add vhost support
From: David Miller @ 2010-02-18 22:11 UTC (permalink / raw)
To: arnd; +Cc: sri, kaber, eswierk, netdev, mst
In-Reply-To: <201002181646.50674.arnd@arndb.de>
From: Arnd Bergmann <arnd@arndb.de>
Date: Thu, 18 Feb 2010 16:46:50 +0100
> This adds support for passing a macvtap file descriptor into
> vhost-net, much like we already do for tun/tap.
>
> Most of the new code is taken from the respective patch
> in the tun driver and may get consolidated in the future.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Applied.
^ permalink raw reply
* Re: [PATCH 1/3] macvtap: rework object lifetime rules
From: David Miller @ 2010-02-18 22:11 UTC (permalink / raw)
To: arnd; +Cc: sri, kaber, eswierk, netdev
In-Reply-To: <201002181645.36426.arnd@arndb.de>
From: Arnd Bergmann <arnd@arndb.de>
Date: Thu, 18 Feb 2010 16:45:36 +0100
> This reworks the change done by the previous patch
> in a more complete way.
>
> The original macvtap code has a number of problems
> resulting from the use of RCU for protecting the
> access to struct macvtap_queue from open files.
>
> This includes
> - need for GFP_ATOMIC allocations for skbs
> - potential deadlocks when copy_*_user sleeps
> - inability to work with vhost-net
>
> Changing the lifetime of macvtap_queue to always
> depend on the open file solves all these. The
> RCU reference simply moves one step down to
> the reference on the macvlan_dev, which we
> only need for nonblocking operations.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Applied.
^ permalink raw reply
* Re: netfilter 00/09: netfilter update part II
From: Jan Engelhardt @ 2010-02-18 21:48 UTC (permalink / raw)
To: kaber; +Cc: netdev, David Miller, Netfilter Developer Mailing List
In-Reply-To: <20100218.121624.32079245.davem@davemloft.net>
From: Patrick McHardy <kaber@trash.net>
Date: Thu, 18 Feb 2010 19:21:03 +0100 (MET)
> following are a few more netfilter patches for 2.6.34, containing:
>
> - bridge netfilter compat support from Florian Westphal
> - IPVS SCTP load-balancing support from Venkata Mohan Reddy
> - a build fix for nf_defrag_ipv4 from myself
>
> Please apply or pull from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6.git master
Can I send my next batch? :)
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox