Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 05/10] parisc: use RCU to find network device
From: Eric Dumazet @ 2009-11-10 18:26 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Kyle McMartin, Helge Deller, Alexander Beregalov,
	netdev, linux-parisc
In-Reply-To: <20091110175647.480041042@vyatta.com>

Stephen Hemminger a écrit :
> Another place where RCU can be used instead of read_lock(&dev_base_lock)
> This is by inspection, don't have platform or cross-build environment
> to validate.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 

Duplicate of previously posted patch...

http://article.gmane.org/gmane.linux.network/143072




^ permalink raw reply

* Re: [PATCH 06/10] s390: use RCU to walk list of network devices
From: Eric Dumazet @ 2009-11-10 18:27 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Martin Schwidefsky, Heiko Carstens, netdev,
	linux390
In-Reply-To: <20091110175647.547660685@vyatta.com>

Stephen Hemminger a écrit :
> This is similar to other cases where for_each_netdev_rcu
> can be used when gathering information.
> 
> By inspection, don't have platform or cross-build environment
> to validate.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> 
> --- a/arch/s390/appldata/appldata_net_sum.c	2009-11-09 22:19:05.593480476 -0800
> +++ b/arch/s390/appldata/appldata_net_sum.c	2009-11-10 09:28:38.335438652 -0800
> @@ -83,8 +83,9 @@ static void appldata_get_net_sum_data(vo
>  	rx_dropped = 0;
>  	tx_dropped = 0;
>  	collisions = 0;
> -	read_lock(&dev_base_lock);
> -	for_each_netdev(&init_net, dev) {
> +
> +	rcu_read_lock();
> +	for_each_netdev_rcu(&init_net, dev) {
>  		const struct net_device_stats *stats = dev_get_stats(dev);
>  
>  		rx_packets += stats->rx_packets;
> @@ -98,7 +99,8 @@ static void appldata_get_net_sum_data(vo
>  		collisions += stats->collisions;
>  		i++;
>  	}
> -	read_unlock(&dev_base_lock);
> +	rcu_read_unlock();
> +
>  	net_data->nr_interfaces = i;
>  	net_data->rx_packets = rx_packets;
>  	net_data->tx_packets = tx_packets;
> 

Not sure if dev_get_stats(dev) could sleep on some devices...


^ permalink raw reply

* Re: [PATCH 06/10] s390: use RCU to walk list of network devices
From: Stephen Hemminger @ 2009-11-10 18:29 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, Martin Schwidefsky, Heiko Carstens, netdev,
	linux390
In-Reply-To: <4AF9B07F.6070606@gmail.com>

On Tue, 10 Nov 2009 19:27:11 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> Stephen Hemminger a écrit :
> > This is similar to other cases where for_each_netdev_rcu
> > can be used when gathering information.
> > 
> > By inspection, don't have platform or cross-build environment
> > to validate.
> > 
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > 
> > 
> > --- a/arch/s390/appldata/appldata_net_sum.c	2009-11-09 22:19:05.593480476 -0800
> > +++ b/arch/s390/appldata/appldata_net_sum.c	2009-11-10 09:28:38.335438652 -0800
> > @@ -83,8 +83,9 @@ static void appldata_get_net_sum_data(vo
> >  	rx_dropped = 0;
> >  	tx_dropped = 0;
> >  	collisions = 0;
> > -	read_lock(&dev_base_lock);
> > -	for_each_netdev(&init_net, dev) {
> > +
> > +	rcu_read_lock();
> > +	for_each_netdev_rcu(&init_net, dev) {
> >  		const struct net_device_stats *stats = dev_get_stats(dev);
> >  
> >  		rx_packets += stats->rx_packets;
> > @@ -98,7 +99,8 @@ static void appldata_get_net_sum_data(vo
> >  		collisions += stats->collisions;
> >  		i++;
> >  	}
> > -	read_unlock(&dev_base_lock);
> > +	rcu_read_unlock();
> > +
> >  	net_data->nr_interfaces = i;
> >  	net_data->rx_packets = rx_packets;
> >  	net_data->tx_packets = tx_packets;
> > 
> 
> Not sure if dev_get_stats(dev) could sleep on some devices...
> 

It would have already been broken since dev_get_stats is previously
called with read_lock(), and sleeping with any lock held causes warning.

-- 

^ permalink raw reply

* Re: [PATCH 10/10] CAN: use dev_get_by_index_rcu
From: Eric Dumazet @ 2009-11-10 18:34 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Oliver Hartkopp, Alexey Dobriyan, Lothar Wassmann,
	netdev
In-Reply-To: <20091110175647.824581805@vyatta.com>

Stephen Hemminger a écrit :
> Use new function to avoid doing read_lock().
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/net/can/bcm.c	2009-11-10 09:45:16.301376272 -0800
> +++ b/net/can/bcm.c	2009-11-10 09:46:30.125005956 -0800
> @@ -139,13 +139,13 @@ static char *bcm_proc_getifname(char *re
>  	if (!ifindex)
>  		return "any";
>  
> -	read_lock(&dev_base_lock);
> -	dev = __dev_get_by_index(&init_net, ifindex);
> +	rcu_read_lock();
> +	dev = dev_get_by_index_rcu(&init_net, ifindex);
>  	if (dev)
>  		strcpy(result, dev->name);
>  	else
>  		strcpy(result, "???");
> -	read_unlock(&dev_base_lock);
> +	rcu_read_unlock();
>  
>  	return result;
>  }
> 

I was pretty sure I had already done this one...

Ah yes, that was planned after a bugfix for net-2.6.

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>


^ permalink raw reply

* Re: [RFC PATCH] net: add dataref destructor to sk_buff
From: Gregory Haskins @ 2009-11-10 18:36 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: alacrityvm-devel, herbert.xu, linux-kernel, netdev
In-Reply-To: <20091110173644.GA8888@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1394 bytes --]

Michael S. Tsirkin wrote:
> On Tue, Nov 10, 2009 at 10:45:16AM -0500, Gregory Haskins wrote:
>> I am not a stack expert, but I was under the impression that we use this
>> model for userspace pages today as well using the wmem callbacks in
>> skb->destructor().  If so, I do not see how you could do something like
>> detach a page from a pskb and still expect to have a proper event that
>> delineates the io-completion to the higher layers.
> 
> I think linux only cares about that for accounting purposes (stuff like
> socket sndbuff size). If someone takes over the page, the socket can
> stop worrying about it.

Only if there isn't zero-copy.

> 
>> So the questions are:
>>
>> 1) do we in fact map userspace pages to pskbs today?
> 
> I don't think so.

What about things like sendfile()?  There has to be *some* way to
synchronize with the io-completion event,  I would think.  Whatever that
is, I'd like to tap into it.

>>> which pages?
>>
>> You said that there are paths that get_page() out of shinfo without
>> holding a shinfo reference.
> 
> Without zero copy, application does not care about these,
> they have been allocated by kernel.

Agreed in the non-zero copy case.  I am not yet convinced that we do not
do zero copy in some form, however. Ill have to dig through the code
when I get a chance to confirm.

Kind Regards,
-Greg




[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]

^ permalink raw reply

* Re: sunrpc port allocation and IANA reserved list
From: Chris Friesen @ 2009-11-10 18:37 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, Linux kernel
In-Reply-To: <1257875623.2834.19.camel@achroite.uk.solarflarecom.com>

On 11/10/2009 11:53 AM, Ben Hutchings wrote:
> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:

>> Given that a userspace application can be stopped and restarted at any
>> time, and a sunrpc registration can happen at any time, what is the
>> expected mechanism to prevent the kernel from allocating a port for use
>> by sunrpc that reserved or well-known?
>>
>> Apparently Redhat and Debian have distro-specific ways of dealing with
>> this, but is there a standard solution?  Should there be?
>>
>> The current setup seems suboptimal.
> 
> I believe both RH and Debian are using the same implementation:
> <http://cyberelk.net/tim/software/portreserve/>.

That helps with the startup case, but still leaves a possible hole if an
app using a fixed port number is restarted at runtime.  During the
window where nobody is bound to the port, the kernel could randomly
assign it to someone else.

Chris

^ permalink raw reply

* Re: [PATCH 00/10] netdev: get rid of read_lock(&dev_base_lock) usages
From: Eric Dumazet @ 2009-11-10 18:39 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20091110102442.733c22bc@nehalam>

Stephen Hemminger a écrit :
> I was just trying to pick up the stragglers you left behind :-)
> 
> The nasty cases left are bonding (whose existing locking model is a pile
> of crap), and sysfs (slightly less stinky). The bonding code just needs to
> be rewritten to have a sane/simple model. 
> 

I was thinking of improving bonding, so it might be good to coordinate our work :)

1) Get rid of rwlock in tx fast path. (RCU ? did I said RCU)

2) multi queue support (Got two dual 82599 dual ports cards from Intel :) )


