* [net-next PATCH] tun: correctly report an error in tun_flow_init()
From: Paul Moore @ 2012-12-06 15:48 UTC (permalink / raw)
To: netdev; +Cc: jasowang
On error, the error code from tun_flow_init() is lost inside
tun_set_iff(), this patch fixes this by assigning the tun_flow_init()
error code to the "err" variable which is returned by
the tun_flow_init() function on error.
Signed-off-by: Paul Moore <pmoore@redhat.com>
---
drivers/net/tun.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a1b2389..14a0454 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1591,7 +1591,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun_net_init(dev);
- if (tun_flow_init(tun))
+ err = tun_flow_init(tun);
+ if (err < 0)
goto err_free_dev;
dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
^ permalink raw reply related
* build failure of latest ethtool
From: Or Gerlitz @ 2012-12-06 16:06 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
Hi Ben,
FYI, building the latest ethtool git fails since sfpid.c is not present
in the Makefile. Once I built it manually and added to the linkage line,
ethtool builds OK.
$ gcc -Wall -g -O2 -o ethtool ethtool.o amd8111e.o de2104x.o e100.o
e1000.o igb.o fec_8xx.o ibm_emac.o ixgb.o ixgbe.o natsemi.o pcnet32.o
realtek.o tg3.o marvell.o vioc.o smsc911x.o at76c50x-usb.o sfc.o
stmmac.o rxclass.o
ethtool.o: In function `do_getmodule':
/upstream/ethtool/ethtool.c:3616: undefined reference to `sff8079_show_all'
collect2: ld returned 1 exit status
make[1]: *** [ethtool] Error 1
^ permalink raw reply
* Re: [RFC PATCH v2 3/3] tun: fix LSM/SELinux labeling of tun/tap devices
From: Michael S. Tsirkin @ 2012-12-06 16:12 UTC (permalink / raw)
To: Paul Moore; +Cc: netdev, linux-security-module, selinux, jasowang
In-Reply-To: <7448004.siKCIqQqTi@sifl>
On Thu, Dec 06, 2012 at 10:46:11AM -0500, Paul Moore wrote:
> On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
> > On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
> > > This patch corrects some problems with LSM/SELinux that were introduced
> > > with the multiqueue patchset. The problem stems from the fact that the
> > > multiqueue work changed the relationship between the tun device and its
> > > associated socket; before the socket persisted for the life of the
> > > device, however after the multiqueue changes the socket only persisted
> > > for the life of the userspace connection (fd open). For non-persistent
> > > devices this is not an issue, but for persistent devices this can cause
> > > the tun device to lose its SELinux label.
> > >
> > > We correct this problem by adding an opaque LSM security blob to the
> > > tun device struct which allows us to have the LSM security state, e.g.
> > > SELinux labeling information, persist for the lifetime of the tun
> > > device. In the process we tweak the LSM hooks to work with this new
> > > approach to TUN device/socket labeling and introduce a new LSM hook,
> > > security_tun_dev_create_queue(), to approve requests to create a new
> > > TUN queue via TUNSETQUEUE.
> > >
> > > The SELinux code has been adjusted to match the new LSM hooks, the
> > > other LSMs do not make use of the LSM TUN controls. This patch makes
> > > use of the recently added "tun_socket:create_queue" permission to
> > > restrict access to the TUNSETQUEUE operation. On older SELinux
> > > policies which do not define the "tun_socket:create_queue" permission
> > > the access control decision for TUNSETQUEUE will be handled according
> > > to the SELinux policy's unknown permission setting.
> > >
> > > Signed-off-by: Paul Moore <pmoore@redhat.com>
> >
> > OK so just to verify: this can be used to ensure that qemu
> > process that has the queue fd can only attach it to
> > a specific device, right?
>
> Whenever a new queue is created via TUNSETQUEUE/tun_set_queue() the
> security_tun_dev_create_queue() LSM hook is called. When SELinux is enabled
> this hook ends up calling selinux_tun_dev_create_queue() which checks that the
> calling process (process_t) is allowed to create a new queue on the specified
> device (tundev_t) . If you are familiar with SELinux security policy, the
> allow rule would look like this:
>
> allow process_t tundev_t:tun_socket create_queue;
>
> In practice, if we assume libvirt is creating the TUN device and running with
> a SELinux label of virtd_t and that QEMU instances are running with a SELinux
> label of svirt_t then the allow rule would look like this:
>
> allow svirt_t virtd_t:tun_socket create_queue;
>
> There is also the matter of the MLS/MCS constraints providing additional
> separation but that is another level of detail which I don't believe is
> important for our discussion.
Hmm. How do the rules for SETIFF look ATM?
I am just checking default policy does not let qemu do with
SETQUEUE something with a device which it can not
attach to using SETIFF.
> --
> paul moore
> security and virtualization @ redhat
^ permalink raw reply
* Re: build failure of latest ethtool
From: Ben Hutchings @ 2012-12-06 16:29 UTC (permalink / raw)
To: Or Gerlitz; +Cc: netdev
In-Reply-To: <50C0C276.5060809@mellanox.com>
On Thu, 2012-12-06 at 18:06 +0200, Or Gerlitz wrote:
> Hi Ben,
>
> FYI, building the latest ethtool git fails since sfpid.c is not present
> in the Makefile.
[...]
If you want to build from git you have to run:
./autogen.sh && ./configure && make
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: build failure of latest ethtool
From: Or Gerlitz @ 2012-12-06 16:33 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
In-Reply-To: <1354811376.2828.1.camel@bwh-desktop.uk.solarflarecom.com>
On 06/12/2012 18:29, Ben Hutchings wrote:
> If you want to build from git you have to run: ./autogen.sh &&
> ./configure && make
OK, sorry for the spam, I pulled the tree but didn't re-run ./autogen.sh
&& ./configure
^ permalink raw reply
* Re: [RFC PATCH v2 3/3] tun: fix LSM/SELinux labeling of tun/tap devices
From: Paul Moore @ 2012-12-06 16:56 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev, linux-security-module, selinux, jasowang
In-Reply-To: <20121206161200.GA4340@redhat.com>
On Thursday, December 06, 2012 06:12:00 PM Michael S. Tsirkin wrote:
> On Thu, Dec 06, 2012 at 10:46:11AM -0500, Paul Moore wrote:
> > On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
> > > OK so just to verify: this can be used to ensure that qemu
> > > process that has the queue fd can only attach it to
> > > a specific device, right?
> >
> > Whenever a new queue is created via TUNSETQUEUE/tun_set_queue() the
> > security_tun_dev_create_queue() LSM hook is called. When SELinux is
> > enabled this hook ends up calling selinux_tun_dev_create_queue() which
> > checks that the calling process (process_t) is allowed to create a new
> > queue on the specified device (tundev_t) . If you are familiar with
> > SELinux security policy, the allow rule would look like this:
> >
> > allow process_t tundev_t:tun_socket create_queue;
> >
> > In practice, if we assume libvirt is creating the TUN device and running
> > with a SELinux label of virtd_t and that QEMU instances are running with
> > a SELinux label of svirt_t then the allow rule would look like this:
> >
> > allow svirt_t virtd_t:tun_socket create_queue;
> >
> > There is also the matter of the MLS/MCS constraints providing additional
> > separation but that is another level of detail which I don't believe is
> > important for our discussion.
>
> Hmm. How do the rules for SETIFF look ATM?
> I am just checking default policy does not let qemu do with
> SETQUEUE something with a device which it can not
> attach to using SETIFF.
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to the
policy's unknown permission setting.
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* [PATCH] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
From: Thomas Graf @ 2012-12-06 17:34 UTC (permalink / raw)
To: linux-sctp; +Cc: netdev, Vlad Yasevich, Neil Horman
address_list is protected via the socket lock or RCU. Since we don't want
to take the socket lock for each assoc we dump in procfs a RCU read-side
critical section must be entered.
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/sctp/proc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 9966e7b..ec9b0c8 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -139,7 +139,8 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
primary = &peer->saddr;
}
- list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
addr = &laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
if (primary && af->cmp_addr(addr, primary)) {
@@ -147,6 +148,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
/* Dump remote addresses of an association. */
--
1.7.11.7
^ permalink raw reply related
* Hi!
From: Marketing Commucation @ 2012-12-06 17:18 UTC (permalink / raw)
I am Mr. Joseph. I have a lucrative business proposal of mutual interest to
share with you.
^ permalink raw reply
* Re: [PATCH net-next 0/7] Allow to monitor multicast cache event via rtnetlink
From: Thomas Graf @ 2012-12-06 17:49 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: David Miller, David.Laight, netdev
In-Reply-To: <50C05AC2.1050504@6wind.com>
On 12/06/12 at 09:43am, Nicolas Dichtel wrote:
> Le 05/12/2012 18:54, David Miller a écrit :
> >From: "David Laight" <David.Laight@ACULAB.COM>
> >Date: Wed, 5 Dec 2012 11:41:33 -0000
> >
> >>Probably worth commenting that the 64bit items might only be 32bit aligned.
> >>Just to stop anyone trying to read/write them with pointer casts.
> >
> >Rather, let's not create this situation at all.
> >
> >It's totally inappropriate to have special code to handle every single
> >time we want to put 64-bit values into netlink messages.
> >
> >We need a real solution to this issue.
> >
> The easiest way is to update *_ALIGNTO values (maybe we can keep
> NLMSG_ALIGNTO to 4). But I think that many userland apps have these
> values hardcoded and, the most important thing, this may increase
> size of many netlink messages. Hence we need probably to find
> something better.
We can't do this, as you say, ALIGNTO is compiled into all the
binaries.
A simple backwards compatible workaround would be to include an
unknown, empty padding attribute if needed. That would be 4 bytes
in size and could be used to include padding as needed.
We could use nla_type = 0 as it is a reserved value that should
be available in all protocols. All readers (kernel and user space)
must ignore such an attribute just like any other unknown
attribute they encounter.
We could easily extend nla_put_u64() and variants to automatically
include such a padding attribute as needed.
The only situation that I can think of where this would not work
is if we have code like this:
foo = nla_nest_start();
for ([..])
nla_put_u64([...])
nla_nest_end([...])
and a reader would stupidly do a nla_for_each_attr() in user space
and assume all attributes found must be NLA_U64 without even
checking the length of the attribute.
I would say we take that risk and let such code die horribly.
^ permalink raw reply
* [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Thomas Graf @ 2012-12-06 18:15 UTC (permalink / raw)
To: linux-sctp; +Cc: netdev, Vlad Yasevich, Neil Horman
peer.transport_addr_list is currently only protected by sk_sock
which is inpractical to acquire for procfs dumping purposes.
This patch adds RCU protection allowing for the procfs readers to
enter RCU read-side critical sections.
Modification of the list continues to be serialized via sk_lock.
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
include/net/sctp/structs.h | 2 ++
net/sctp/associola.c | 4 ++--
net/sctp/proc.c | 8 ++++++--
net/sctp/transport.c | 18 +++++++++++++-----
4 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 64158aa..5d6987b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -948,6 +948,8 @@ struct sctp_transport {
/* 64-bit random number sent with heartbeat. */
__u64 hb_nonce;
+
+ struct rcu_head rcu;
};
struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b1ef3bc..c826bb8 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -565,7 +565,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
sctp_assoc_update_retran_path(asoc);
/* Remove this peer from the list. */
- list_del(&peer->transports);
+ list_del_rcu(&peer->transports);
/* Get the first transport of asoc. */
pos = asoc->peer.transport_addr_list.next;
@@ -765,7 +765,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->state = peer_state;
/* Attach the remote transport to our asoc. */
- list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+ list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
asoc->peer.transport_count++;
/* If we do not yet have a primary path, set one. */
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index ec9b0c8..36a3f9d 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -159,7 +159,8 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
struct sctp_af *af;
primary = &assoc->peer.primary_addr;
- list_for_each_entry(transport, &assoc->peer.transport_addr_list,
+ rcu_read_lock();
+ list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
transports) {
addr = &transport->ipaddr;
af = sctp_get_af_specific(addr->sa.sa_family);
@@ -168,6 +169,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
@@ -438,11 +440,12 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
+ rcu_read_lock();
sctp_for_each_hentry(epb, node, &head->chain) {
if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
continue;
assoc = sctp_assoc(epb);
- list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
+ list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
transports) {
/*
* The remote address (ADDR)
@@ -489,6 +492,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
}
}
+ rcu_read_unlock();
read_unlock(&head->lock);
sctp_local_bh_enable();
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 206cf52..1295aec 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
sctp_transport_put(transport);
}
-/* Destroy the transport data structure.
- * Assumes there are no more users of this structure.
- */
-static void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy_rcu(struct rcu_head *head)
{
- SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+ struct sctp_transport *transport;
+ transport = container_of(head, struct sctp_transport, rcu);
if (transport->asoc)
sctp_association_put(transport->asoc);
@@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
SCTP_DBG_OBJCNT_DEC(transport);
}
+/* Destroy the transport data structure.
+ * Assumes there are no more users of this structure.
+ */
+static void sctp_transport_destroy(struct sctp_transport *transport)
+{
+ SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+
+ call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+}
+
/* Start T3_rtx timer if it is not already running and update the heartbeat
* timer. This routine is called every time a DATA chunk is sent.
*/
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
From: Vlad Yasevich @ 2012-12-06 18:25 UTC (permalink / raw)
To: Thomas Graf; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <a803093c70e857e8e01e554288ee79f66f7acda4.1354814846.git.tgraf@suug.ch>
On 12/06/2012 12:34 PM, Thomas Graf wrote:
> address_list is protected via the socket lock or RCU. Since we don't want
> to take the socket lock for each assoc we dump in procfs a RCU read-side
> critical section must be entered.
>
> Cc: Vlad Yasevich <vyasevich@gmail.com>
> Cc: Neil Horman <nhorman@tuxdriver.com>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> ---
> net/sctp/proc.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index 9966e7b..ec9b0c8 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -139,7 +139,8 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
> primary = &peer->saddr;
> }
>
> - list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
> + rcu_read_lock();
> + list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
> addr = &laddr->a;
> af = sctp_get_af_specific(addr->sa.sa_family);
> if (primary && af->cmp_addr(addr, primary)) {
> @@ -147,6 +148,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
> }
> af->seq_dump_addr(seq, addr);
> }
> + rcu_read_unlock();
> }
>
> /* Dump remote addresses of an association. */
>
May want to avoid printing addresses that are !addr->valid.
Otherwise looks good.
-vlad
^ permalink raw reply
* Re: [PATCH] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
From: Thomas Graf @ 2012-12-06 18:28 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <50C0E300.3000703@gmail.com>
On 12/06/12 at 01:25pm, Vlad Yasevich wrote:
> May want to avoid printing addresses that are !addr->valid.
>
> Otherwise looks good.
Good point, I'll send a follow-up patch if that is OK. Same
applies to dead transports obviously.
^ permalink raw reply
* Re: [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Vlad Yasevich @ 2012-12-06 18:35 UTC (permalink / raw)
To: Thomas Graf; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <16453bea94a6fc43d657139dff2ce0b5924e2a1f.1354817574.git.tgraf@suug.ch>
On 12/06/2012 01:15 PM, Thomas Graf wrote:
> peer.transport_addr_list is currently only protected by sk_sock
> which is inpractical to acquire for procfs dumping purposes.
>
> This patch adds RCU protection allowing for the procfs readers to
> enter RCU read-side critical sections.
>
> Modification of the list continues to be serialized via sk_lock.
>
> Cc: Vlad Yasevich <vyasevich@gmail.com>
> Cc: Neil Horman <nhorman@tuxdriver.com>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> ---
> include/net/sctp/structs.h | 2 ++
> net/sctp/associola.c | 4 ++--
> net/sctp/proc.c | 8 ++++++--
> net/sctp/transport.c | 18 +++++++++++++-----
> 4 files changed, 23 insertions(+), 9 deletions(-)
>
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 64158aa..5d6987b 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -948,6 +948,8 @@ struct sctp_transport {
>
> /* 64-bit random number sent with heartbeat. */
> __u64 hb_nonce;
> +
> + struct rcu_head rcu;
> };
>
> struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index b1ef3bc..c826bb8 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -565,7 +565,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
> sctp_assoc_update_retran_path(asoc);
>
> /* Remove this peer from the list. */
> - list_del(&peer->transports);
> + list_del_rcu(&peer->transports);
>
> /* Get the first transport of asoc. */
> pos = asoc->peer.transport_addr_list.next;
> @@ -765,7 +765,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
> peer->state = peer_state;
>
> /* Attach the remote transport to our asoc. */
> - list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
> + list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
> asoc->peer.transport_count++;
>
> /* If we do not yet have a primary path, set one. */
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index ec9b0c8..36a3f9d 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -159,7 +159,8 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
> struct sctp_af *af;
>
> primary = &assoc->peer.primary_addr;
> - list_for_each_entry(transport, &assoc->peer.transport_addr_list,
> + rcu_read_lock();
> + list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
> transports) {
> addr = &transport->ipaddr;
> af = sctp_get_af_specific(addr->sa.sa_family);
> @@ -168,6 +169,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
> }
> af->seq_dump_addr(seq, addr);
> }
> + rcu_read_unlock();
> }
>
> static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
> @@ -438,11 +440,12 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
> head = &sctp_assoc_hashtable[hash];
> sctp_local_bh_disable();
> read_lock(&head->lock);
> + rcu_read_lock();
> sctp_for_each_hentry(epb, node, &head->chain) {
> if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
> continue;
> assoc = sctp_assoc(epb);
> - list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
> + list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
> transports) {
> /*
> * The remote address (ADDR)
> @@ -489,6 +492,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
> }
> }
>
> + rcu_read_unlock();
> read_unlock(&head->lock);
> sctp_local_bh_enable();
>
> diff --git a/net/sctp/transport.c b/net/sctp/transport.c
> index 206cf52..1295aec 100644
> --- a/net/sctp/transport.c
> +++ b/net/sctp/transport.c
> @@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
> sctp_transport_put(transport);
> }
>
> -/* Destroy the transport data structure.
> - * Assumes there are no more users of this structure.
> - */
> -static void sctp_transport_destroy(struct sctp_transport *transport)
> +static void sctp_transport_destroy_rcu(struct rcu_head *head)
> {
> - SCTP_ASSERT(transport->dead, "Transport is not dead", return);
> + struct sctp_transport *transport;
>
> + transport = container_of(head, struct sctp_transport, rcu);
> if (transport->asoc)
> sctp_association_put(transport->asoc);
>
> @@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
> SCTP_DBG_OBJCNT_DEC(transport);
> }
>
> +/* Destroy the transport data structure.
> + * Assumes there are no more users of this structure.
> + */
> +static void sctp_transport_destroy(struct sctp_transport *transport)
> +{
> + SCTP_ASSERT(transport->dead, "Transport is not dead", return);
> +
> + call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
> +}
> +
> /* Start T3_rtx timer if it is not already running and update the heartbeat
> * timer. This routine is called every time a DATA chunk is sent.
> */
>
We may want to mark transports as dead sooner. Probably right about the
time we pull them off the list. When displaying, we may want to
look at transport->dead, and skip them. It will reduce the probability
that we would be looking at a transport that's about to go away.
Otherwise, looks very nice.
-vlad
^ permalink raw reply
* Re: [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Thomas Graf @ 2012-12-06 18:44 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <50C0E585.1080701@gmail.com>
On 12/06/12 at 01:35pm, Vlad Yasevich wrote:
> We may want to mark transports as dead sooner. Probably right about
> the time we pull them off the list.
We mark it dead in sctp_transport_free() which is called at the
end of sctp_assoc_rm_peer(). Do you want to mark it dead at the
beginning of sctp_assoc_rm_peer() as well? (We still need to
mark in sctp_transport_free() anyway).
> When displaying, we may want to
> look at transport->dead, and skip them. It will reduce the probability
> that we would be looking at a transport that's about to go away.
Agreed.
^ permalink raw reply
* [PATCH] tcp: bug fix Fast Open client retransmission
From: Yuchung Cheng @ 2012-12-06 18:45 UTC (permalink / raw)
To: davem, ncardwell, nanditad, edumazet; +Cc: netdev, Yuchung Cheng
If SYN-ACK partially acks SYN-data, the client retransmits the
remaining data by tcp_retransmit_skb(). This increments lost recovery
state variables like tp->retrans_out in Open state. If loss recovery
happens before the retransmission is acked, it triggers the WARN_ON
check in tcp_fastretrans_alert(). For example: the client sends
SYN-data, gets SYN-ACK acking only ISN, retransmits data, sends
another 4 data packets and get 3 dupacks.
Since the retransmission is not caused by network drop it should not
update the recovery state variables. Further the server may return a
smaller MSS than the cached MSS used for SYN-data, so the retranmission
needs a loop. Otherwise some data will not be retransmitted until timeout
or other loss recovery events.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
---
include/net/tcp.h | 1 +
net/ipv4/tcp_input.c | 6 +++++-
net/ipv4/tcp_output.c | 15 ++++++++++-----
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 3202bde..aed42c7 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -524,6 +524,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
int nonagle);
extern bool tcp_may_send_now(struct sock *sk);
+extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_retransmit_timer(struct sock *sk);
extern void tcp_xmit_retransmit_queue(struct sock *);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index fc67831..a136925 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5652,7 +5652,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
if (data) { /* Retransmit unacked data in SYN */
- tcp_retransmit_skb(sk, data);
+ tcp_for_write_queue_from(data, sk) {
+ if (data == tcp_send_head(sk) ||
+ __tcp_retransmit_skb(sk, data))
+ break;
+ }
tcp_rearm_rto(sk);
return true;
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 8ac0855..5d45159 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2309,12 +2309,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
* state updates are done by the caller. Returns non-zero if an
* error occurred which prevented the send.
*/
-int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
unsigned int cur_mss;
- int err;
/* Inconslusive MTU probe */
if (icsk->icsk_mtup.probe_size) {
@@ -2387,11 +2386,17 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
GFP_ATOMIC);
- err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
- -ENOBUFS;
+ return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
+ -ENOBUFS;
} else {
- err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+ return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
}
+}
+
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int err = __tcp_retransmit_skb(sk, skb);
if (err == 0) {
/* Update global TCP statistics. */
--
1.7.7.3
^ permalink raw reply related
* Re: [PATCH net next] team: remove team parameter from port_enter callback.
From: Jiri Pirko @ 2012-12-06 18:50 UTC (permalink / raw)
To: Rami Rosen; +Cc: davem, netdev
In-Reply-To: <1354799382-23808-1-git-send-email-ramirose@gmail.com>
Thu, Dec 06, 2012 at 02:09:42PM CET, ramirose@gmail.com wrote:
>This patch removes an unused parameter (team) from port_enter callback in
>team_mode_ops and fixes accordingly its invocations in 3 modes and in team.c.
Please do not do this. This parameter is ment to be used in future.
Thanks.
Jiri
>
>Signed-off-by: Rami Rosen <ramirose@gmail.com>
>---
> drivers/net/team/team.c | 2 +-
> drivers/net/team/team_mode_broadcast.c | 2 +-
> drivers/net/team/team_mode_loadbalance.c | 2 +-
> drivers/net/team/team_mode_roundrobin.c | 2 +-
> include/linux/if_team.h | 2 +-
> 5 files changed, 5 insertions(+), 5 deletions(-)
>
>diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
>index ad86660..4203808 100644
>--- a/drivers/net/team/team.c
>+++ b/drivers/net/team/team.c
>@@ -887,7 +887,7 @@ static int team_port_enter(struct team *team, struct team_port *port)
> dev_hold(team->dev);
> port->dev->priv_flags |= IFF_TEAM_PORT;
> if (team->ops.port_enter) {
>- err = team->ops.port_enter(team, port);
>+ err = team->ops.port_enter(port);
> if (err) {
> netdev_err(team->dev, "Device %s failed to enter team mode\n",
> port->dev->name);
>diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c
>index c5db428..c3840bc 100644
>--- a/drivers/net/team/team_mode_broadcast.c
>+++ b/drivers/net/team/team_mode_broadcast.c
>@@ -46,7 +46,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
> return sum_ret;
> }
>
>-static int bc_port_enter(struct team *team, struct team_port *port)
>+static int bc_port_enter(struct team_port *port)
> {
> return team_port_set_team_dev_addr(port);
> }
>diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
>index cdc31b5..1e84c77 100644
>--- a/drivers/net/team/team_mode_loadbalance.c
>+++ b/drivers/net/team/team_mode_loadbalance.c
>@@ -614,7 +614,7 @@ static void lb_exit(struct team *team)
> kfree(lb_priv->ex);
> }
>
>-static int lb_port_enter(struct team *team, struct team_port *port)
>+static int lb_port_enter(struct team_port *port)
> {
> struct lb_port_priv *lb_port_priv = get_lb_port_priv(port);
>
>diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c
>index 105135a..abe889e 100644
>--- a/drivers/net/team/team_mode_roundrobin.c
>+++ b/drivers/net/team/team_mode_roundrobin.c
>@@ -64,7 +64,7 @@ drop:
> return false;
> }
>
>-static int rr_port_enter(struct team *team, struct team_port *port)
>+static int rr_port_enter(struct team_port *port)
> {
> return team_port_set_team_dev_addr(port);
> }
>diff --git a/include/linux/if_team.h b/include/linux/if_team.h
>index 0245def..3366453 100644
>--- a/include/linux/if_team.h
>+++ b/include/linux/if_team.h
>@@ -105,7 +105,7 @@ struct team_mode_ops {
> struct team_port *port,
> struct sk_buff *skb);
> bool (*transmit)(struct team *team, struct sk_buff *skb);
>- int (*port_enter)(struct team *team, struct team_port *port);
>+ int (*port_enter)(struct team_port *port);
> void (*port_leave)(struct team *team, struct team_port *port);
> void (*port_change_dev_addr)(struct team *team, struct team_port *port);
> void (*port_enabled)(struct team *team, struct team_port *port);
>--
>1.7.11.7
>
^ permalink raw reply
* Re: [PATCH] net : enable tx time stamping in the vde driver.
From: Richard Cochran @ 2012-12-06 18:57 UTC (permalink / raw)
To: Paul Chavent; +Cc: jdike, richard, user-mode-linux-devel, netdev
In-Reply-To: <1354807505-21222-1-git-send-email-paul.chavent@onera.fr>
On Thu, Dec 06, 2012 at 04:25:05PM +0100, Paul Chavent wrote:
> This new version moves the skb_tx_timestamp in the main uml
> driver. This should avoid the need to call this function in each
> transport (vde, slirp, tuntap, ...). It also add support for ethtool
> get_ts_info.
>
> Signed-off-by: Paul Chavent <paul.chavent@onera.fr>
Acked-by: Richard Cochran <richardcochran@gmail.com>
^ permalink raw reply
* Re: [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Vlad Yasevich @ 2012-12-06 18:57 UTC (permalink / raw)
To: Thomas Graf; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <20121206184433.GE16122@casper.infradead.org>
On 12/06/2012 01:44 PM, Thomas Graf wrote:
> On 12/06/12 at 01:35pm, Vlad Yasevich wrote:
>> We may want to mark transports as dead sooner. Probably right about
>> the time we pull them off the list.
>
> We mark it dead in sctp_transport_free() which is called at the
> end of sctp_assoc_rm_peer(). Do you want to mark it dead at the
> beginning of sctp_assoc_rm_peer() as well? (We still need to
> mark in sctp_transport_free() anyway).
Crud.. sctp_transport_free() is called directly in places... Hmm...
the one in sctp_association_free() may need to be list_del_rcu()...
Ok, we can leave the dead handling the way it is..
-vlad
>
>> When displaying, we may want to
>> look at transport->dead, and skip them. It will reduce the probability
>> that we would be looking at a transport that's about to go away.
>
> Agreed.
>
^ permalink raw reply
* Re: [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Thomas Graf @ 2012-12-06 19:08 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <50C0EAB5.3050303@gmail.com>
On 12/06/12 at 01:57pm, Vlad Yasevich wrote:
> On 12/06/2012 01:44 PM, Thomas Graf wrote:
> >On 12/06/12 at 01:35pm, Vlad Yasevich wrote:
> >>We may want to mark transports as dead sooner. Probably right about
> >>the time we pull them off the list.
> >
> >We mark it dead in sctp_transport_free() which is called at the
> >end of sctp_assoc_rm_peer(). Do you want to mark it dead at the
> >beginning of sctp_assoc_rm_peer() as well? (We still need to
> >mark in sctp_transport_free() anyway).
>
> Crud.. sctp_transport_free() is called directly in places... Hmm...
> the one in sctp_association_free() may need to be list_del_rcu()...
It's not really needed but it wouldn't be wrong from a
documentation perspective. The assoc is always unhashed
while holding head->lock before sctp_association_free()
and all current RCU readers of transport_addr_list access
the the assoc while holding a read-lock on head->lock.
Let me respin this patch and do a list_del_rcu() there
to document the RCU'iness of it.
^ permalink raw reply
* Re: [PATCH] sctp: Add RCU protection to assoc->transport_addr_list
From: Vlad Yasevich @ 2012-12-06 19:14 UTC (permalink / raw)
To: Thomas Graf; +Cc: linux-sctp, netdev, Neil Horman
In-Reply-To: <20121206190835.GF16122@casper.infradead.org>
On 12/06/2012 02:08 PM, Thomas Graf wrote:
> On 12/06/12 at 01:57pm, Vlad Yasevich wrote:
>> On 12/06/2012 01:44 PM, Thomas Graf wrote:
>>> On 12/06/12 at 01:35pm, Vlad Yasevich wrote:
>>>> We may want to mark transports as dead sooner. Probably right about
>>>> the time we pull them off the list.
>>>
>>> We mark it dead in sctp_transport_free() which is called at the
>>> end of sctp_assoc_rm_peer(). Do you want to mark it dead at the
>>> beginning of sctp_assoc_rm_peer() as well? (We still need to
>>> mark in sctp_transport_free() anyway).
>>
>> Crud.. sctp_transport_free() is called directly in places... Hmm...
>> the one in sctp_association_free() may need to be list_del_rcu()...
>
> It's not really needed but it wouldn't be wrong from a
> documentation perspective. The assoc is always unhashed
> while holding head->lock before sctp_association_free()
> and all current RCU readers of transport_addr_list access
> the the assoc while holding a read-lock on head->lock.
>
> Let me respin this patch and do a list_del_rcu() there
> to document the RCU'iness of it.
>
Right, but there may be chunks that have cached association with a ref
before sctp_association_free() is called. Now, after free they may
be looking at the transport list for whatever reason... Most places
check assoc->dead, but I don't want to get caught. So, there is
a remote chance that someone may look at transports and would crash
without rcu.
-vlad
^ permalink raw reply
* Re: [PATCH] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
From: Neil Horman @ 2012-12-06 19:16 UTC (permalink / raw)
To: Thomas Graf; +Cc: Vlad Yasevich, linux-sctp, netdev
In-Reply-To: <20121206182840.GD16122@casper.infradead.org>
On Thu, Dec 06, 2012 at 06:28:40PM +0000, Thomas Graf wrote:
> On 12/06/12 at 01:25pm, Vlad Yasevich wrote:
> > May want to avoid printing addresses that are !addr->valid.
> >
> > Otherwise looks good.
>
> Good point, I'll send a follow-up patch if that is OK. Same
> applies to dead transports obviously.
Assuming a followup patch to avoid dead addresses..
Acked-by: Neil Horman <nhorman@tuxdriver.com>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH 0/2 v2] sctp: RCU protection when accessing assoc members for procfs
From: Thomas Graf @ 2012-12-06 19:25 UTC (permalink / raw)
To: linux-sctp; +Cc: netdev, vyasevich, nhorman
@Dave: This is a respin of the following patches:
[PATCH] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
[PATCH] sctp: Add RCU protection to assoc->transport_addr_list
Thomas Graf (2):
sctp: proc: protect bind_addr->address_list accesses with
rcu_read_lock()
sctp: Add RCU protection to assoc->transport_addr_list
include/net/sctp/structs.h | 2 ++
net/sctp/associola.c | 6 +++---
net/sctp/proc.c | 21 ++++++++++++++++++---
net/sctp/transport.c | 18 +++++++++++++-----
4 files changed, 36 insertions(+), 11 deletions(-)
--
1.7.11.7
^ permalink raw reply
* Re: [PATCH] net : enable tx time stamping in the vde driver.
From: Richard Weinberger @ 2012-12-06 19:25 UTC (permalink / raw)
To: Richard Cochran, Paul Chavent; +Cc: jdike, user-mode-linux-devel, netdev
In-Reply-To: <20121206185742.GA2175@netboy.at.omicron.at>
Richard Cochran <richardcochran@gmail.com> schrieb:
>On Thu, Dec 06, 2012 at 04:25:05PM +0100, Paul Chavent wrote:
>> This new version moves the skb_tx_timestamp in the main uml
>> driver. This should avoid the need to call this function in each
>> transport (vde, slirp, tuntap, ...). It also add support for ethtool
>> get_ts_info.
>>
>> Signed-off-by: Paul Chavent <paul.chavent@onera.fr>
>
>Acked-by: Richard Cochran <richardcochran@gmail.com>
Queued for 3.8.
Thanks,
//richard
^ permalink raw reply
* [PATCH 1/2] sctp: proc: protect bind_addr->address_list accesses with rcu_read_lock()
From: Thomas Graf @ 2012-12-06 19:25 UTC (permalink / raw)
To: linux-sctp; +Cc: netdev, vyasevich, nhorman, Thomas Graf
In-Reply-To: <cover.1354821623.git.tgraf@suug.ch>
From: Thomas Graf <tgraf@redhat.com>
address_list is protected via the socket lock or RCU. Since we don't want
to take the socket lock for each assoc we dump in procfs a RCU read-side
critical section must be entered.
V2: Skip local addresses marked as dead
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/sctp/proc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 9966e7b..06b05ee 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -139,7 +139,11 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
primary = &peer->saddr;
}
- list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
+ if (!laddr->valid)
+ continue;
+
addr = &laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
if (primary && af->cmp_addr(addr, primary)) {
@@ -147,6 +151,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
/* Dump remote addresses of an association. */
--
1.7.11.7
^ permalink raw reply related
* [PATCH 2/2] sctp: Add RCU protection to assoc->transport_addr_list
From: Thomas Graf @ 2012-12-06 19:25 UTC (permalink / raw)
To: linux-sctp; +Cc: netdev, vyasevich, nhorman
In-Reply-To: <cover.1354821623.git.tgraf@suug.ch>
peer.transport_addr_list is currently only protected by sk_sock
which is inpractical to acquire for procfs dumping purposes.
This patch adds RCU protection allowing for the procfs readers to
enter RCU read-side critical sections.
Modification of the list continues to be serialized via sk_lock.
V2: Use list_del_rcu() in sctp_association_free() to be safe
Skip transports marked dead when dumping for procfs
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
include/net/sctp/structs.h | 2 ++
net/sctp/associola.c | 6 +++---
net/sctp/proc.c | 14 ++++++++++++--
net/sctp/transport.c | 18 +++++++++++++-----
4 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 64158aa..5d6987b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -948,6 +948,8 @@ struct sctp_transport {
/* 64-bit random number sent with heartbeat. */
__u64 hb_nonce;
+
+ struct rcu_head rcu;
};
struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b1ef3bc..81b1236 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -445,7 +445,7 @@ void sctp_association_free(struct sctp_association *asoc)
/* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);
- list_del(pos);
+ list_del_rcu(pos);
sctp_transport_free(transport);
}
@@ -565,7 +565,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
sctp_assoc_update_retran_path(asoc);
/* Remove this peer from the list. */
- list_del(&peer->transports);
+ list_del_rcu(&peer->transports);
/* Get the first transport of asoc. */
pos = asoc->peer.transport_addr_list.next;
@@ -765,7 +765,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->state = peer_state;
/* Attach the remote transport to our asoc. */
- list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+ list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
asoc->peer.transport_count++;
/* If we do not yet have a primary path, set one. */
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 06b05ee..8c19e97 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -162,15 +162,20 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
struct sctp_af *af;
primary = &assoc->peer.primary_addr;
- list_for_each_entry(transport, &assoc->peer.transport_addr_list,
+ rcu_read_lock();
+ list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
transports) {
addr = &transport->ipaddr;
+ if (transport->dead)
+ continue;
+
af = sctp_get_af_specific(addr->sa.sa_family);
if (af->cmp_addr(addr, primary)) {
seq_printf(seq, "*");
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
@@ -441,12 +446,16 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
+ rcu_read_lock();
sctp_for_each_hentry(epb, node, &head->chain) {
if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
continue;
assoc = sctp_assoc(epb);
- list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
+ list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
transports) {
+ if (tsp->dead)
+ continue;
+
/*
* The remote address (ADDR)
*/
@@ -492,6 +501,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
}
}
+ rcu_read_unlock();
read_unlock(&head->lock);
sctp_local_bh_enable();
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 206cf52..1295aec 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
sctp_transport_put(transport);
}
-/* Destroy the transport data structure.
- * Assumes there are no more users of this structure.
- */
-static void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy_rcu(struct rcu_head *head)
{
- SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+ struct sctp_transport *transport;
+ transport = container_of(head, struct sctp_transport, rcu);
if (transport->asoc)
sctp_association_put(transport->asoc);
@@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
SCTP_DBG_OBJCNT_DEC(transport);
}
+/* Destroy the transport data structure.
+ * Assumes there are no more users of this structure.
+ */
+static void sctp_transport_destroy(struct sctp_transport *transport)
+{
+ SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+
+ call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+}
+
/* Start T3_rtx timer if it is not already running and update the heartbeat
* timer. This routine is called every time a DATA chunk is sent.
*/
--
1.7.11.7
^ permalink raw reply related
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