^ permalink raw reply

* Re: [PATCH 06/10] s390: use RCU to walk list of network devices
From: Eric Dumazet @ 2009-11-10 18:40 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Martin Schwidefsky, Heiko Carstens, netdev,
	linux390
In-Reply-To: <20091110175647.547660685@vyatta.com>

Stephen Hemminger a écrit :
> This is similar to other cases where for_each_netdev_rcu
> can be used when gathering information.
> 
> By inspection, don't have platform or cross-build environment
> to validate.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> 

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>


^ permalink raw reply

* [PATCH] ixgbe: Fixing EEH handler to handle more than one error
From: leitao @ 2009-11-10 18:37 UTC (permalink / raw)
  To: netdev; +Cc: peter.p.waskiewicz.jr, jeffrey.t.kirsher, Breno Leitao

After commmit 4b77b0a2ba27d64f58f16d8d4d48d8319dda36ff EEH breaks
after the second error, since it calls pci_restore_state()
but it returns 0, since pci->state_saved is false.

So, this patch just call pci_save_state() after pci_restore_state().

Signed-off-by: Breno Leitao <leitao@linux.vnet.ibm.com>
---
 drivers/net/ixgbe/ixgbe_main.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 5bd9e6b..a5036f7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5994,6 +5994,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
 	} else {
 		pci_set_master(pdev);
 		pci_restore_state(pdev);
+		pci_save_state(pdev);
 
 		pci_wake_from_d3(pdev, false);
 
-- 
1.6.0.2


^ permalink raw reply related

* Re: [PATCH 07/10] decnet: use RCU to find network devices
From: Eric Dumazet @ 2009-11-10 18:43 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Christine Caulfield, Hannes Eder, Alexey Dobriyan,
	Steven Whitehouse, netdev, linux-decnet-users
In-Reply-To: <20091110175647.615305929@vyatta.com>

Stephen Hemminger a écrit :
> When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> Compile tested only.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
>  	dev = dn_dev_get_default();
>  last_chance:
>  	if (dev) {
> -		read_lock(&dev_base_lock);
>  		rv = dn_dev_get_first(dev, addr);
> -		read_unlock(&dev_base_lock);
>  		dev_put(dev);
>  		if (rv == 0 || dev == init_net.loopback_dev)
>  			return rv;
> @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d


I dont understand this part. Why previous locking can be avoided ?

^ permalink raw reply

* Re: [PATCH] support static-only systems
From: Stephen Hemminger @ 2009-11-10 18:45 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: stephen.hemminger, netdev
In-Reply-To: <1257505762-13819-1-git-send-email-vapier@gentoo.org>

On Fri,  6 Nov 2009 06:09:22 -0500
Mike Frysinger <vapier@gentoo.org> wrote:

> The iptables code supports a "no shared libs" mode where it can be used
> without requiring dlfcn related functionality.  This adds similar support
> to iproute2 so that it can easily be used on systems like nommu Linux (but
> obviously with a few limitations -- no dynamic plugins).
> 
> Rather than modify every location that uses dlfcn.h, I hooked the dlfcn.h
> header with stub functions when shared library support is disabled.  Then
> symbol lookup is done via a local static lookup table (which is generated
> automatically at build time) so that internal symbols can be found.
> 
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> ---

Both applied thanks.


-- 

^ permalink raw reply

* Re: [PATCH 09/10] IPV4: use rcu to walk list of devices in IGMP
From: Eric Dumazet @ 2009-11-10 18:47 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20091110175647.754389168@vyatta.com>

Stephen Hemminger a écrit :
> This also needs to be optimized for large number of devices.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>  

>  static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
> +	__releases(rcu)

Minor note : we usually use RCU instead of rcu, but it doesnt really matter.

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>


^ permalink raw reply

* [PATCH 2/4] [RFC] Add c/r support for connected INET sockets (v4)
From: Dan Smith @ 2009-11-10 18:47 UTC (permalink / raw)
  To: containers; +Cc: netdev
In-Reply-To: <1257878856-25520-1-git-send-email-danms@us.ibm.com>

This patch adds basic support for C/R of open INET sockets.  I think that
all the important bits of the TCP and ICSK socket structures is saved,
but I think there is still some additional IPv6 stuff that needs to be
handled.

With this patch applied, the following script can be used to demonstrate
the functionality:

  https://lists.linux-foundation.org/pipermail/containers/2009-October/021239.html

It shows that this enables migration of a sendmail process with open
connections from one machine to another without dropping.

We probably need comments from the netdev people about the quality of
sanity checking we do on the values in the ckpt_hdr_socket_inet
structure on restart.

Note that this still doesn't address lingering sockets yet.

Changes in v4:
 - Use the new socket buffer restore functions introduced in the
   previous patch
 - Move listen_sockets list under the restart items in ckpt_ctx
 - Rename RESTART_SOCK_LISTENONLY to RESTART_CONN_RESET

Changes in v3:
 - Prevent restart from allowing a bind on a <1024 port unless the
   user is granted that capability
 - Add some sanity checking in the inet_precheck() function to make sure
   the values read from the checkpoint image are within acceptable ranges
 - Check the result of sock_restore_header_info() and fail if needed

Changes in v2:
 - Restore saddr, rcv_saddr, daddr, sport, and dport from the sockaddr
   structure instead of saving them separately
 - Fix 'sock' naming in sock_cptrst()
 - Don't take the queue lock before skb_queue_tail() since it is
   done for us
 - Allow "listen only" restore behavior if RESTART_SOCK_LISTENONLY
   flag is specified on sys_restart()
 - Pull the implementation of the list of listening sockets back into
   this patch
 - Fix dangling printk
 - Add some comments around the parent/child restore logic

Cc: netdev@vger.kernel.org
Acked-by: Oren Laadan <orenl@librato.com>
Signed-off-by: Dan Smith <danms@us.ibm.com>
---
 checkpoint/sys.c                 |    4 +
 include/linux/checkpoint.h       |    5 +-
 include/linux/checkpoint_hdr.h   |   95 +++++++++
 include/linux/checkpoint_types.h |    1 +
 net/checkpoint.c                 |   27 ++--
 net/ipv4/checkpoint.c            |  391 ++++++++++++++++++++++++++++++++++----
 6 files changed, 473 insertions(+), 50 deletions(-)

diff --git a/checkpoint/sys.c b/checkpoint/sys.c
index 260a1ee..df00973 100644
--- a/checkpoint/sys.c
+++ b/checkpoint/sys.c
@@ -221,6 +221,8 @@ static void ckpt_ctx_free(struct ckpt_ctx *ctx)
 
 	kfree(ctx->pids_arr);
 
+	sock_listening_list_free(&ctx->listen_sockets);
+
 	kfree(ctx);
 }
 
@@ -249,6 +251,8 @@ static struct ckpt_ctx *ckpt_ctx_alloc(int fd, unsigned long uflags,
 	spin_lock_init(&ctx->lock);
 #endif
 
+	INIT_LIST_HEAD(&ctx->listen_sockets);
+
 	err = -EBADF;
 	ctx->file = fget(fd);
 	if (!ctx->file)
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
index 3e73e68..d4765f6 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -19,6 +19,7 @@
 #define RESTART_TASKSELF	0x1
 #define RESTART_FROZEN		0x2
 #define RESTART_GHOST		0x4
+#define RESTART_CONN_RESET	0x8
 
 #ifdef __KERNEL__
 #ifdef CONFIG_CHECKPOINT
@@ -48,7 +49,8 @@
 #define RESTART_USER_FLAGS  \
 	(RESTART_TASKSELF | \
 	 RESTART_FROZEN | \
-	 RESTART_GHOST)
+	 RESTART_GHOST | \
+	 RESTART_CONN_RESET)
 
 extern int walk_task_subtree(struct task_struct *task,
 			     int (*func)(struct task_struct *, void *),
@@ -101,6 +103,7 @@ extern int ckpt_sock_getnames(struct ckpt_ctx *ctx,
 			      struct sockaddr *loc, unsigned *loc_len,
 			      struct sockaddr *rem, unsigned *rem_len);
 struct sk_buff *sock_restore_skb(struct ckpt_ctx *ctx);
+void sock_listening_list_free(struct list_head *head);
 
 /* ckpt kflags */
 #define ckpt_set_ctx_kflag(__ctx, __kflag)  \
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index ace4139..7c81f93 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -20,6 +20,7 @@
 #include <linux/socket.h>
 #include <linux/un.h>
 #include <linux/in.h>
+#include <linux/in6.h>
 #else
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -592,6 +593,100 @@ struct ckpt_hdr_socket_unix {
 
 struct ckpt_hdr_socket_inet {
 	struct ckpt_hdr h;
+	__u32 daddr;
+	__u32 rcv_saddr;
+	__u32 saddr;
+	__u16 dport;
+	__u16 num;
+	__u16 sport;
+	__s16 uc_ttl;
+	__u16 cmsg_flags;
+
+	struct {
+		__u64 timeout;
+		__u32 ato;
+		__u32 lrcvtime;
+		__u16 last_seg_size;
+		__u16 rcv_mss;
+		__u8 pending;
+		__u8 quick;
+		__u8 pingpong;
+		__u8 blocked;
+	} icsk_ack __attribute__ ((aligned(8)));
+
+	/* FIXME: Skipped opt, tos, multicast, cork settings */
+
+	struct {
+		__u32 rcv_nxt;
+		__u32 copied_seq;
+		__u32 rcv_wup;
+		__u32 snd_nxt;
+		__u32 snd_una;
+		__u32 snd_sml;
+		__u32 rcv_tstamp;
+		__u32 lsndtime;
+
+		__u32 snd_wl1;
+		__u32 snd_wnd;
+		__u32 max_window;
+		__u32 mss_cache;
+		__u32 window_clamp;
+		__u32 rcv_ssthresh;
+		__u32 frto_highmark;
+
+		__u32 srtt;
+		__u32 mdev;
+		__u32 mdev_max;
+		__u32 rttvar;
+		__u32 rtt_seq;
+
+		__u32 packets_out;
+		__u32 retrans_out;
+
+		__u32 snd_up;
+		__u32 rcv_wnd;
+		__u32 write_seq;
+		__u32 pushed_seq;
+		__u32 lost_out;
+		__u32 sacked_out;
+		__u32 fackets_out;
+		__u32 tso_deferred;
+		__u32 bytes_acked;
+
+		__s32 lost_cnt_hint;
+		__u32 retransmit_high;
+
+		__u32 lost_retrans_low;
+
+		__u32 prior_ssthresh;
+		__u32 high_seq;
+
+		__u32 retrans_stamp;
+		__u32 undo_marker;
+		__s32 undo_retrans;
+		__u32 total_retrans;
+
+		__u32 urg_seq;
+		__u32 keepalive_time;
+		__u32 keepalive_intvl;
+
+		__u16 urg_data;
+		__u16 advmss;
+		__u8 frto_counter;
+		__u8 nonagle;
+
+		__u8 ecn_flags;
+		__u8 reordering;
+
+		__u8 keepalive_probes;
+	} tcp __attribute__ ((aligned(8)));
+
+	struct {
+		struct in6_addr saddr;
+		struct in6_addr rcv_saddr;
+		struct in6_addr daddr;
+	} inet6 __attribute__ ((aligned(8)));
+
 	__u32 laddr_len;
 	__u32 raddr_len;
 	struct sockaddr_in laddr;
diff --git a/include/linux/checkpoint_types.h b/include/linux/checkpoint_types.h
index 5cc11d9..eac0d5a 100644
--- a/include/linux/checkpoint_types.h
+++ b/include/linux/checkpoint_types.h
@@ -78,6 +78,7 @@ struct ckpt_ctx {
 	wait_queue_head_t waitq;	/* waitqueue for restarting tasks */
 	wait_queue_head_t ghostq;	/* waitqueue for ghost tasks */
 	struct cred *realcred, *ecred;	/* tmp storage for cred at restart */
+	struct list_head listen_sockets;/* listening parent sockets */
 
 	struct ckpt_stats stats;	/* statistics */
 
diff --git a/net/checkpoint.c b/net/checkpoint.c
index 00365b2..32ccaba 100644
--- a/net/checkpoint.c
+++ b/net/checkpoint.c
@@ -319,6 +319,7 @@ static int __sock_write_skb(struct ckpt_ctx *ctx,
 
 static int __sock_write_buffers(struct ckpt_ctx *ctx,
 				struct sk_buff_head *queue,
+				uint16_t family,
 				int dst_objref)
 {
 	struct sk_buff *skb;
@@ -331,11 +332,11 @@ static int __sock_write_buffers(struct ckpt_ctx *ctx,
 			return -EBUSY;
 		}
 
-		/* The other ancillary messages are always present
-		 * unlike descriptors.  Even though we can't detect
-		 * them and fail the checkpoint, we're not at risk
-		 * because we don't save out (or restore) the control
-		 * information contained in the skb.
+		/* The other ancillary messages UNIX are always
+		 * present unlike descriptors.  Even though we can't
+		 * detect them and fail the checkpoint, we're not at
+		 * risk because we don't restore the control
+		 * information in the UNIX code.
 		 */
 
 		ret = __sock_write_skb(ctx, skb, dst_objref);
@@ -348,6 +349,7 @@ static int __sock_write_buffers(struct ckpt_ctx *ctx,
 
 static int sock_write_buffers(struct ckpt_ctx *ctx,
 			      struct sk_buff_head *queue,
+			      uint16_t family,
 			      int dst_objref)
 {
 	struct ckpt_hdr_socket_queue *h;
@@ -367,7 +369,7 @@ static int sock_write_buffers(struct ckpt_ctx *ctx,
 	h->skb_count = ret;
 	ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
 	if (!ret)
-		ret = __sock_write_buffers(ctx, &tmpq, dst_objref);
+		ret = __sock_write_buffers(ctx, &tmpq, family, dst_objref);
 
  out:
 	ckpt_hdr_put(ctx, h);
@@ -389,12 +391,14 @@ int sock_deferred_write_buffers(void *data)
 		return dst_objref;
 	}
 
-	ret = sock_write_buffers(ctx, &dq->sk->sk_receive_queue, dst_objref);
+	ret = sock_write_buffers(ctx, &dq->sk->sk_receive_queue,
+				 dq->sk->sk_family, dst_objref);
 	ckpt_debug("write recv buffers: %i\n", ret);
 	if (ret < 0)
 		return ret;
 
-	ret = sock_write_buffers(ctx, &dq->sk->sk_write_queue, dst_objref);
+	ret = sock_write_buffers(ctx, &dq->sk->sk_write_queue,
+				 dq->sk->sk_family, dst_objref);
 	ckpt_debug("write send buffers: %i\n", ret);
 
 	return ret;
@@ -919,10 +923,9 @@ struct sock *do_sock_restore(struct ckpt_ctx *ctx)
 		goto err;
 
 	if ((h->sock_common.family == AF_INET) &&
-	    (h->sock.state != TCP_LISTEN)) {
-		/* Temporary hack to enable restore of TCP_LISTEN sockets
-		 * while forcing anything else to a closed state
-		 */
+	    (h->sock.state != TCP_LISTEN) &&
+	    (ctx->uflags & RESTART_CONN_RESET)) {
+		ckpt_debug("Forcing open socket closed\n");
 		sock->sk->sk_state = TCP_CLOSE;
 		sock->state = SS_UNCONNECTED;
 	}
diff --git a/net/ipv4/checkpoint.c b/net/ipv4/checkpoint.c
index 9cbbf5e..ee41633 100644
--- a/net/ipv4/checkpoint.c
+++ b/net/ipv4/checkpoint.c
@@ -17,6 +17,7 @@
 #include <linux/deferqueue.h>
 #include <net/tcp_states.h>
 #include <net/tcp.h>
+#include <net/ipv6.h>
 
 struct dq_sock {
 	struct ckpt_ctx *ctx;
@@ -28,6 +29,236 @@ struct dq_buffers {
 	struct sock *sk;
 };
 
+struct listen_item {
+	struct sock *sk;
+	struct list_head list;
+};
+
+void sock_listening_list_free(struct list_head *head)
+{
+	struct listen_item *item, *tmp;
+
+	list_for_each_entry_safe(item, tmp, head, list) {
+		list_del(&item->list);
+		kfree(item);
+	}
+}
+
+static int sock_listening_list_add(struct ckpt_ctx *ctx, struct sock *sk)
+{
+	struct listen_item *item;
+
+	item = kmalloc(sizeof(*item), GFP_KERNEL);
+	if (!item)
+		return -ENOMEM;
+
+	item->sk = sk;
+	list_add(&item->list, &ctx->listen_sockets);
+
+	return 0;
+}
+
+static struct sock *sock_get_parent(struct ckpt_ctx *ctx, struct sock *sk)
+{
+	struct listen_item *item;
+
+	list_for_each_entry(item, &ctx->listen_sockets, list) {
+		if (inet_sk(sk)->sport == inet_sk(item->sk)->sport)
+			return item->sk;
+	}
+
+	return NULL;
+}
+
+static int sock_hash_parent(void *data)
+{
+	struct dq_sock *dq = (struct dq_sock *)data;
+	struct sock *parent;
+
+	ckpt_debug("INET post-restart hash\n");
+
+	dq->sk->sk_prot->hash(dq->sk);
+
+	/* If there is a listening socket with the same source port,
+	 * then become a child of that socket [we are the result of an
+	 * accept()].  Otherwise hash ourselves directly in [we are
+	 * the result of a connect()]
+	 */
+
+	parent = sock_get_parent(dq->ctx, dq->sk);
+	if (parent) {
+		inet_sk(dq->sk)->num = ntohs(inet_sk(dq->sk)->sport);
+		local_bh_disable();
+		__inet_inherit_port(parent, dq->sk);
+		local_bh_enable();
+	} else {
+		inet_sk(dq->sk)->num = 0;
+		inet_hash_connect(&tcp_death_row, dq->sk);
+		inet_sk(dq->sk)->num = ntohs(inet_sk(dq->sk)->sport);
+	}
+
+	return 0;
+}
+
+static int sock_defer_hash(struct ckpt_ctx *ctx, struct sock *sock)
+{
+	struct dq_sock dq;
+
+	dq.sk = sock;
+	dq.ctx = ctx;
+
+	return deferqueue_add(ctx->deferqueue, &dq, sizeof(dq),
+			      sock_hash_parent, NULL);
+}
+
+static int sock_inet_tcp_cptrst(struct ckpt_ctx *ctx,
+				struct tcp_sock *sk,
+				struct ckpt_hdr_socket_inet *hh,
+				int op)
+{
+	CKPT_COPY(op, hh->tcp.rcv_nxt, sk->rcv_nxt);
+	CKPT_COPY(op, hh->tcp.copied_seq, sk->copied_seq);
+	CKPT_COPY(op, hh->tcp.rcv_wup, sk->rcv_wup);
+	CKPT_COPY(op, hh->tcp.snd_nxt, sk->snd_nxt);
+	CKPT_COPY(op, hh->tcp.snd_una, sk->snd_una);
+	CKPT_COPY(op, hh->tcp.snd_sml, sk->snd_sml);
+	CKPT_COPY(op, hh->tcp.rcv_tstamp, sk->rcv_tstamp);
+	CKPT_COPY(op, hh->tcp.lsndtime, sk->lsndtime);
+
+	CKPT_COPY(op, hh->tcp.snd_wl1, sk->snd_wl1);
+	CKPT_COPY(op, hh->tcp.snd_wnd, sk->snd_wnd);
+	CKPT_COPY(op, hh->tcp.max_window, sk->max_window);
+	CKPT_COPY(op, hh->tcp.mss_cache, sk->mss_cache);
+	CKPT_COPY(op, hh->tcp.window_clamp, sk->window_clamp);
+	CKPT_COPY(op, hh->tcp.rcv_ssthresh, sk->rcv_ssthresh);
+	CKPT_COPY(op, hh->tcp.frto_highmark, sk->frto_highmark);
+	CKPT_COPY(op, hh->tcp.advmss, sk->advmss);
+	CKPT_COPY(op, hh->tcp.frto_counter, sk->frto_counter);
+	CKPT_COPY(op, hh->tcp.nonagle, sk->nonagle);
+
+	CKPT_COPY(op, hh->tcp.srtt, sk->srtt);
+	CKPT_COPY(op, hh->tcp.mdev, sk->mdev);
+	CKPT_COPY(op, hh->tcp.mdev_max, sk->mdev_max);
+	CKPT_COPY(op, hh->tcp.rttvar, sk->rttvar);
+	CKPT_COPY(op, hh->tcp.rtt_seq, sk->rtt_seq);
+
+	CKPT_COPY(op, hh->tcp.packets_out, sk->packets_out);
+	CKPT_COPY(op, hh->tcp.retrans_out, sk->retrans_out);
+
+	CKPT_COPY(op, hh->tcp.urg_data, sk->urg_data);
+	CKPT_COPY(op, hh->tcp.ecn_flags, sk->ecn_flags);
+	CKPT_COPY(op, hh->tcp.reordering, sk->reordering);
+	CKPT_COPY(op, hh->tcp.snd_up, sk->snd_up);
+
+	CKPT_COPY(op, hh->tcp.keepalive_probes, sk->keepalive_probes);
+
+	CKPT_COPY(op, hh->tcp.rcv_wnd, sk->rcv_wnd);
+	CKPT_COPY(op, hh->tcp.write_seq, sk->write_seq);
+	CKPT_COPY(op, hh->tcp.pushed_seq, sk->pushed_seq);
+	CKPT_COPY(op, hh->tcp.lost_out, sk->lost_out);
+	CKPT_COPY(op, hh->tcp.sacked_out, sk->sacked_out);
+	CKPT_COPY(op, hh->tcp.fackets_out, sk->fackets_out);
+	CKPT_COPY(op, hh->tcp.tso_deferred, sk->tso_deferred);
+	CKPT_COPY(op, hh->tcp.bytes_acked, sk->bytes_acked);
+
+	CKPT_COPY(op, hh->tcp.lost_cnt_hint, sk->lost_cnt_hint);
+	CKPT_COPY(op, hh->tcp.retransmit_high, sk->retransmit_high);
+
+	CKPT_COPY(op, hh->tcp.lost_retrans_low, sk->lost_retrans_low);
+
+	CKPT_COPY(op, hh->tcp.prior_ssthresh, sk->prior_ssthresh);
+	CKPT_COPY(op, hh->tcp.high_seq, sk->high_seq);
+
+	CKPT_COPY(op, hh->tcp.retrans_stamp, sk->retrans_stamp);
+	CKPT_COPY(op, hh->tcp.undo_marker, sk->undo_marker);
+	CKPT_COPY(op, hh->tcp.undo_retrans, sk->undo_retrans);
+	CKPT_COPY(op, hh->tcp.total_retrans, sk->total_retrans);
+
+	CKPT_COPY(op, hh->tcp.urg_seq, sk->urg_seq);
+	CKPT_COPY(op, hh->tcp.keepalive_time, sk->keepalive_time);
+	CKPT_COPY(op, hh->tcp.keepalive_intvl, sk->keepalive_intvl);
+
+	if (!skb_queue_empty(&sk->ucopy.prequeue))
+		printk("PREQUEUE!\n");
+
+	return 0;
+}
+
+static int sock_inet_restore_addrs(struct inet_sock *inet,
+				   struct ckpt_hdr_socket_inet *hh)
+{
+	inet->daddr = hh->raddr.sin_addr.s_addr;
+	inet->saddr = hh->laddr.sin_addr.s_addr;
+	inet->rcv_saddr = inet->saddr;
+
+	inet->dport = hh->raddr.sin_port;
+	inet->sport = hh->laddr.sin_port;
+
+	return 0;
+}
+
+static int sock_inet_cptrst(struct ckpt_ctx *ctx,
+			    struct sock *sk,
+			    struct ckpt_hdr_socket_inet *hh,
+			    int op)
+{
+	struct inet_sock *inet = inet_sk(sk);
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	int ret;
+
+	if (op == CKPT_CPT) {
+		CKPT_COPY(op, hh->daddr, inet->daddr);
+		CKPT_COPY(op, hh->rcv_saddr, inet->rcv_saddr);
+		CKPT_COPY(op, hh->dport, inet->dport);
+		CKPT_COPY(op, hh->saddr, inet->saddr);
+		CKPT_COPY(op, hh->sport, inet->sport);
+	} else {
+		ret = sock_inet_restore_addrs(inet, hh);
+		if (ret)
+			return ret;
+	}
+
+	CKPT_COPY(op, hh->num, inet->num);
+	CKPT_COPY(op, hh->uc_ttl, inet->uc_ttl);
+	CKPT_COPY(op, hh->cmsg_flags, inet->cmsg_flags);
+
+	CKPT_COPY(op, hh->icsk_ack.pending, icsk->icsk_ack.pending);
+	CKPT_COPY(op, hh->icsk_ack.quick, icsk->icsk_ack.quick);
+	CKPT_COPY(op, hh->icsk_ack.pingpong, icsk->icsk_ack.pingpong);
+	CKPT_COPY(op, hh->icsk_ack.blocked, icsk->icsk_ack.blocked);
+	CKPT_COPY(op, hh->icsk_ack.ato, icsk->icsk_ack.ato);
+	CKPT_COPY(op, hh->icsk_ack.timeout, icsk->icsk_ack.timeout);
+	CKPT_COPY(op, hh->icsk_ack.lrcvtime, icsk->icsk_ack.lrcvtime);
+	CKPT_COPY(op,
+		  hh->icsk_ack.last_seg_size, icsk->icsk_ack.last_seg_size);
+	CKPT_COPY(op, hh->icsk_ack.rcv_mss, icsk->icsk_ack.rcv_mss);
+
+	if (sk->sk_protocol == IPPROTO_TCP)
+		ret = sock_inet_tcp_cptrst(ctx, tcp_sk(sk), hh, op);
+	else if (sk->sk_protocol == IPPROTO_UDP)
+		ret = 0;
+	else {
+		ckpt_write_err(ctx, "T", "unknown socket protocol %d",
+			       sk->sk_protocol);
+		ret = -EINVAL;
+	}
+
+	if (sk->sk_family == AF_INET6) {
+		struct ipv6_pinfo *inet6 = inet6_sk(sk);
+		if (op == CKPT_CPT) {
+			ipv6_addr_copy(&hh->inet6.saddr, &inet6->saddr);
+			ipv6_addr_copy(&hh->inet6.rcv_saddr, &inet6->rcv_saddr);
+			ipv6_addr_copy(&hh->inet6.daddr, &inet6->daddr);
+		} else {
+			ipv6_addr_copy(&inet6->saddr, &hh->inet6.saddr);
+			ipv6_addr_copy(&inet6->rcv_saddr, &hh->inet6.rcv_saddr);
+			ipv6_addr_copy(&inet6->daddr, &hh->inet6.daddr);
+		}
+	}
+
+	return ret;
+}
+
 int inet_checkpoint(struct ckpt_ctx *ctx, struct socket *sock)
 {
 	struct ckpt_hdr_socket_inet *in;
@@ -43,6 +274,10 @@ int inet_checkpoint(struct ckpt_ctx *ctx, struct socket *sock)
 	if (ret)
 		goto out;
 
+	ret = sock_inet_cptrst(ctx, sock->sk, in, CKPT_CPT);
+	if (ret < 0)
+		goto out;
+
 	ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) in);
  out:
 	ckpt_hdr_put(ctx, in);
@@ -55,51 +290,22 @@ int inet_collect(struct ckpt_ctx *ctx, struct socket *sock)
 	return ckpt_obj_collect(ctx, sock->sk, CKPT_OBJ_SOCK);
 }
 
-static int inet_read_buffer(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
+static int inet_read_buffer(struct ckpt_ctx *ctx,
+			    struct sk_buff_head *queue)
 {
-	struct ckpt_hdr_socket_buffer *h;
-	int len;
-	int ret;
 	struct sk_buff *skb = NULL;
 
-	h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_BUFFER);
-	if (IS_ERR(h))
-		return PTR_ERR(h);
-
-	len = _ckpt_read_obj_type(ctx, NULL, 0, CKPT_HDR_BUFFER);
-	if (len < 0) {
-		ret = len;
-		goto out;
-	} else if (len > SKB_MAX_ALLOC) {
-		ckpt_debug("Socket buffer too big (%i > %lu)",
-			   len, SKB_MAX_ALLOC);
-		ret = -ENOSPC;
-		goto out;
-	}
-
-	skb = alloc_skb(len, GFP_KERNEL);
-	if (!skb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = ckpt_kread(ctx, skb_put(skb, len), len);
-	if (ret < 0)
-		goto out;
+	skb = sock_restore_skb(ctx);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
 
-	spin_lock(&queue->lock);
 	skb_queue_tail(queue, skb);
-	spin_unlock(&queue->lock);
- out:
-	ckpt_hdr_put(ctx, h);
-
-	if ((ret < 0) && skb)
-		kfree_skb(skb);
 
-	return ret;
+	return skb->len;
 }
 
-static int inet_read_buffers(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
+static int inet_read_buffers(struct ckpt_ctx *ctx,
+			     struct sk_buff_head *queue)
 {
 	struct ckpt_hdr_socket_queue *h;
 	int ret = 0;
@@ -162,6 +368,19 @@ static int inet_defer_restore_buffers(struct ckpt_ctx *ctx, struct sock *sk)
 
 static int inet_precheck(struct socket *sock, struct ckpt_hdr_socket_inet *in)
 {
+	__u8 icsk_ack_mask = ICSK_ACK_SCHED | ICSK_ACK_TIMER |
+		ICSK_ACK_PUSHED | ICSK_ACK_PUSHED2;
+	__u16 urg_mask = TCP_URG_VALID | TCP_URG_NOTYET | TCP_URG_READ;
+	__u8 nonagle_mask = TCP_NAGLE_OFF | TCP_NAGLE_CORK | TCP_NAGLE_PUSH;
+	__u8 ecn_mask = TCP_ECN_OK | TCP_ECN_QUEUE_CWR | TCP_ECN_DEMAND_CWR;
+
+	if ((htons(in->laddr.sin_port) < PROT_SOCK) &&
+	    !capable(CAP_NET_BIND_SERVICE)) {
+		ckpt_debug("unable to bind to port %hu\n",
+			   htons(in->laddr.sin_port));
+		return -EINVAL;
+	}
+
 	if (in->laddr_len > sizeof(struct sockaddr_in)) {
 		ckpt_debug("laddr_len is too big\n");
 		return -EINVAL;
@@ -172,6 +391,77 @@ static int inet_precheck(struct socket *sock, struct ckpt_hdr_socket_inet *in)
 		return -EINVAL;
 	}
 
+	/* Set ato to the default */
+	in->icsk_ack.ato = TCP_ATO_MIN;
+
+	/* No quick acks are scheduled after a restart */
+	in->icsk_ack.quick = 0;
+
+	if (in->icsk_ack.pending & ~icsk_ack_mask) {
+		ckpt_debug("invalid pending flags 0x%x\n",
+			   in->icsk_ack.pending & ~icsk_ack_mask);
+		return -EINVAL;
+	}
+
+	if (in->icsk_ack.pingpong > 1) {
+		ckpt_debug("invalid icsk_ack.pingpong value\n");
+		return -EINVAL;
+	}
+
+	if (in->icsk_ack.blocked > 1) {
+		ckpt_debug("invalid icsk_ack.blocked value\n");
+		return -EINVAL;
+	}
+
+	/* do_tcp_setsockopt() quietly makes this coercion */
+	if (in->tcp.window_clamp < (SOCK_MIN_RCVBUF / 2))
+		in->tcp.window_clamp = SOCK_MIN_RCVBUF / 2;
+	else if (in->tcp.window_clamp > 65535U) {
+		ckpt_debug("invalid window_clamp value\n");
+		return -EINVAL;
+	}
+
+	if (in->tcp.rcv_ssthresh > (4U * in->tcp.advmss))
+		in->tcp.rcv_ssthresh = 4U * in->tcp.advmss;
+
+	/* These will all be recalculated on the next call to
+	 * tcp_rtt_estimator()
+	 */
+	in->tcp.srtt = in->tcp.mdev = in->tcp.mdev_max = 0;
+	in->tcp.rttvar = in->tcp.rtt_seq = 0;
+
+	/* Might want to set packets_out to zero ? */
+
+	if (in->tcp.rcv_wnd > MAX_TCP_WINDOW)
+		in->tcp.rcv_wnd = MAX_TCP_WINDOW;
+
+	if (in->tcp.keepalive_intvl > MAX_TCP_KEEPINTVL) {
+		ckpt_debug("keepalive_intvl %i out of range\n",
+			   in->tcp.keepalive_intvl);
+		return -EINVAL;
+	}
+
+	if (in->tcp.keepalive_probes > MAX_TCP_KEEPCNT) {
+		ckpt_debug("Invalid keepalive_probes value %i\n",
+			   in->tcp.keepalive_probes);
+		return -EINVAL;
+	}
+
+	if (in->tcp.urg_data & ~urg_mask) {
+		ckpt_debug("Invalid urg_data value\n");
+		return -EINVAL;
+	}
+
+	if (in->tcp.nonagle & ~nonagle_mask) {
+		ckpt_debug("Invalid nonagle value\n");
+		return -EINVAL;
+	}
+
+	if (in->tcp.ecn_flags & ~ecn_mask) {
+		ckpt_debug("Invalid ecn_flags value\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -209,8 +499,35 @@ int inet_restore(struct ckpt_ctx *ctx,
 			ckpt_debug("inet listen: %i\n", ret);
 			if (ret < 0)
 				goto out;
+
+			/* We are a listening socket, so add ourselves
+			 * to the list of parent sockets.  This will
+			 * allow our children to find us later and
+			 * link up
+			 */
+
+			ret = sock_listening_list_add(ctx, sock->sk);
+			if (ret < 0)
+				goto out;
 		}
 	} else {
+		ret = sock_inet_cptrst(ctx, sock->sk, in, CKPT_RST);
+		if (ret)
+			goto out;
+
+		if ((h->sock.state == TCP_ESTABLISHED) &&
+		    (h->sock.protocol == IPPROTO_TCP)) {
+			/* A connected socket that was spawned from an
+			 * accept() needs to be hashed with its parent
+			 * listening socket in order to receive
+			 * traffic on the original port.  Since we may
+			 * not have restarted the parent yet, we defer
+			 * this until later when we know we have all
+			 * the listening sockets accounted for.
+			 */
+			ret = sock_defer_hash(ctx, sock->sk);
+		}
+
 		if (!sock_flag(sock->sk, SOCK_DEAD))
 			ret = inet_defer_restore_buffers(ctx, sock->sk);
 	}
-- 
1.6.3.3


^ permalink raw reply related

* Re: sunrpc port allocation and IANA reserved list
From: Chris Friesen @ 2009-11-10 18:48 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, Linux kernel, twaugh
In-Reply-To: <4AF9B2CF.6050305@nortel.com>

On 11/10/2009 12:37 PM, Chris Friesen wrote:
> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
>> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
> 
>>> Given that a userspace application can be stopped and restarted at any
>>> time, and a sunrpc registration can happen at any time, what is the
>>> expected mechanism to prevent the kernel from allocating a port for use
>>> by sunrpc that reserved or well-known?
>>>
>>> Apparently Redhat and Debian have distro-specific ways of dealing with
>>> this, but is there a standard solution?  Should there be?
>>>
>>> The current setup seems suboptimal.
>>
>> I believe both RH and Debian are using the same implementation:
>> <http://cyberelk.net/tim/software/portreserve/>.
> 
> That helps with the startup case, but still leaves a possible hole if an
> app using a fixed port number is restarted at runtime.  During the
> window where nobody is bound to the port, the kernel could randomly
> assign it to someone else.

After some reflection it seems to me that the only way to close this
race condition is to store the list of reserved ports in the kernel and
simply avoid handing out a reserved address unless it is specifically
requested.

Maybe we could keep the config files of the existing portreserve
package, but rather than maintaining the reservation list itself the
portreserve app would simply feed the reservations into the kernel (via
/proc or netlink or something) at startup.

This would also avoid the need to modify the startup scripts of
applications wanting to use a fixed port.  The config file containing
the port number would still be necessary, however.

Chris

^ permalink raw reply

* Re: [PATCH 07/10] decnet: use RCU to find network devices
From: Stephen Hemminger @ 2009-11-10 18:50 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, Christine Caulfield, Hannes Eder, Alexey Dobriyan,
	Steven Whitehouse, netdev, linux-decnet-users
In-Reply-To: <4AF9B449.6040708@gmail.com>

On Tue, 10 Nov 2009 19:43:21 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> Stephen Hemminger a écrit :
> > When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> > Compile tested only.
> > 
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > 
> > --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> > +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> > @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
> >  	dev = dn_dev_get_default();
> >  last_chance:
> >  	if (dev) {
> > -		read_lock(&dev_base_lock);
> >  		rv = dn_dev_get_first(dev, addr);
> > -		read_unlock(&dev_base_lock);
> >  		dev_put(dev);
> >  		if (rv == 0 || dev == init_net.loopback_dev)
> >  			return rv;
> > @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
> 
> 
> I dont understand this part. Why previous locking can be avoided ?

dn_dev_get_default acquires a reference on dev so the device can
not go away.

It could be the original author meant to ensure the address list
doesn't change. If so, then rtnl_lock() should have been used.

^ permalink raw reply

* Re: [PATCH 00/10] netdev: get rid of read_lock(&dev_base_lock) usages
From: Stephen Hemminger @ 2009-11-10 18:53 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <4AF9B358.9030006@gmail.com>

On Tue, 10 Nov 2009 19:39:20 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> Stephen Hemminger a écrit :
> > I was just trying to pick up the stragglers you left behind :-)
> > 
> > The nasty cases left are bonding (whose existing locking model is a pile
> > of crap), and sysfs (slightly less stinky). The bonding code just needs to
> > be rewritten to have a sane/simple model. 
> > 
> 
> I was thinking of improving bonding, so it might be good to coordinate our work :)

I'll be happy to review, but was avoiding doing any serious work on it.

> 
> 1) Get rid of rwlock in tx fast path. (RCU ? did I said RCU)
> 
> 2) multi queue support (Got two dual 82599 dual ports cards from Intel :) )

I hope to get back to doing netlink interface for bridging, then bonding
over next few weeks.

-- 

^ permalink raw reply

* RE: [PATCH] e1000e: Add new ID
From: Allan, Bruce W @ 2009-11-10 18:56 UTC (permalink / raw)
  To: Sven Anders, netdev
In-Reply-To: <4AF87AAF.2020508@anduras.de>

NAK.  While this is indeed a trivial patch to enable a device that is not currently supported in e1000e, this device requires special handling to get the bypass functionality to work properly and as such this patch is insufficient.

>-----Original Message-----
>From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
>On Behalf Of Sven Anders
>Sent: Monday, November 09, 2009 12:25 PM
>To: netdev
>Subject: [PATCH] e1000e: Add new ID
>
>Hello!
>
>We use the the 82571EB (QUAD COPPER BP) with the e1000e driver.
>We haven't experienced any problems yet.
>
>The patch is trivial, just adding a new PCI ID...
>
>Regards
> Sven Anders
>
>--
> Sven Anders <anders@anduras.de>                 () Ascii Ribbon Campaign
>                                                 /\ Support plain text e-
>mail
> ANDURAS service solutions AG
> Innstrasse 71 - 94036 Passau - Germany
> Web: www.anduras.de - Tel: +49 (0)851-4 90 50-0 - Fax: +49 (0)851-4 90
>50-55
>
>Those who would give up essential Liberty, to purchase a little
>temporary Safety, deserve neither Liberty nor Safety.
>  - Benjamin Franklin

^ permalink raw reply

* [PATCH] sctp: Set source addresses on the association before adding transports
From: Vlad Yasevich @ 2009-11-10 18:57 UTC (permalink / raw)
  To: davem; +Cc: netdev, linux-sctp, Vlad Yasevich

Recent commit 8da645e101a8c20c6073efda3c7cc74eec01b87f
	sctp: Get rid of an extra routing lookup when adding a transport
introduced a regression in the connection setup.  The behavior was
different between IPv4 and IPv6.  IPv4 case ended up working because the
route lookup routing returned a NULL route, which triggered another
route lookup later in the output patch that succeeded.  In the IPv6 case,
a valid route was returned for first call, but we could not find a valid
source address at the time since the source addresses were not set on the
association yet.  Thus resulted in a hung connection.

The solution is to set the source addresses on the association prior to
adding peers.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
 include/net/sctp/structs.h |    2 +-
 net/sctp/associola.c       |    4 +---
 net/sctp/sm_statefuns.c    |   15 +++++++++------
 net/sctp/socket.c          |   22 ++++++++++++----------
 4 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6e5f0e0..cd2e187 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1980,7 +1980,7 @@ void sctp_assoc_set_primary(struct sctp_association *,
 void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
 				    struct sctp_transport *);
 int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
-				     gfp_t);
+				     sctp_scope_t, gfp_t);
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
 					 struct sctp_cookie*,
 					 gfp_t gfp);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8450960..7eed77a 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1485,15 +1485,13 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
  * local endpoint and the remote peer.
  */
 int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
-				     gfp_t gfp)
+				     sctp_scope_t scope, gfp_t gfp)
 {
-	sctp_scope_t scope;
 	int flags;
 
 	/* Use scoping rules to determine the subset of addresses from
 	 * the endpoint.
 	 */
-	scope = sctp_scope(&asoc->peer.active_path->ipaddr);
 	flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
 	if (asoc->peer.ipv4_address)
 		flags |= SCTP_ADDR4_PEERSUPP;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index c8fae19..d4df450 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -384,6 +384,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
 	if (!new_asoc)
 		goto nomem;
 
+	if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
+					     sctp_scope(sctp_source(chunk)),
+					     GFP_ATOMIC) < 0)
+		goto nomem_init;
+
 	/* The call, sctp_process_init(), can fail on memory allocation.  */
 	if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,
 			       sctp_source(chunk),
@@ -401,9 +406,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
 		len = ntohs(err_chunk->chunk_hdr->length) -
 			sizeof(sctp_chunkhdr_t);
 
-	if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
-		goto nomem_init;
-
 	repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
 	if (!repl)
 		goto nomem_init;
@@ -1452,6 +1454,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
 	if (!new_asoc)
 		goto nomem;
 
+	if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
+				sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0)
+		goto nomem;
+
 	/* In the outbound INIT ACK the endpoint MUST copy its current
 	 * Verification Tag and Peers Verification tag into a reserved
 	 * place (local tie-tag and per tie-tag) within the state cookie.
@@ -1488,9 +1494,6 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
 			sizeof(sctp_chunkhdr_t);
 	}
 
-	if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
-		goto nomem;
-
 	repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
 	if (!repl)
 		goto nomem;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c8d0575..bf705ba 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1080,6 +1080,13 @@ static int __sctp_connect(struct sock* sk,
 				err = -ENOMEM;
 				goto out_free;
 			}
+
+			err = sctp_assoc_set_bind_addr_from_ep(asoc, scope,
+							      GFP_KERNEL);
+			if (err < 0) {
+				goto out_free;
+			}
+
 		}
 
 		/* Prime the peer's transport structures.  */
@@ -1095,11 +1102,6 @@ static int __sctp_connect(struct sock* sk,
 		walk_size += af->sockaddr_len;
 	}
 
-	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
-	if (err < 0) {
-		goto out_free;
-	}
-
 	/* In case the user of sctp_connectx() wants an association
 	 * id back, assign one now.
 	 */
@@ -1689,6 +1691,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 			goto out_unlock;
 		}
 		asoc = new_asoc;
+		err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL);
+		if (err < 0) {
+			err = -ENOMEM;
+			goto out_free;
+		}
 
 		/* If the SCTP_INIT ancillary data is specified, set all
 		 * the association init values accordingly.
@@ -1718,11 +1725,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 			err = -ENOMEM;
 			goto out_free;
 		}
-		err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
-		if (err < 0) {
-			err = -ENOMEM;
-			goto out_free;
-		}
 	}
 
 	/* ASSERT: we have a valid association at this point.  */
-- 
1.6.0.4


^ permalink raw reply related

* More info on SO_TIMESTAMPING problems in V6
From: Marcus D. Leech @ 2009-11-10 19:03 UTC (permalink / raw)
  To: netdev; +Cc: patrick.ohly

It looks like there *isn't* support on the V6 side for SO_TIMESTAMPING.

The ipv6/udp.c  calls the V4 udp_sendmsg when the packet is a "V4 on a 
V6 socket", but otherwise
   the necessary "goop" doesn't appear to be implemented for V6.

In particular, the V4 udp_sendmsg function has a structure, ipcm_cookie, 
which appears to
   be used to carry the shtx flags, including the "hardware" flag that 
indicates hardware
   timestamping.  It's not clear exactly where this gets "attached" to 
the outgoing SKB, but
   none of this appears in the V6 version of udp.c

While the V6 udp.c is quite *similar* to the V4 version, some of the 
data structures are
   quite different, and it's not clear to me where to begin.  Further, I 
got a note from Patrick
   Ohly indicating that the e1000 driver guys at Intel have been the 
ones maintaining the
   SO_TIMESTAMPING code, so I don't want to replicate work that may 
already be in-progress/
   done.

Looking at even the latest kernel code, there's no hint that this has 
been addressed.

Also, there's no hint of implementation for net/packet (AF_PACKET).

The context of all this is a PTPV2 (IEEE1588-2008) implementation that 
requires hardware time-stamping support for all three of: IPV4, IPV6, 
and ETHERNET (AF_PACKET/SOCK_DGRAM).

I've been testing with IPV4 exclusively, and it has been working quite well.

^ permalink raw reply

* Re: [PATCH 40/75] cxgb3: declare MODULE_FIRMWARE
From: Divy Le Ray @ 2009-11-10 19:19 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: David Miller, netdev
In-Reply-To: <1257630832.15927.440.camel@localhost>

On Saturday 07 November 2009 01:53:52 pm Ben Hutchings wrote:
> Replace run-time string formatting with preprocessor string
> manipulation.
> 
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

Acked-by: Divy Le Ray <divy@chelsio.com>

> ---
>  drivers/net/cxgb3/common.h     |    8 +++-----
>  drivers/net/cxgb3/cxgb3_main.c |   25 ++++++++++++++++---------
>  2 files changed, 19 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
> index 1b2c305..6ff356d 100644
> --- a/drivers/net/cxgb3/common.h
> +++ b/drivers/net/cxgb3/common.h
> @@ -125,11 +125,9 @@ enum {				/* adapter interrupt-maintained statistics
>  */ IRQ_NUM_STATS		/* keep last */
>  };
> 
> -enum {
> -	TP_VERSION_MAJOR	= 1,
> -	TP_VERSION_MINOR	= 1,
> -	TP_VERSION_MICRO	= 0
> -};
> +#define TP_VERSION_MAJOR	1
> +#define TP_VERSION_MINOR	1
> +#define TP_VERSION_MICRO	0
> 
>  #define S_TP_VERSION_MAJOR		16
>  #define M_TP_VERSION_MAJOR		0xFF
> diff --git a/drivers/net/cxgb3/cxgb3_main.c
>  b/drivers/net/cxgb3/cxgb3_main.c index c9113d3..b1a5a00 100644
> --- a/drivers/net/cxgb3/cxgb3_main.c
> +++ b/drivers/net/cxgb3/cxgb3_main.c
> @@ -44,6 +44,7 @@
>  #include <linux/rtnetlink.h>
>  #include <linux/firmware.h>
>  #include <linux/log2.h>
> +#include <linux/stringify.h>
>  #include <asm/uaccess.h>
> 
>  #include "common.h"
> @@ -992,11 +993,21 @@ static int bind_qsets(struct adapter *adap)
>  	return err;
>  }
> 
> -#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin"
> -#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin"
> +#define FW_VERSION __stringify(FW_VERSION_MAJOR) "."			\
> +	__stringify(FW_VERSION_MINOR) "." __stringify(FW_VERSION_MICRO)
> +#define FW_FNAME "cxgb3/t3fw-" FW_VERSION ".bin"
> +#define TPSRAM_VERSION __stringify(TP_VERSION_MAJOR) "."		\
> +	__stringify(TP_VERSION_MINOR) "." __stringify(TP_VERSION_MICRO)
> +#define TPSRAM_NAME "cxgb3/t3%c_psram-" TPSRAM_VERSION ".bin"
>  #define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin"
>  #define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin"
>  #define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin"
> +MODULE_FIRMWARE(FW_FNAME);
> +MODULE_FIRMWARE("cxgb3/t3b_psram-" TPSRAM_VERSION ".bin");
> +MODULE_FIRMWARE("cxgb3/t3c_psram-" TPSRAM_VERSION ".bin");
> +MODULE_FIRMWARE(AEL2005_OPT_EDC_NAME);
> +MODULE_FIRMWARE(AEL2005_TWX_EDC_NAME);
> +MODULE_FIRMWARE(AEL2020_TWX_EDC_NAME);
> 
>  static inline const char *get_edc_fw_name(int edc_idx)
>  {
> @@ -1067,16 +1078,13 @@ int t3_get_edc_fw(struct cphy *phy, int edc_idx,
>  int size) static int upgrade_fw(struct adapter *adap)
>  {
>  	int ret;
> -	char buf[64];
>  	const struct firmware *fw;
>  	struct device *dev = &adap->pdev->dev;
> 
> -	snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
> -		 FW_VERSION_MINOR, FW_VERSION_MICRO);
> -	ret = request_firmware(&fw, buf, dev);
> +	ret = request_firmware(&fw, FW_FNAME, dev);
>  	if (ret < 0) {
>  		dev_err(dev, "could not upgrade firmware: unable to load %s\n",
> -			buf);
> +			FW_FNAME);
>  		return ret;
>  	}
>  	ret = t3_load_fw(adap, fw->data, fw->size);
> @@ -1120,8 +1128,7 @@ static int update_tpsram(struct adapter *adap)
>  	if (!rev)
>  		return 0;
> 
> -	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
> -		 TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
> +	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
> 
>  	ret = request_firmware(&tpsram, buf, dev);
>  	if (ret < 0) {
> 

^ permalink raw reply

* Re: [PATCH 07/10] decnet: use RCU to find network devices
From: Eric Dumazet @ 2009-11-10 19:25 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Christine Caulfield, Hannes Eder, Alexey Dobriyan,
	Steven Whitehouse, netdev, linux-decnet-users
In-Reply-To: <20091110105053.16687e93@nehalam>

Stephen Hemminger a écrit :
> On Tue, 10 Nov 2009 19:43:21 +0100
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
> 
>> Stephen Hemminger a écrit :
>>> When showing device statistics use RCU rather than read_lock(&dev_base_lock)
>>> Compile tested only.
>>>
>>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>>>
>>> --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
>>> +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
>>> @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
>>>  	dev = dn_dev_get_default();
>>>  last_chance:
>>>  	if (dev) {
>>> -		read_lock(&dev_base_lock);
>>>  		rv = dn_dev_get_first(dev, addr);
>>> -		read_unlock(&dev_base_lock);
>>>  		dev_put(dev);
>>>  		if (rv == 0 || dev == init_net.loopback_dev)
>>>  			return rv;
>>> @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
>>
>> I dont understand this part. Why previous locking can be avoided ?
> 
> dn_dev_get_default acquires a reference on dev so the device can
> not go away.
> 
> It could be the original author meant to ensure the address list
> doesn't change. If so, then rtnl_lock() should have been used.

Hmm... I spot some bugs during my previous round of patches, so maybe
this is a real bug... We should double check.



^ permalink raw reply

* Re: [PATCH 07/10] decnet: use RCU to find network devices
From: steve @ 2009-11-10 18:24 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Eric Dumazet, David Miller, Christine Caulfield, Hannes Eder,
	Alexey Dobriyan, Steven Whitehouse, netdev, linux-decnet-users
In-Reply-To: <20091110105053.16687e93@nehalam>

Hi,

On Tue, Nov 10, 2009 at 10:50:53AM -0800, Stephen Hemminger wrote:
> On Tue, 10 Nov 2009 19:43:21 +0100
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
> 
> > Stephen Hemminger a écrit :
> > > When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> > > Compile tested only.
> > > 
> > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > > 
> > > --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> > > +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> > > @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
> > >  	dev = dn_dev_get_default();
> > >  last_chance:
> > >  	if (dev) {
> > > -		read_lock(&dev_base_lock);
> > >  		rv = dn_dev_get_first(dev, addr);
> > > -		read_unlock(&dev_base_lock);
> > >  		dev_put(dev);
> > >  		if (rv == 0 || dev == init_net.loopback_dev)
> > >  			return rv;
> > > @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
> > 
> > 
> > I dont understand this part. Why previous locking can be avoided ?
> 
> dn_dev_get_default acquires a reference on dev so the device can
> not go away.
> 
> It could be the original author meant to ensure the address list
> doesn't change. If so, then rtnl_lock() should have been used.

The original author has tried to remember what he was thinking when
he wrote this code :-)

I think you are right that it should be rtnl_lock() as we don't want
the address list changing at this point. On the other hand I notice
also that other bits of the code seem to be using dev_base_lock too.

Maybe this is a hang over from another era? I'll have to refresh
my memory some more before I can give a verdict on that I'm afraid,

Steve.


^ permalink raw reply

* Re: [PATCH 01/10] netdev: add netdev_continue_rcu
From: Paul E. McKenney @ 2009-11-10 19:39 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20091110175647.200655064@vyatta.com>

On Tue, Nov 10, 2009 at 09:54:47AM -0800, Stephen Hemminger wrote:
> This adds an RCU macro for continuing search, useful for some
> network devices like vlan.

Looks good!!!

Of course, you need to either have a single RCU read-side critical section
cover all the chained list_for_each_entry_continue_rcu() invocations, or
you need to do something (e.g., reference count) to make sure that the
element in question doesn't disappear in the meantime, right?

							Thanx, Paul

> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/include/linux/netdevice.h	2009-11-09 22:19:08.511480873 -0800
> +++ b/include/linux/netdevice.h	2009-11-10 09:27:17.973376267 -0800
> @@ -1079,6 +1079,8 @@ extern rwlock_t				dev_base_lock;		/* De
>  		list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
>  #define for_each_netdev_continue(net, d)		\
>  		list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
> +#define for_each_netdev_continue_rcu(net, d)		\
> +	list_for_each_entry_continue_rcu(d, &(net)->dev_base_head, dev_list)
>  #define net_device_entry(lh)	list_entry(lh, struct net_device, dev_list)
> 
>  static inline struct net_device *next_net_device(struct net_device *dev)
> --- a/include/linux/rculist.h	2009-11-09 22:19:08.529480859 -0800
> +++ b/include/linux/rculist.h	2009-11-10 09:27:17.974376609 -0800
> @@ -262,6 +262,20 @@ static inline void list_splice_init_rcu(
>  		(pos) = rcu_dereference((pos)->next))
> 
>  /**
> + * list_for_each_entry_continue_rcu - continue iteration over list of given type
> + * @pos:	the type * to use as a loop cursor.
> + * @head:	the head for your list.
> + * @member:	the name of the list_struct within the struct.
> + *
> + * Continue to iterate over list of given type, continuing after
> + * the current position.
> + */
> +#define list_for_each_entry_continue_rcu(pos, head, member) 		\
> +	for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \
> +	     prefetch(pos->member.next), &pos->member != (head);	\
> +	     pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
> +
> +/**
>   * hlist_del_rcu - deletes entry from hash list without re-initialization
>   * @n: the element to delete from the hash list.
>   *
> 
> -- 
> 

^ permalink raw reply

* Re: [PATCH] can: fix WARN_ON dump in net/core/rtnetlink.c:rtmsg_ifinfo()
From: Wolfgang Grandegger @ 2009-11-10 19:45 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, David Miller
In-Reply-To: <4AF94D74.4040606-dcUjhNyLwpNeoWH0uzbU5w@public.gmane.org>

Patrick McHardy wrote:
> Wolfgang Grandegger wrote:
>> David Miller wrote:
>>> From: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
>>> Date: Sat, 07 Nov 2009 10:53:13 +0100
>>>
>>>> On older kernels, e.g. 2.6.27, a WARN_ON dump in rtmsg_ifinfo()
>>>> is thrown when the CAN device is registered due to insufficient
>>>> skb space, as reported by various users. This patch adds the
>>>> rtnl_link_ops "get_size" to fix the problem. I think this patch
>>>> is required for more recent kernels as well, even if no WARN_ON
>>>> dumps are triggered. Maybe we also need "get_xstats_size" for
>>>> the CAN xstats.
>>>>
>>>> Signed-off-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
>>> Applied to net-2.6, thanks Wolfgang.
>> Thanks, the commit message included some questions. What is the rule
>> using the rtnl_link_ops "get_size" or "get_xstats_size". Are these
>> mandatory if the corresponding fill functions are used?
> 
> Yes. You also need a get_xstats_size() function.

Thanks for clarification. I will provide a patch a.s.a.p.

Wolfgang.

^ permalink raw reply

* [PATCH] s2io: fixing a ethtool test that is broken
From: leitao @ 2009-11-10 19:44 UTC (permalink / raw)
  To: netdev; +Cc: sreenivasa.honnur, Breno Leitao

Due commit 4b77b0a2ba27d64f58f16d8d4d48d8319dda36ff, it is not more
possible to pci_restore_state() more than once without calling
pci_save_state() in the middle.

Actually running a ethtool test on s2io makes the card inactive, 
and it needs to unload/reload the module to fix. 

This patch just save the state just after it restore in order to
keep the old behaviour

Signed-off-by: Breno Leitao <leitao@linux.vnet.ibm.com>
---
 drivers/net/s2io.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index ddccf5f..0dd7839 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3494,6 +3494,7 @@ static void s2io_reset(struct s2io_nic *sp)
 
 		/* Restore the PCI state saved during initialization. */
 		pci_restore_state(sp->pdev);
+		pci_save_state(sp->pdev);
 		pci_read_config_word(sp->pdev, 0x2, &val16);
 		if (check_pci_device_id(val16) != (u16)PCI_ANY_ID)
 			break;
-- 
1.6.0.2


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox