* Re: [PATCHv2] am33xx: cpsw: default to ethernet hwaddr from efuse if not defined in dt
From: Michal Bachraty @ 2013-01-18 8:26 UTC (permalink / raw)
To: Mugunthan V N
Cc: michal.bachraty-6oiIBCxl0MMjD8S081q9vkEOCMrvLtNR,
netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
richardcochran-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <50F8DA3A.3090406-l0cyMroinI0@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 1641 bytes --]
On Fri, Jan 18, 2013 at 6:14 AM, Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org> wrote:
> On 1/18/2013 3:48 AM, Peter Korsgaard wrote:
>
>> When booting with CONFIG_ARM_APPENDED_DTB (either because of using an old
>> U-Boot, not wanting the hassle of 2 files or when using Falcon fast boot
>> mode in U-Boot), nothing updates the ethernet hwaddr specified for the
>> CPSW slaves, causing the driver to use a random hwaddr, which is some
>> times
>> troublesome.
>>
>> The am33xx has unique ethernet hwaddrs programmed in the efuse, so it
>> makes
>> more sense to default to these rather than random ones. Add a fixup step
>> which adds mac-address dt properties using the efuse addresses if the DTB
>> didn't contain valid ones.
>>
>> Signed-off-by: Peter Korsgaard <jacmet-OfajU3CKLf1/SzgSGea1oA@public.gmane.org>
>>
>>
> This implementation looks fine.
> Acked-by: Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org>
>
> Regards
> Mugunthan V N
>
Thanks,
My approach for cpsw driver is posted here:
https://patchwork.kernel.org/patch/1966481/
I added DT option mac-address-source because there is still possiblility to
have mac address set by the u-boot in the future. Beaglebone have special
eeprom on board, were you can have stored user MAC and u-boot can read
eeprom
data. Maybe some users will want this feature. Also in cpsw dt binding
documentation, there is mention /* Filled in by U-Boot */. For that
purpose,
code I proposed can easily deal with any driver exteds.
Reading CPU mac address registers with (my approach) or without (your
approach) DT should be more discussed. Also your way seems to be fine.
[-- Attachment #1.2: Type: text/html, Size: 2435 bytes --]
[-- Attachment #2: Type: text/plain, Size: 192 bytes --]
_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply
* Re: [PATCH] net: usb: initialize tmp in dm9601.c to avoid warning
From: Peter Korsgaard @ 2013-01-18 8:44 UTC (permalink / raw)
To: David Miller; +Cc: sque, netdev, msb
In-Reply-To: <20130118.030341.2246222347501217868.davem@davemloft.net>
>>>>> "David" == David Miller <davem@davemloft.net> writes:
>> Sure, I just wondered as the code hasn't changed in 5+ years, and the
>> function that gets called is defined just above, so the compiler should
>> be able to figure it out.
David> Nothing guarentees that a piece of memory passed into an external
David> function has it's contents initialized completely by that function.
David> The compiler can't see what usbnet_read_cmd() does with the memory
David> behind the 'data' pointer argument. So it makes the only assumption
David> it can make, which is that 'tmp' might be uninitialized.
True, I had forgotten about the usbnet_read_cmd() change (which is the
change causing the warning). With that:
Acked-by: Peter Korsgaard <jacmet@sunsite.dk>
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [Patch net-next 3/2] xfrm: use separated locks to protect pointers of struct xfrm_state_afinfo
From: Steffen Klassert @ 2013-01-18 8:54 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, Herbert Xu, David S. Miller
In-Reply-To: <1358411651-3579-1-git-send-email-amwang@redhat.com>
On Thu, Jan 17, 2013 at 04:34:11PM +0800, Cong Wang wrote:
> (On top of my previous RCU convert patches)
>
> afinfo->type_map and afinfo->mode_map deserve separated locks,
> they are different things.
>
> We should just take RCU read lock to protect afinfo itself,
> but not for the inner pointers.
>
> Cc: Steffen Klassert <steffen.klassert@secunet.com>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: "David S. Miller" <davem@davemloft.net>
> Signed-off-by: Cong Wang <amwang@redhat.com>
All Aplied to ipsec-next, thanks!
^ permalink raw reply
* Re: [PATCH] net/xfrm/xfrm_replay: avoid division by zero
From: Steffen Klassert @ 2013-01-18 8:57 UTC (permalink / raw)
To: Nickolai Zeldovich; +Cc: Herbert Xu, David S. Miller, netdev, linux-kernel
In-Reply-To: <1358449108-67839-1-git-send-email-nickolai@csail.mit.edu>
On Thu, Jan 17, 2013 at 01:58:28PM -0500, Nickolai Zeldovich wrote:
> All of the xfrm_replay->advance functions in xfrm_replay.c check if
> x->replay_esn->replay_window is zero (and return if so). However,
> one of them, xfrm_replay_advance_bmp(), divides by that value (in the
> '%' operator) before doing the check, which can potentially trigger
> a divide-by-zero exception. Some compilers will also assume that the
> earlier division means the value cannot be zero later, and thus will
> eliminate the subsequent zero check as dead code.
>
> This patch moves the division to after the check.
>
> Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH v2] net: fix wrong length of mac address
From: Waskiewicz Jr, Peter P @ 2013-01-18 9:00 UTC (permalink / raw)
To: Amos Kong; +Cc: davem, kys, haiyangz, netdev, devel
In-Reply-To: <1358495514-18047-1-git-send-email-kongjianjun@gmail.com>
On Fri, Jan 18, 2013 at 03:51:54PM +0800, Amos Kong wrote:
> Typo, it should be ETH_ALEN.
>
> Signed-off-by: Amos Kong <kongjianjun@gmail.com>
> ---
> v2: update commitlog, fix cc list
> ---
> drivers/net/hyperv/netvsc_drv.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index f825a62..8264f0e 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -349,7 +349,7 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
> struct net_device_context *ndevctx = netdev_priv(ndev);
> struct hv_device *hdev = ndevctx->device_ctx;
> struct sockaddr *addr = p;
> - char save_adr[14];
> + char save_adr[ETH_ALEN];
> unsigned char save_aatype;
> int err;
While you're at it, you should fix drivers/net/hyperv/hyperv_net.h:
struct netvsc_device_info {
>>> unsigned char mac_adr[6];
bool link_state; /* 0 - link up, 1 - link down */
int ring_size;
};
Cheers,
-PJ
^ permalink raw reply
* [patch v3] doc: add nf_conntrack sysctl api documentation
From: Jiri Pirko @ 2013-01-18 9:05 UTC (permalink / raw)
To: netdev
Cc: davem, rob, linux-doc, kuznet, jmorris, yoshfuji, pablo,
netfilter-devel, netfilter, coreteam, fw
I grepped through the code and picked bits about nf_conntrack sysctl api
and put that into one documentation file.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
v2->v3:
processed in changes suggested by Pablo Neira Ayuso
v1->v2:
processed in changes suggested by Florian Westphal
Documentation/networking/nf_conntrack-sysctl.txt | 177 +++++++++++++++++++++++
1 file changed, 177 insertions(+)
create mode 100644 Documentation/networking/nf_conntrack-sysctl.txt
diff --git a/Documentation/networking/nf_conntrack-sysctl.txt b/Documentation/networking/nf_conntrack-sysctl.txt
new file mode 100644
index 0000000..11e450e
--- /dev/null
+++ b/Documentation/networking/nf_conntrack-sysctl.txt
@@ -0,0 +1,177 @@
+/proc/sys/net/netfilter/nf_conntrack_* Variables:
+
+nf_conntrack_acct - BOOLEAN
+ 0 - disabled (default)
+ not 0 - enabled
+
+ Enable connection tracking flow accounting. 64-bits byte and packet
+ counters per flow are added.
+
+nf_conntrack_buckets - INTEGER (read-only)
+ Size of hash table. Value depends on total memory size according to
+ following rules:
+ Use 1/16384 of memory.
+ If memory size is bigger than 1GB have 16384 buckets.
+ Minimum value is 32.
+
+nf_conntrack_checksum - BOOLEAN
+ 0 - disabled
+ not 0 - enabled (default)
+
+ Verify checksum of incoming packets. Packets with bad checksum
+ will not be considered for connection tracking, i.e. such packets
+ will be in INVALID state.
+
+nf_conntrack_count - INTEGER (read-only)
+ Number of currently allocated flow entries.
+
+nf_conntrack_events - BOOLEAN
+ 0 - disabled
+ not 0 - enabled (default)
+
+ If this option is enabled, the connection tracking code will
+ provide userspace with connection tracking events via ctnetlink.
+
+nf_conntrack_events_retry_timeout - INTEGER (seconds)
+ default 15
+
+ This option is only relevant when "reliable connection tracking
+ events" are used. Normally, ctnetlink is "lossy", i.e. when
+ userspace listeners can't keep up, events are dropped.
+
+ Userspace can request "reliable event mode". When this mode is
+ active, the conntrack will only be destroyed after the event was
+ delivered. If event delivery fails, the kernel periodically
+ re-tries to send the event to userspace.
+
+ This is the maximum interval the kernel should use when re-trying
+ to deliver the destroy event.
+
+ Higher number means less delivery re-tries (but it will then take
+ longer for a backlog to be processed).
+
+nf_conntrack_expect_max - INTEGER
+ Maximum size of expectation table. Default value is
+ nf_conntrack_buckets / 256. Minimum is 1.
+
+nf_conntrack_frag6_high_thresh - INTEGER
+ default 262144
+
+ Maximum memory used to reassemble IPv6 fragments. When
+ nf_conntrack_frag6_high_thresh bytes of memory is allocated for this
+ purpose, the fragment handler will toss packets until
+ nf_conntrack_frag6_low_thresh is reached.
+
+nf_conntrack_frag6_low_thresh - INTEGER
+ default 196608
+
+ See nf_conntrack_frag6_low_thresh
+
+nf_conntrack_frag6_timeout - INTEGER (seconds)
+ default 60
+
+ Time to keep an IPv6 fragment in memory.
+
+nf_conntrack_generic_timeout - INTEGER (seconds)
+ default 600
+
+ Default for generic timeout. This refers to layer 4 unknown/unsupported
+ protocols.
+
+nf_conntrack_helper - BOOLEAN
+ 0 - disabled
+ not 0 - enabled (default)
+
+ Enable automatic conntrack helper assignment.
+
+nf_conntrack_icmp_timeout - INTEGER (seconds)
+ default 30
+
+ Default for ICMP timeout.
+
+nf_conntrack_icmpv6_timeout - INTEGER (seconds)
+ default 30
+
+ Default for ICMP6 timeout.
+
+nf_conntrack_log_invalid - INTEGER
+ 0 - disable (default)
+ 1 - log ICMP packets
+ 6 - log TCP packets
+ 17 - log UDP packets
+ 33 - log DCCP packets
+ 41 - log ICMPv6 packets
+ 136 - log UDPLITE packets
+ 255 - log packets of any protocol
+
+ Log invalid packets of a type specified by value.
+
+nf_conntrack_max - INTEGER
+ Size of connection tracking table. Default value is
+ nf_conntrack_buckets value * 4.
+
+nf_conntrack_tcp_be_liberal - BOOLEAN
+ 0 - disabled (default)
+ not 0 - enabled
+
+ Be conservative in what you do, be liberal in what you accept from others.
+ If it's non-zero, we mark only out of window RST segments as INVALID.
+
+nf_conntrack_tcp_loose - BOOLEAN
+ 0 - disabled
+ not 0 - enabled (default)
+
+ If it is set to zero, we disable picking up already established
+ connections.
+
+nf_conntrack_tcp_max_retrans - INTEGER
+ default 3
+
+ Max number of the retransmitted packets without receiving an
+ (acceptable) ACK from the destination. If this number is reached,
+ a shorter timer will be started.
+
+nf_conntrack_tcp_timeout_close - INTEGER (seconds)
+ default 10
+
+nf_conntrack_tcp_timeout_close_wait - INTEGER (seconds)
+ default 60
+
+nf_conntrack_tcp_timeout_established - INTEGER (seconds)
+ default 432000 (5 days)
+
+nf_conntrack_tcp_timeout_fin_wait - INTEGER (seconds)
+ default 120
+
+nf_conntrack_tcp_timeout_last_ack - INTEGER (seconds)
+ default 30
+
+nf_conntrack_tcp_timeout_max_retrans - INTEGER (seconds)
+ default 300
+
+nf_conntrack_tcp_timeout_syn_recv - INTEGER (seconds)
+ default 60
+
+nf_conntrack_tcp_timeout_syn_sent - INTEGER (seconds)
+ default 120
+
+nf_conntrack_tcp_timeout_time_wait - INTEGER (seconds)
+ default 120
+
+nf_conntrack_tcp_timeout_unacknowledged - INTEGER (seconds)
+ default 300
+
+nf_conntrack_timestamp - BOOLEAN
+ 0 - disabled (default)
+ not 0 - enabled
+
+ Enable connection tracking flow timestamping.
+
+nf_conntrack_udp_timeout - INTEGER (seconds)
+ default 30
+
+nf_conntrack_udp_timeout_stream2 - INTEGER (seconds)
+ default 180
+
+ This extended timeout will be used in case there is an UDP stream
+ detected.
--
1.8.1
^ permalink raw reply related
* Re: Wake on LAN for USB ethernet?
From: Petko Manolov @ 2013-01-18 8:53 UTC (permalink / raw)
To: Ming Lei
Cc: Sarah Sharp, linux-usb, netdev, Petko Manolov, Alan Stern,
Greg KH, Oliver Neukum
In-Reply-To: <CACVXFVOtpzOFAGRJ74XP1NFD1ah_au9e9gqHFiBLuv1jAwZ6cQ@mail.gmail.com>
The code in the driver is based on the specs from ADMTek (later,
Infineon). Since i never suspend my machines this feature has not been
tested by me.
However, if the proposed patch is the right thing to do i'd be happy to
see it applied.
cheers,
Petko
On Fri, 18 Jan 2013, Ming Lei wrote:
> On Fri, Jan 18, 2013 at 8:12 AM, Sarah Sharp
> <sarah.a.sharp@linux.intel.com> wrote:
>> Is it reasonable to expect that Wake on LAN works if the target box is
>> connected via a USB-to-ethernet adapter?
>
> It is surely reasonable, and seems SMSC75xx or SMSC95xx can
> bring system out of suspend.
>
>>
>> One of my validation testers has a USB ethernet device that successfully
>> wakes up Windows from hibernate (S4), but it doesn't work under Linux.
>> Wake on LAN works fine with the hardwired ethernet port. USB remote
>> wakeup from S3/S4 works fine with a USB keyboard.
>>
>> So I need to figure out if it's an issue with the kernel, their test
>> suite, or the USB host controller.
>>
>>
>> I've experimented with USB ethernet devices with the pegasus driver with
>> no success. Here's what I've tried:
>>
>> 1. Connect the USB to ethernet adapter to the rootport under the xHCI
>> (USB 3.0) host controller. (lsusb for the two devices I've tried is
>> attached)
>>
>> 2. Enable remote wakeup for all devices (including the PCI host) by
>> echoing 'enabled' to power/wakeup. (script for that attached)
>>
>> 3. Use ethtool to turn on WOL:
>> sudo ethtool -s ethX wol g
>
> Could you check here if the attribute 'power/wakeup' of the USB device
> has been enabled? If so, and step 6 still can't wakeup system, the
> problem may be in the set_wol stetting on hardware of the driver since
> your USB wakeup works.
>
> Also, the wakeup enabling is missed in the pegasus_set_wol(), and
> the below patch is needed:
>
> diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
> index a0b5807..d5304f1 100644
> --- a/drivers/net/usb/pegasus.c
> +++ b/drivers/net/usb/pegasus.c
> @@ -1096,6 +1096,7 @@ pegasus_set_wol(struct net_device *dev, struct
> ethtool_wolinfo *wol)
> {
> pegasus_t *pegasus = netdev_priv(dev);
> u8 reg78 = 0x04;
> + int ret;
>
> if (wol->wolopts & ~WOL_SUPPORTED)
> return -EINVAL;
> @@ -1110,7 +1111,11 @@ pegasus_set_wol(struct net_device *dev, struct
> ethtool_wolinfo *wol)
> else
> pegasus->eth_regs[0] &= ~0x10;
> pegasus->wolopts = wol->wolopts;
> - return set_register(pegasus, WakeupControl, reg78);
> +
> + ret = set_register(pegasus, WakeupControl, reg78);
> + if (!ret)
> + ret = device_set_wakeup_enable(&pegasus->usb->dev, 1);
> + return ret;
> }
>
> static inline void pegasus_reset_wol(struct net_device *dev)
>
>
>>
>> 4. Find the MAC address by running ifconfig and looking at the HWaddr
>> field.
>>
>> 5. Verify with wireshark that I can see the Magic WOL packet when I run
>> this command on another machine:
>> sudo etherwake -i ethX macaddr
>>
>> 6. Suspend or hibernate the target machine, and then send the Magic WOL
>> packet from a second machine.
>>
>>
>> Am I missing any steps in testing this? Does WOL just not work for USB
>> ethernet devices under Linux? Perhaps just the pegasus driver doesn't
>> support WOL?
>
> Probably the set_wol of pegasus is broken if wakeup has been enabled
> on the USB device.
>
> Thanks,
> --
> Ming Lei
>
^ permalink raw reply
* RE: [PATCH for 3.8] iproute2: Add "ip netns pids" and "ip netns identify"
From: David Laight @ 2013-01-18 9:41 UTC (permalink / raw)
To: Eric W. Biederman, Ben Hutchings
Cc: Stephen Hemminger, netdev, Serge E. Hallyn
In-Reply-To: <87mww71drv.fsf@xmission.com>
> >> >> + if (!isdigit(ch))
> >> >
> >> > ch must be cast to unsigned char before passing to isdigit().
> >>
> >> isdigit is defined to take an int. A legacy of the implicit casts in
> >> the K&R C days. Casting to unsigned char would be pointless and silly.
> > [...]
> >
> > It's not pointless. This is explained in the very first line of the
> > description in the manual page...
>
> If it's not pointless it is an implementation bug. The conversion to of
> char to int happens implicitly whenever you pass a char. It is
> absolutely broken to have a function that takes a char converted to int
> and reject the automatic conversion of char to int.
>
> I suspect much more strongly that it is a case of poor documentation.
All of the isxxxx() functions have an input domain of EOF and all the
values of 'char' cast to unsigned (I've forgotten the exact words).
Passing in a value that is outside the domain has an undefined effect
and is very likely to generate a core dump, even if it doesn't
dump, the returned value is likely to be wrong.
This input value matches the values returned by the stdio getc()
functions and getopt().
> If isdigit can't deal with what I have passed it I will be much more
> interested in writing a patch for isdigit.
The traditional/expected implementation of the isxxx() functions is
a macro expansion that indexes an array and checks for some bits.
gcc even has a warning about indexing arrays with 'char' that,
I suspect, is there to detect incorrect uses of the isxxx() functions.
> That said I just dobule checked with the code below. Negative character
> values work correctly and don't cause any runtime errors.
The fact that one specific piece of code appears to work doesn't mean
that all such code will work - it won't.
In any case the functions have to differentiate between EOF and
the 256 valid values of 'char'. EOF (more or less) has to be -1
so the char bit pattern 0xff must not become -1 (it passes
isprint() in at least some locales).
I've had to do a trawl through a large amount of user code fixing
the buggy calls to the isxxxx() functions. Interestingly I didn't
actually find any code that could pass EOF as an argument!
David
^ permalink raw reply
* RE: [PATCH v2] [iproute] ipxfrm: use alloca to allocate stack space
From: David Laight @ 2013-01-18 10:00 UTC (permalink / raw)
To: Mike Frysinger, stephen.hemminger, netdev
In-Reply-To: <1358481650-20816-1-git-send-email-vapier@gentoo.org>
> Clang doesn't support the gcc extension for embeddeding flexible arrays
> inside of structures. Use the slightly more portable alloca().
>
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> ---
> v2
> - use alloca rather than flexible arrays in structures
...
> +#include <alloca.h>
I'm not sure what happens in Linux, but alloca.h is likely
to try to use the libc version of alloca().
While that worked 20 years ago, these days compilers then
to use %sp relative addressing so you must only use the
compiler builtin alloca() code.
With gcc, compiling with -std=c89 (I think that is the one)
causes the builtin alloca() not to be defined.
By default alloca() is part of the language and the header
isn't needed.
Use of alloca() also stops some of the stack overwrite
protection being enabled.
In this case I suspect malloc() and free() is best.
(Or change the called function ...)
David
^ permalink raw reply
* [PATCH 2/4] net: ethernet: davinci_cpdma: fix descriptor handling
From: Sebastian Andrzej Siewior @ 2013-01-18 10:06 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Thomas Gleixner, Rakesh Ranjan, Bruno Bittner,
stable, Holger Dengler, Jan Altenberg, Sebastian Andrzej Siewior
In-Reply-To: <1358503572-5057-1-git-send-email-sebastian@breakpoint.cc>
From: Thomas Gleixner <tglx@linutronix.de>
According to the datasheet there is a miss-queued buffer condition
handling required in the processing. This is implemented correctly
when descriptors are queued for TX, but during TX cleanup of already
transmitted descriptors the condition is not handled correctly. That
leads to a stall of the TX queue which fills up and never gets processed.
Cc: Rakesh Ranjan <rakesh.ranjan@vnl.in>
Cc: Bruno Bittner <Bruno.Bittner@sick.com>
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[dengler: patch description]
Signed-off-by: Holger Dengler <dengler@linutronix.de>
[jan: forward ported]
Signed-off-by: Jan Altenberg <jan@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/net/ethernet/ti/davinci_cpdma.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index dd5f2db..709c437 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -756,7 +756,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
chan->count--;
chan->stats.good_dequeue++;
- if (status & CPDMA_DESC_EOQ) {
+ if ((status & CPDMA_DESC_EOQ) && (chan->head) &&
+ (!(status & CPDMA_DESC_TD_COMPLETE))) {
chan->stats.requeue++;
chan_write(chan, hdp, desc_phys(pool, chan->head));
}
--
1.7.6.5
^ permalink raw reply related
* [PATCH 4/4] net: ethernet: ti cpsw: separate interrupt handler for TX, RX, and MISC
From: Sebastian Andrzej Siewior @ 2013-01-18 10:06 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Thomas Gleixner, Mugunthan V N, Rakesh Ranjan,
Bruno Bittner, stable, Holger Dengler, Jan Altenberg,
Sebastian Andrzej Siewior
In-Reply-To: <1358503572-5057-1-git-send-email-sebastian@breakpoint.cc>
From: Thomas Gleixner <tglx@linutronix.de>
The interrupt handling of the device is using the same interrupt
handler function for all possible device interrupts.
If an host error interrupt is raised (misc), then it merily switches
the device driver into NAPI scheduling mode which is completely
pointless since neither RX nor TX completes. It also fails to give
any information about the reason for this host error interrupt.
The solution for this problem is to provide separate interrupt
handlers for RX, TX and the error (misc) interrupt.
This allows at least to print out the host error reason even if we
have no error handling mechanisms there yet. Though it allowed us
to pinpoint the main problem as we had the information what kind of
error the DMA engine run into.
The patch also clean ups the complete TX queue. It was observed that
sometimes the EOI ack for RX queue also ACKed TX packets which were
not-yet processed. This lead to TX stall.
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Cc: Rakesh Ranjan <rakesh.ranjan@vnl.in>
Cc: Bruno Bittner <Bruno.Bittner@sick.com>
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[dengler: patch description]
Signed-off-by: Holger Dengler <dengler@linutronix.de>
[jan: forward ported]
Signed-off-by: Jan Altenberg <jan@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/net/ethernet/ti/cpsw.c | 249 ++++++++++++++++++++++++++-----
drivers/net/ethernet/ti/davinci_cpdma.c | 31 +++-
drivers/net/ethernet/ti/davinci_cpdma.h | 5 +-
3 files changed, 236 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 40aff68..ee4533d 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -118,6 +118,13 @@ do { \
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x76543210
+enum {
+ CPSW_IRQ_TYPE_RX_THRESH,
+ CPSW_IRQ_TYPE_RX,
+ CPSW_IRQ_TYPE_TX,
+ CPSW_IRQ_TYPE_MISC,
+};
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -312,9 +319,12 @@ struct cpsw_priv {
struct cpdma_ctlr *dma;
struct cpdma_chan *txch, *rxch;
struct cpsw_ale *ale;
+ bool rx_irqs_disabled;
+ bool tx_irqs_disabled;
+ bool misc_irqs_disabled;
/* snapshot of IRQ numbers */
- u32 irqs_table[4];
- u32 num_irqs;
+ u32 irqs_table[4];
+ u32 num_irqs;
struct cpts cpts;
};
@@ -350,21 +360,93 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
}
}
-static void cpsw_intr_enable(struct cpsw_priv *priv)
+static void cpsw_intr_rx_enable(struct cpsw_priv *priv)
+{
+ __raw_writel(0x01, &priv->wr_regs->rx_en);
+ cpdma_chan_int_ctrl(priv->rxch, true);
+ return;
+}
+
+static void cpsw_intr_rx_disable(struct cpsw_priv *priv)
+{
+ __raw_writel(0x00, &priv->wr_regs->rx_en);
+ cpdma_chan_int_ctrl(priv->rxch, false);
+ return;
+}
+
+static void cpsw_intr_tx_enable(struct cpsw_priv *priv)
+{
+ __raw_writel(0x01, &priv->wr_regs->tx_en);
+ cpdma_chan_int_ctrl(priv->txch, true);
+ return;
+}
+
+static void cpsw_intr_tx_disable(struct cpsw_priv *priv)
{
- __raw_writel(0xFF, &priv->wr_regs->tx_en);
- __raw_writel(0xFF, &priv->wr_regs->rx_en);
+ __raw_writel(0x00, &priv->wr_regs->tx_en);
+ cpdma_chan_int_ctrl(priv->txch, false);
+ return;
+}
+static void cpsw_intr_misc_enable(struct cpsw_priv *priv)
+{
+ __raw_writel(0x04, &priv->wr_regs->misc_en);
cpdma_ctlr_int_ctrl(priv->dma, true);
return;
}
+static void cpsw_intr_misc_disable(struct cpsw_priv *priv)
+{
+ __raw_writel(0x00, &priv->wr_regs->misc_en);
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+}
+
+static void cpsw_intr_enable(struct cpsw_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->rx_irqs_disabled) {
+ enable_irq(priv->irqs_table[CPSW_IRQ_TYPE_RX]);
+ priv->rx_irqs_disabled = false;
+ }
+ if (priv->tx_irqs_disabled) {
+ enable_irq(priv->irqs_table[CPSW_IRQ_TYPE_TX]);
+ priv->tx_irqs_disabled = false;
+ }
+ if (priv->misc_irqs_disabled) {
+ enable_irq(priv->irqs_table[CPSW_IRQ_TYPE_MISC]);
+ priv->misc_irqs_disabled = false;
+ }
+ cpsw_intr_rx_enable(priv);
+ cpsw_intr_tx_enable(priv);
+ cpsw_intr_misc_enable(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
static void cpsw_intr_disable(struct cpsw_priv *priv)
{
- __raw_writel(0, &priv->wr_regs->tx_en);
- __raw_writel(0, &priv->wr_regs->rx_en);
+ unsigned long flags;
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->rx_irqs_disabled) {
+ disable_irq_nosync(priv->irqs_table[CPSW_IRQ_TYPE_RX]);
+ priv->rx_irqs_disabled = true;
+ }
+ if (!priv->tx_irqs_disabled) {
+ disable_irq_nosync(priv->irqs_table[CPSW_IRQ_TYPE_TX]);
+ priv->tx_irqs_disabled = true;
+ }
+ if (!priv->misc_irqs_disabled) {
+ disable_irq_nosync(priv->irqs_table[CPSW_IRQ_TYPE_MISC]);
+ priv->misc_irqs_disabled = true;
+ }
- cpdma_ctlr_int_ctrl(priv->dma, false);
+ cpsw_intr_rx_disable(priv);
+ cpsw_intr_tx_disable(priv);
+ cpsw_intr_misc_disable(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
return;
}
@@ -422,15 +504,57 @@ void cpsw_rx_handler(void *token, int len, int status)
WARN_ON(ret < 0);
}
-static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
+static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
{
struct cpsw_priv *priv = dev_id;
+ unsigned long flags;
- if (likely(netif_running(priv->ndev))) {
- cpsw_intr_disable(priv);
- cpsw_disable_irq(priv);
+ spin_lock_irqsave(&priv->lock, flags);
+ disable_irq_nosync(irq);
+ priv->rx_irqs_disabled = true;
+ cpsw_intr_rx_disable(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (netif_running(priv->ndev))
napi_schedule(&priv->napi);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
+{
+ struct cpsw_priv *priv = dev_id;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ disable_irq_nosync(irq);
+ priv->tx_irqs_disabled = true;
+ cpsw_intr_tx_disable(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (netif_running(priv->ndev))
+ napi_schedule(&priv->napi);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_misc_interrupt(int irq, void *dev_id)
+{
+ struct cpsw_priv *priv = dev_id;
+ unsigned long flags;
+
+ if (!netif_running(priv->ndev)) {
+ spin_lock_irqsave(&priv->lock, flags);
+ disable_irq_nosync(irq);
+ priv->misc_irqs_disabled = true;
+ cpsw_intr_misc_disable(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return IRQ_HANDLED;
}
+
+ printk(KERN_ERR "Host error: %x\n", cpdma_get_host_state(priv->dma));
+ cpdma_ctlr_misc_eoi(priv->dma);
+
return IRQ_HANDLED;
}
@@ -445,20 +569,39 @@ static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
static int cpsw_poll(struct napi_struct *napi, int budget)
{
struct cpsw_priv *priv = napi_to_priv(napi);
- int num_tx, num_rx;
+ int num_rx = 0;
+ int txcnt = 0;
+ int tx;
+ unsigned long flags;
- num_tx = cpdma_chan_process(priv->txch, 128);
- num_rx = cpdma_chan_process(priv->rxch, budget);
-
- if (num_rx || num_tx)
- cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
- num_rx, num_tx);
+ /* cleanup the complete TX queue */
+ do {
+ tx = cpdma_chan_process(priv->txch, 128);
+ if (tx > 0)
+ txcnt += tx;
+ } while (tx == 128);
+ if (txcnt) {
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->tx_irqs_disabled == true) {
+ cpsw_intr_tx_enable(priv);
+ cpdma_ctlr_tx_eoi(priv->dma);
+ enable_irq(priv->irqs_table[CPSW_IRQ_TYPE_TX]);
+ priv->tx_irqs_disabled = false;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ num_rx = cpdma_chan_process(priv->rxch, budget);
if (num_rx < budget) {
- napi_complete(napi);
- cpsw_intr_enable(priv);
- cpdma_ctlr_eoi(priv->dma);
- cpsw_enable_irq(priv);
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->rx_irqs_disabled == true) {
+ napi_complete(napi);
+ cpsw_intr_rx_enable(priv);
+ cpdma_ctlr_rx_eoi(priv->dma);
+ enable_irq(priv->irqs_table[CPSW_IRQ_TYPE_RX]);
+ priv->rx_irqs_disabled = false;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return num_rx;
@@ -679,7 +822,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpdma_ctlr_start(priv->dma);
cpsw_intr_enable(priv);
napi_enable(&priv->napi);
- cpdma_ctlr_eoi(priv->dma);
+ cpdma_ctlr_rx_eoi(priv->dma);
+ cpdma_ctlr_tx_eoi(priv->dma);
return 0;
}
@@ -702,7 +846,6 @@ static int cpsw_ndo_stop(struct net_device *ndev)
napi_disable(&priv->napi);
netif_carrier_off(priv->ndev);
cpsw_intr_disable(priv);
- cpdma_ctlr_int_ctrl(priv->dma, false);
cpdma_ctlr_stop(priv->dma);
cpsw_ale_stop(priv->ale);
for_each_slave(priv, cpsw_slave_stop, priv);
@@ -896,12 +1039,11 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
cpsw_err(priv, tx_err, "transmit timeout, restarting dma\n");
priv->stats.tx_errors++;
cpsw_intr_disable(priv);
- cpdma_ctlr_int_ctrl(priv->dma, false);
cpdma_chan_stop(priv->txch);
cpdma_chan_start(priv->txch);
- cpdma_ctlr_int_ctrl(priv->dma, true);
cpsw_intr_enable(priv);
- cpdma_ctlr_eoi(priv->dma);
+ cpdma_ctlr_rx_eoi(priv->dma);
+ cpdma_ctlr_tx_eoi(priv->dma);
}
static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev)
@@ -916,11 +1058,11 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
struct cpsw_priv *priv = netdev_priv(ndev);
cpsw_intr_disable(priv);
- cpdma_ctlr_int_ctrl(priv->dma, false);
- cpsw_interrupt(ndev->irq, priv);
- cpdma_ctlr_int_ctrl(priv->dma, true);
+ cpsw_rx_interrupt(priv->irqs_table[CPSW_IRQ_TYPE_RX], priv);
+ cpsw_tx_interrupt(priv->irqs_table[CPSW_IRQ_TYPE_TX], priv);
cpsw_intr_enable(priv);
- cpdma_ctlr_eoi(priv->dma);
+ cpdma_ctlr_rx_eoi(priv->dma);
+ cpdma_ctlr_tx_eoi(priv->dma);
}
#endif
@@ -1333,17 +1475,37 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_ale_ret;
}
+ priv->num_irqs = 0;
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
- for (i = res->start; i <= res->end; i++) {
- if (request_irq(i, cpsw_interrupt, IRQF_DISABLED,
+ i = res->start;
+ switch (k) {
+ case CPSW_IRQ_TYPE_RX_THRESH:
+ i = 0;
+ break;
+ case CPSW_IRQ_TYPE_RX:
+ if (request_irq(i, cpsw_rx_interrupt, 0,
dev_name(&pdev->dev), priv)) {
dev_err(priv->dev, "error attaching irq\n");
- goto clean_ale_ret;
+ goto clean_irq_ret;
}
- priv->irqs_table[k] = i;
- priv->num_irqs = k;
+ break;
+ case CPSW_IRQ_TYPE_TX:
+ if (request_irq(i, cpsw_tx_interrupt, 0,
+ dev_name(&pdev->dev), priv)) {
+ dev_err(priv->dev, "error attaching irq\n");
+ goto clean_irq_ret;
+ }
+ break;
+ case CPSW_IRQ_TYPE_MISC:
+ if (request_irq(i, cpsw_misc_interrupt, 0,
+ dev_name(&pdev->dev), priv)) {
+ dev_err(priv->dev, "error attaching irq\n");
+ goto clean_irq_ret;
+ }
+ break;
}
- k++;
+ priv->irqs_table[k++] = i;
+ priv->num_irqs = k;
}
ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
@@ -1371,7 +1533,10 @@ static int cpsw_probe(struct platform_device *pdev)
return 0;
clean_irq_ret:
- free_irq(ndev->irq, priv);
+ for (i = 0; i < priv->num_irqs; i++) {
+ if (priv->irqs_table[i] > 0)
+ free_irq(priv->irqs_table[i], priv);
+ }
clean_ale_ret:
cpsw_ale_destroy(priv->ale);
clean_dma_ret:
@@ -1402,12 +1567,16 @@ static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
+ int i;
pr_info("removing device");
platform_set_drvdata(pdev, NULL);
cpts_unregister(&priv->cpts);
- free_irq(ndev->irq, priv);
+ for (i = 0; i < priv->num_irqs; i++) {
+ if (priv->irqs_table[i] > 0)
+ free_irq(priv->irqs_table[i], priv);
+ }
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 70325cd..8c7c589 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -479,7 +479,7 @@ EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
{
unsigned long flags;
- int i, reg;
+ int reg;
spin_lock_irqsave(&ctlr->lock, flags);
if (ctlr->state != CPDMA_STATE_ACTIVE) {
@@ -489,20 +489,35 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
-
- for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
- if (ctlr->channels[i])
- cpdma_chan_int_ctrl(ctlr->channels[i], enable);
- }
-
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl);
+
+u32 cpdma_get_host_state(struct cpdma_ctlr *ctlr)
+{
+ return dma_reg_read(ctlr, CPDMA_DMASTATUS);
+}
+EXPORT_SYMBOL_GPL(cpdma_get_host_state);
+
+void cpdma_ctlr_rx_eoi(struct cpdma_ctlr *ctlr)
+{
+ dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 1);
+}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_rx_eoi);
+
+void cpdma_ctlr_tx_eoi(struct cpdma_ctlr *ctlr)
+{
+ dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 2);
+}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_tx_eoi);
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
+void cpdma_ctlr_misc_eoi(struct cpdma_ctlr *ctlr)
{
dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
+ dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 3);
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_misc_eoi);
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
cpdma_handler_fn handler)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index afa19a0..083a0cc 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -86,8 +86,11 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
int cpdma_chan_process(struct cpdma_chan *chan, int quota);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
+void cpdma_ctlr_rx_eoi(struct cpdma_ctlr *ctlr);
+void cpdma_ctlr_tx_eoi(struct cpdma_ctlr *ctlr);
+void cpdma_ctlr_misc_eoi(struct cpdma_ctlr *ctlr);
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
+u32 cpdma_get_host_state(struct cpdma_ctlr *ctlr);
enum cpdma_control {
CPDMA_CMD_IDLE, /* write-only */
--
1.7.6.5
^ permalink raw reply related
* [PATCH 3/4] net: ethernet: ti cpsw: Split up DMA descriptor pool
From: Sebastian Andrzej Siewior @ 2013-01-18 10:06 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Thomas Gleixner, Rakesh Ranjan, Bruno Bittner,
Holger Dengler, Jan Altenberg, Sebastian Andrzej Siewior
In-Reply-To: <1358503572-5057-1-git-send-email-sebastian@breakpoint.cc>
From: Thomas Gleixner <tglx@linutronix.de>
Split the buffer pool into a RX and a TX block so neither of the
channels can influence the other. It is possible to fillup the pool by
sending a lot of large packets on a slow half-duplex link.
Cc: Rakesh Ranjan <rakesh.ranjan@vnl.in>
Cc: Bruno Bittner <Bruno.Bittner@sick.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[dengler: patch description]
Signed-off-by: Holger Dengler <dengler@linutronix.de>
[jan: forward ported]
Signed-off-by: Jan Altenberg <jan@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/net/ethernet/ti/davinci_cpdma.c | 35 +++++++++++++++++++++++++++---
1 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 709c437..70325cd 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -217,16 +217,41 @@ desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
}
static struct cpdma_desc __iomem *
-cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
+cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc, bool is_rx)
{
unsigned long flags;
int index;
struct cpdma_desc __iomem *desc = NULL;
+ static int last_index = 4096;
spin_lock_irqsave(&pool->lock, flags);
- index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
- num_desc, 0);
+ /*
+ * The pool is split into two areas rx and tx. So we make sure
+ * that we can't run out of pool buffers for RX when TX has
+ * tons of stuff queued.
+ */
+ if (is_rx) {
+ index = bitmap_find_next_zero_area(pool->bitmap,
+ pool->num_desc/2, 0, num_desc, 0);
+ } else {
+ if (last_index >= pool->num_desc)
+ last_index = pool->num_desc / 2;
+
+ index = bitmap_find_next_zero_area(pool->bitmap,
+ pool->num_desc, last_index, num_desc, 0);
+
+ if (!(index < pool->num_desc)) {
+ index = bitmap_find_next_zero_area(pool->bitmap,
+ pool->num_desc, pool->num_desc/2, num_desc, 0);
+ }
+
+ if (index < pool->num_desc)
+ last_index = index + 1;
+ else
+ last_index = pool->num_desc / 2;
+ }
+
if (index < pool->num_desc) {
bitmap_set(pool->bitmap, index, num_desc);
desc = pool->iomap + pool->desc_size * index;
@@ -660,6 +685,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
unsigned long flags;
u32 mode;
int ret = 0;
+ bool is_rx;
spin_lock_irqsave(&chan->lock, flags);
@@ -668,7 +694,8 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
goto unlock_ret;
}
- desc = cpdma_desc_alloc(ctlr->pool, 1);
+ is_rx = (chan->rxfree != 0);
+ desc = cpdma_desc_alloc(ctlr->pool, 1, is_rx);
if (!desc) {
chan->stats.desc_alloc_fail++;
ret = -ENOMEM;
--
1.7.6.5
^ permalink raw reply related
* [PATCH 1/4] net: ethernet: davinci cpdma: Enable interrupt while waiting for teardown complete
From: Sebastian Andrzej Siewior @ 2013-01-18 10:06 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Thomas Gleixner, Rakesh Ranjan, Bruno Bittner,
Holger Dengler, Jan Altenberg, Sebastian Andrzej Siewior
From: Thomas Gleixner <tglx@linutronix.de>
A teardown might take some time. If the other CPU is going to queue
something it will spin and wait. Dropping the lock will allow to
continue processing. It will notice that the channel is in state
teardown and will not do anything.
Cc: Rakesh Ranjan <rakesh.ranjan@vnl.in>
Cc: Bruno Bittner <Bruno.Bittner@sick.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[dengler: patch description]
Signed-off-by: Holger Dengler <dengler@linutronix.de>
[jan: forward ported]
Signed-off-by: Jan Altenberg <jan@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/net/ethernet/ti/davinci_cpdma.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 4995673..dd5f2db 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -836,6 +836,8 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
/* trigger teardown */
dma_reg_write(ctlr, chan->td, chan_linear(chan));
+ spin_unlock_irqrestore(&chan->lock, flags);
+
/* wait for teardown complete */
timeout = jiffies + HZ/10; /* 100 msec */
while (time_before(jiffies, timeout)) {
@@ -845,6 +847,8 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
cpu_relax();
}
WARN_ON(!time_before(jiffies, timeout));
+
+ spin_lock_irqsave(&chan->lock, flags);
chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
/* handle completed packets */
--
1.7.6.5
^ permalink raw reply related
* RE: [PATCH] net: usb: initialize tmp in dm9601.c to avoid warning
From: David Laight @ 2013-01-18 10:07 UTC (permalink / raw)
To: David Miller, jacmet; +Cc: sque, netdev, msb
In-Reply-To: <20130118.030341.2246222347501217868.davem@davemloft.net>
> > Sure, I just wondered as the code hasn't changed in 5+ years, and the
> > function that gets called is defined just above, so the compiler should
> > be able to figure it out.
>
> Nothing guarentees that a piece of memory passed into an external
> function has it's contents initialized completely by that function.
>
> The compiler can't see what usbnet_read_cmd() does with the memory
> behind the 'data' pointer argument. So it makes the only assumption
> it can make, which is that 'tmp' might be uninitialized.
Possibly the called function is being inlined, then the analysis
knows that some paths don't assign a value.
When it isn't inlined it assumes the value is always modified.
David
^ permalink raw reply
* [PATCH RESEND 01/10] netfilter: move nf_conntrack initialize out of pernet operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
Right now,the netfilter initialize and cleanup codes are
in pernet operations function.
This job should be done in module_init/exit.We can't use
init_net to identify if it's the right time to initialize
or cleanup.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_core.h | 8 ++-
net/netfilter/nf_conntrack_core.c | 96 ++++++++++++-------------------
net/netfilter/nf_conntrack_standalone.c | 28 ++++++---
3 files changed, 62 insertions(+), 70 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index e98aeb3..e05c1f6 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -25,12 +25,16 @@ extern unsigned int nf_conntrack_in(struct net *net,
unsigned int hooknum,
struct sk_buff *skb);
-extern int nf_conntrack_init(struct net *net);
-extern void nf_conntrack_cleanup(struct net *net);
+extern int nf_conntrack_init_net(struct net *net);
+extern void nf_conntrack_cleanup_net(struct net *net);
extern int nf_conntrack_proto_init(struct net *net);
extern void nf_conntrack_proto_fini(struct net *net);
+extern int nf_conntrack_init_start(void);
+extern void nf_conntrack_cleanup_start(void);
+
+extern void nf_conntrack_init_end(void);
extern void nf_conntrack_cleanup_end(void);
extern bool
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e4a0c4f..79eee4e 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1331,8 +1331,14 @@ static int untrack_refs(void)
return cnt;
}
-static void nf_conntrack_cleanup_init_net(void)
+void nf_conntrack_cleanup_start(void)
{
+ RCU_INIT_POINTER(ip_ct_attach, NULL);
+}
+
+void nf_conntrack_cleanup_end(void)
+{
+ RCU_INIT_POINTER(nf_ct_destroy, NULL);
while (untrack_refs() > 0)
schedule();
@@ -1341,8 +1347,18 @@ static void nf_conntrack_cleanup_init_net(void)
#endif
}
-static void nf_conntrack_cleanup_net(struct net *net)
+/*
+ * Mishearing the voices in his head, our hero wonders how he's
+ * supposed to kill the mall.
+ */
+void nf_conntrack_cleanup_net(struct net *net)
{
+ /*
+ * This makes sure all current packets have passed through
+ * netfilter framework. Roll on, two-stage module
+ * delete...
+ */
+ synchronize_net();
i_see_dead_people:
nf_ct_iterate_cleanup(net, kill_all, NULL);
nf_ct_release_dying_list(net);
@@ -1352,6 +1368,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
}
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
+ nf_conntrack_proto_fini(net);
nf_conntrack_helper_fini(net);
nf_conntrack_timeout_fini(net);
nf_conntrack_ecache_fini(net);
@@ -1363,27 +1380,6 @@ static void nf_conntrack_cleanup_net(struct net *net)
free_percpu(net->ct.stat);
}
-/* Mishearing the voices in his head, our hero wonders how he's
- supposed to kill the mall. */
-void nf_conntrack_cleanup(struct net *net)
-{
- if (net_eq(net, &init_net))
- RCU_INIT_POINTER(ip_ct_attach, NULL);
-
- /* This makes sure all current packets have passed through
- netfilter framework. Roll on, two-stage module
- delete... */
- synchronize_net();
- nf_conntrack_proto_fini(net);
- nf_conntrack_cleanup_net(net);
-}
-
-void nf_conntrack_cleanup_end(void)
-{
- RCU_INIT_POINTER(nf_ct_destroy, NULL);
- nf_conntrack_cleanup_init_net();
-}
-
void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
{
struct hlist_nulls_head *hash;
@@ -1474,7 +1470,7 @@ void nf_ct_untracked_status_or(unsigned long bits)
}
EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or);
-static int nf_conntrack_init_init_net(void)
+int nf_conntrack_init_start(void)
{
int max_factor = 8;
int ret, cpu;
@@ -1522,6 +1518,16 @@ err_extend:
return ret;
}
+void nf_conntrack_init_end(void)
+{
+ /* For use by REJECT target */
+ RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
+ RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
+
+ /* Howto get NAT offsets */
+ RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
+}
+
/*
* We need to use special "null" values, not used in hash table
*/
@@ -1529,7 +1535,7 @@ err_extend:
#define DYING_NULLS_VAL ((1<<30)+1)
#define TEMPLATE_NULLS_VAL ((1<<30)+2)
-static int nf_conntrack_init_net(struct net *net)
+int nf_conntrack_init_net(struct net *net)
{
int ret;
@@ -1583,7 +1589,12 @@ static int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_helper_init(net);
if (ret < 0)
goto err_helper;
+ ret = nf_conntrack_proto_init(net);
+ if (ret < 0)
+ goto err_proto;
return 0;
+err_proto:
+ nf_conntrack_helper_fini(net);
err_helper:
nf_conntrack_timeout_fini(net);
err_timeout:
@@ -1610,38 +1621,3 @@ s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
enum ip_conntrack_dir dir,
u32 seq);
EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
-
-int nf_conntrack_init(struct net *net)
-{
- int ret;
-
- if (net_eq(net, &init_net)) {
- ret = nf_conntrack_init_init_net();
- if (ret < 0)
- goto out_init_net;
- }
- ret = nf_conntrack_proto_init(net);
- if (ret < 0)
- goto out_proto;
- ret = nf_conntrack_init_net(net);
- if (ret < 0)
- goto out_net;
-
- if (net_eq(net, &init_net)) {
- /* For use by REJECT target */
- RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
- RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
-
- /* Howto get NAT offsets */
- RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
- }
- return 0;
-
-out_net:
- nf_conntrack_proto_fini(net);
-out_proto:
- if (net_eq(net, &init_net))
- nf_conntrack_cleanup_init_net();
-out_init_net:
- return ret;
-}
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index e7185c6..00bf93c 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -530,11 +530,11 @@ static void nf_conntrack_standalone_fini_sysctl(struct net *net)
}
#endif /* CONFIG_SYSCTL */
-static int nf_conntrack_net_init(struct net *net)
+static int nf_conntrack_pernet_init(struct net *net)
{
int ret;
- ret = nf_conntrack_init(net);
+ ret = nf_conntrack_init_net(net);
if (ret < 0)
goto out_init;
ret = nf_conntrack_standalone_init_proc(net);
@@ -550,30 +550,42 @@ static int nf_conntrack_net_init(struct net *net)
out_sysctl:
nf_conntrack_standalone_fini_proc(net);
out_proc:
- nf_conntrack_cleanup(net);
+ nf_conntrack_cleanup_net(net);
out_init:
return ret;
}
-static void nf_conntrack_net_exit(struct net *net)
+static void nf_conntrack_pernet_exit(struct net *net)
{
nf_conntrack_standalone_fini_sysctl(net);
nf_conntrack_standalone_fini_proc(net);
- nf_conntrack_cleanup(net);
+ nf_conntrack_cleanup_net(net);
}
static struct pernet_operations nf_conntrack_net_ops = {
- .init = nf_conntrack_net_init,
- .exit = nf_conntrack_net_exit,
+ .init = nf_conntrack_pernet_init,
+ .exit = nf_conntrack_pernet_exit,
};
static int __init nf_conntrack_standalone_init(void)
{
- return register_pernet_subsys(&nf_conntrack_net_ops);
+ int ret = nf_conntrack_init_start();
+ if (ret < 0)
+ goto out_start;
+ ret = register_pernet_subsys(&nf_conntrack_net_ops);
+ if (ret < 0)
+ goto out_pernet;
+ nf_conntrack_init_end();
+ return 0;
+out_pernet:
+ nf_conntrack_cleanup_end();
+out_start:
+ return ret;
}
static void __exit nf_conntrack_standalone_fini(void)
{
+ nf_conntrack_cleanup_start();
unregister_pernet_subsys(&nf_conntrack_net_ops);
nf_conntrack_cleanup_end();
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 05/10] netfilter: ecache: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_ecache.h | 19 +++++++++++----
net/netfilter/nf_conntrack_core.c | 15 ++++++++----
net/netfilter/nf_conntrack_ecache.c | 37 ++++++++++-------------------
3 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 5654d29..092dc65 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -207,9 +207,11 @@ nf_ct_expect_event(enum ip_conntrack_expect_events event,
nf_ct_expect_event_report(event, exp, 0, 0);
}
-extern int nf_conntrack_ecache_init(struct net *net);
-extern void nf_conntrack_ecache_fini(struct net *net);
+extern int nf_conntrack_ecache_pernet_init(struct net *net);
+extern void nf_conntrack_ecache_pernet_fini(struct net *net);
+extern int nf_conntrack_ecache_init(void);
+extern void nf_conntrack_ecache_fini(void);
#else /* CONFIG_NF_CONNTRACK_EVENTS */
static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
@@ -232,12 +234,21 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
u32 portid,
int report) {}
-static inline int nf_conntrack_ecache_init(struct net *net)
+static inline int nf_conntrack_ecache_pernet_init(struct net *net)
{
return 0;
}
-static inline void nf_conntrack_ecache_fini(struct net *net)
+static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
+{
+}
+
+static inline int nf_conntrack_ecache_init(void)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_ecache_fini(void)
{
}
#endif /* CONFIG_NF_CONNTRACK_EVENTS */
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index ad8100e0c..8a6c7b6 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_ecache_fini();
nf_conntrack_tstamp_fini();
nf_conntrack_acct_fini();
nf_conntrack_expect_fini();
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_conntrack_proto_fini(net);
nf_conntrack_helper_fini(net);
nf_conntrack_timeout_fini(net);
- nf_conntrack_ecache_fini(net);
+ nf_conntrack_ecache_pernet_fini(net);
nf_conntrack_tstamp_pernet_fini(net);
nf_conntrack_acct_pernet_fini(net);
nf_conntrack_expect_pernet_fini(net);
@@ -1513,6 +1514,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_tstamp;
+ ret = nf_conntrack_ecache_init();
+ if (ret < 0)
+ goto err_ecache;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1530,8 +1535,10 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
- nf_conntrack_tstamp_fini();
+ nf_conntrack_ecache_fini();
#endif
+err_ecache:
+ nf_conntrack_tstamp_fini();
err_tstamp:
nf_conntrack_acct_fini();
err_acct:
@@ -1602,7 +1609,7 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_tstamp_pernet_init(net);
if (ret < 0)
goto err_tstamp;
- ret = nf_conntrack_ecache_init(net);
+ ret = nf_conntrack_ecache_pernet_init(net);
if (ret < 0)
goto err_ecache;
ret = nf_conntrack_timeout_init(net);
@@ -1620,7 +1627,7 @@ err_proto:
err_helper:
nf_conntrack_timeout_fini(net);
err_timeout:
- nf_conntrack_ecache_fini(net);
+ nf_conntrack_ecache_pernet_fini(net);
err_ecache:
nf_conntrack_tstamp_pernet_fini(net);
err_tstamp:
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index faa978f..b5d2eb8 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -233,38 +233,27 @@ static void nf_conntrack_event_fini_sysctl(struct net *net)
}
#endif /* CONFIG_SYSCTL */
-int nf_conntrack_ecache_init(struct net *net)
+int nf_conntrack_ecache_pernet_init(struct net *net)
{
- int ret;
-
net->ct.sysctl_events = nf_ct_events;
net->ct.sysctl_events_retry_timeout = nf_ct_events_retry_timeout;
+ return nf_conntrack_event_init_sysctl(net);
+}
- if (net_eq(net, &init_net)) {
- ret = nf_ct_extend_register(&event_extend);
- if (ret < 0) {
- printk(KERN_ERR "nf_ct_event: Unable to register "
- "event extension.\n");
- goto out_extend_register;
- }
- }
+void nf_conntrack_ecache_pernet_fini(struct net *net)
+{
+ nf_conntrack_event_fini_sysctl(net);
+}
- ret = nf_conntrack_event_init_sysctl(net);
+int nf_conntrack_ecache_init(void)
+{
+ int ret = nf_ct_extend_register(&event_extend);
if (ret < 0)
- goto out_sysctl;
-
- return 0;
-
-out_sysctl:
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&event_extend);
-out_extend_register:
+ pr_err("nf_ct_event: Unable to register event extension.\n");
return ret;
}
-void nf_conntrack_ecache_fini(struct net *net)
+void nf_conntrack_ecache_fini(void)
{
- nf_conntrack_event_fini_sysctl(net);
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&event_extend);
+ nf_ct_extend_unregister(&event_extend);
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 03/10] netfilter: acct: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_acct.h | 6 ++++--
net/netfilter/nf_conntrack_acct.c | 36 +++++++++++--------------------
net/netfilter/nf_conntrack_core.c | 15 +++++++++----
3 files changed, 28 insertions(+), 29 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
index 463ae8e..2bdb7a1 100644
--- a/include/net/netfilter/nf_conntrack_acct.h
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -57,7 +57,9 @@ static inline void nf_ct_set_acct(struct net *net, bool enable)
net->ct.sysctl_acct = enable;
}
-extern int nf_conntrack_acct_init(struct net *net);
-extern void nf_conntrack_acct_fini(struct net *net);
+extern int nf_conntrack_acct_pernet_init(struct net *net);
+extern void nf_conntrack_acct_pernet_fini(struct net *net);
+extern int nf_conntrack_acct_init(void);
+extern void nf_conntrack_acct_fini(void);
#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 7df424e..2d3030a 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -106,36 +106,26 @@ static void nf_conntrack_acct_fini_sysctl(struct net *net)
}
#endif
-int nf_conntrack_acct_init(struct net *net)
+int nf_conntrack_acct_pernet_init(struct net *net)
{
- int ret;
-
net->ct.sysctl_acct = nf_ct_acct;
+ return nf_conntrack_acct_init_sysctl(net);
+}
- if (net_eq(net, &init_net)) {
- ret = nf_ct_extend_register(&acct_extend);
- if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
- goto out_extend_register;
- }
- }
+void nf_conntrack_acct_pernet_fini(struct net *net)
+{
+ nf_conntrack_acct_fini_sysctl(net);
+}
- ret = nf_conntrack_acct_init_sysctl(net);
+int nf_conntrack_acct_init(void)
+{
+ int ret = nf_ct_extend_register(&acct_extend);
if (ret < 0)
- goto out_sysctl;
-
- return 0;
-
-out_sysctl:
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&acct_extend);
-out_extend_register:
+ pr_err("nf_conntrack_acct: Unable to register extension\n");
return ret;
}
-void nf_conntrack_acct_fini(struct net *net)
+void nf_conntrack_acct_fini(void)
{
- nf_conntrack_acct_fini_sysctl(net);
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&acct_extend);
+ nf_ct_extend_unregister(&acct_extend);
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 5c7870b..5b28ee9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_acct_fini();
nf_conntrack_expect_fini();
}
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_conntrack_timeout_fini(net);
nf_conntrack_ecache_fini(net);
nf_conntrack_tstamp_fini(net);
- nf_conntrack_acct_fini(net);
+ nf_conntrack_acct_pernet_fini(net);
nf_conntrack_expect_pernet_fini(net);
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
kfree(net->ct.slabname);
@@ -1503,6 +1504,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_expect;
+ ret = nf_conntrack_acct_init();
+ if (ret < 0)
+ goto err_acct;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1520,8 +1525,10 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
- nf_conntrack_expect_fini();
+ nf_conntrack_acct_fini();
#endif
+err_acct:
+ nf_conntrack_expect_fini();
err_expect:
return ret;
}
@@ -1582,7 +1589,7 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_expect_pernet_init(net);
if (ret < 0)
goto err_expect;
- ret = nf_conntrack_acct_init(net);
+ ret = nf_conntrack_acct_pernet_init(net);
if (ret < 0)
goto err_acct;
ret = nf_conntrack_tstamp_init(net);
@@ -1610,7 +1617,7 @@ err_timeout:
err_ecache:
nf_conntrack_tstamp_fini(net);
err_tstamp:
- nf_conntrack_acct_fini(net);
+ nf_conntrack_acct_pernet_fini(net);
err_acct:
nf_conntrack_expect_pernet_fini(net);
err_expect:
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 07/10] netfilter: helper: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_helper.h | 7 ++--
net/netfilter/nf_conntrack_core.c | 15 ++++++---
net/netfilter/nf_conntrack_helper.c | 52 ++++++++++++++---------------
3 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 9aad956..ce27edf 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -82,8 +82,11 @@ static inline void *nfct_help_data(const struct nf_conn *ct)
return (void *)help->data;
}
-extern int nf_conntrack_helper_init(struct net *net);
-extern void nf_conntrack_helper_fini(struct net *net);
+extern int nf_conntrack_helper_pernet_init(struct net *net);
+extern void nf_conntrack_helper_pernet_fini(struct net *net);
+
+extern int nf_conntrack_helper_init(void);
+extern void nf_conntrack_helper_fini(void);
extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
unsigned int protoff,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9aea05f..91b240c 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_helper_fini();
nf_conntrack_timeout_fini();
nf_conntrack_ecache_fini();
nf_conntrack_tstamp_fini();
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
nf_conntrack_proto_fini(net);
- nf_conntrack_helper_fini(net);
+ nf_conntrack_helper_pernet_fini(net);
nf_conntrack_ecache_pernet_fini(net);
nf_conntrack_tstamp_pernet_fini(net);
nf_conntrack_acct_pernet_fini(net);
@@ -1522,6 +1523,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_timeout;
+ ret = nf_conntrack_helper_init();
+ if (ret < 0)
+ goto err_helper;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1539,8 +1544,10 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
- nf_conntrack_timeout_fini();
+ nf_conntrack_helper_fini();
#endif
+err_helper:
+ nf_conntrack_timeout_fini();
err_timeout:
nf_conntrack_ecache_fini();
err_ecache:
@@ -1618,7 +1625,7 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_ecache_pernet_init(net);
if (ret < 0)
goto err_ecache;
- ret = nf_conntrack_helper_init(net);
+ ret = nf_conntrack_helper_pernet_init(net);
if (ret < 0)
goto err_helper;
ret = nf_conntrack_proto_init(net);
@@ -1626,7 +1633,7 @@ int nf_conntrack_init_net(struct net *net)
goto err_proto;
return 0;
err_proto:
- nf_conntrack_helper_fini(net);
+ nf_conntrack_helper_pernet_fini(net);
err_helper:
nf_conntrack_ecache_pernet_fini(net);
err_ecache:
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 884f2b3..1fda099 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -423,44 +423,42 @@ static struct nf_ct_ext_type helper_extend __read_mostly = {
.id = NF_CT_EXT_HELPER,
};
-int nf_conntrack_helper_init(struct net *net)
+int nf_conntrack_helper_pernet_init(struct net *net)
{
- int err;
-
net->ct.auto_assign_helper_warned = false;
net->ct.sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
+ return nf_conntrack_helper_init_sysctl(net);
+}
- if (net_eq(net, &init_net)) {
- nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
- nf_ct_helper_hash =
- nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0);
- if (!nf_ct_helper_hash)
- return -ENOMEM;
+void nf_conntrack_helper_pernet_fini(struct net *net)
+{
+ nf_conntrack_helper_fini_sysctl(net);
+}
- err = nf_ct_extend_register(&helper_extend);
- if (err < 0)
- goto err1;
+int nf_conntrack_helper_init(void)
+{
+ int ret;
+ nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
+ nf_ct_helper_hash =
+ nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0);
+ if (!nf_ct_helper_hash)
+ return -ENOMEM;
+
+ ret = nf_ct_extend_register(&helper_extend);
+ if (ret < 0) {
+ pr_err("nf_ct_helper: Unable to register helper extension.\n");
+ goto out_extend;
}
- err = nf_conntrack_helper_init_sysctl(net);
- if (err < 0)
- goto out_sysctl;
-
return 0;
-out_sysctl:
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&helper_extend);
-err1:
+out_extend:
nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
- return err;
+ return ret;
}
-void nf_conntrack_helper_fini(struct net *net)
+void nf_conntrack_helper_fini(void)
{
- nf_conntrack_helper_fini_sysctl(net);
- if (net_eq(net, &init_net)) {
- nf_ct_extend_unregister(&helper_extend);
- nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
- }
+ nf_ct_extend_unregister(&helper_extend);
+ nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 09/10] netfilter: l3proto: refactor l3proto support for netns
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
move the code that register/unregister l3proto
to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_l3proto.h | 19 +++++++++----
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 22 ++++++++++-----
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 26 ++++++++++++------
net/netfilter/nf_conntrack_proto.c | 37 +++++++++-----------------
4 files changed, 61 insertions(+), 43 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 6f7c13f..b22605a 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -76,11 +76,20 @@ struct nf_conntrack_l3proto {
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
-/* Protocol registration. */
-extern int nf_conntrack_l3proto_register(struct net *net,
- struct nf_conntrack_l3proto *proto);
-extern void nf_conntrack_l3proto_unregister(struct net *net,
- struct nf_conntrack_l3proto *proto);
+/* Protocol pernet registration. */
+extern int
+nf_conntrack_l3proto_pernet_register(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+extern void
+nf_conntrack_l3proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+
+/* Protocol global registration. */
+extern int
+nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
+extern void
+nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+
extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index fcdd0c2..04799da 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -438,10 +438,10 @@ static int ipv4_net_init(struct net *net)
pr_err("nf_conntrack_l4proto_icmp4 :protocol register failed\n");
goto out_icmp;
}
- ret = nf_conntrack_l3proto_register(net,
- &nf_conntrack_l3proto_ipv4);
+ ret = nf_conntrack_l3proto_pernet_register(net,
+ &nf_conntrack_l3proto_ipv4);
if (ret < 0) {
- pr_err("nf_conntrack_l3proto_ipv4 :protocol register failed\n");
+ pr_err("nf_conntrack_l3proto_ipv4 :sysctl register failed\n");
goto out_ipv4;
}
return 0;
@@ -460,7 +460,7 @@ out_tcp:
static void ipv4_net_exit(struct net *net)
{
- nf_conntrack_l3proto_unregister(net,
+ nf_conntrack_l3proto_pernet_unregister(net,
&nf_conntrack_l3proto_ipv4);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmp);
@@ -500,16 +500,25 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
pr_err("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_pernet;
}
+
+ ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
+ goto cleanup_hooks;
+ }
+
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
ret = nf_conntrack_ipv4_compat_init();
if (ret < 0)
- goto cleanup_hooks;
+ goto cleanup_proto;
#endif
return ret;
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ cleanup_proto:
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
+#endif
cleanup_hooks:
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
-#endif
cleanup_pernet:
unregister_pernet_subsys(&ipv4_net_ops);
cleanup_sockopt:
@@ -523,6 +532,7 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
nf_conntrack_ipv4_compat_fini();
#endif
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
unregister_pernet_subsys(&ipv4_net_ops);
nf_unregister_sockopt(&so_getorigdst);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 137e245..af2756e 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -439,10 +439,10 @@ static int ipv6_net_init(struct net *net)
printk(KERN_ERR "nf_conntrack_l4proto_icmp6: protocol register failed\n");
goto cleanup_udp6;
}
- ret = nf_conntrack_l3proto_register(net,
- &nf_conntrack_l3proto_ipv6);
+ ret = nf_conntrack_l3proto_pernet_register(net,
+ &nf_conntrack_l3proto_ipv6);
if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_l3proto_ipv6: protocol register failed\n");
+ pr_err("nf_conntrack_l3proto_ipv6: sysctl register failed.\n");
goto cleanup_icmpv6;
}
return 0;
@@ -461,7 +461,7 @@ static int ipv6_net_init(struct net *net)
static void ipv6_net_exit(struct net *net)
{
- nf_conntrack_l3proto_unregister(net,
+ nf_conntrack_l3proto_pernet_unregister(net,
&nf_conntrack_l3proto_ipv6);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmpv6);
@@ -491,19 +491,28 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
ret = register_pernet_subsys(&ipv6_net_ops);
if (ret < 0)
- goto cleanup_pernet;
+ goto cleanup_sockopt;
+
ret = nf_register_hooks(ipv6_conntrack_ops,
ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register pre-routing defrag "
"hook.\n");
- goto cleanup_ipv6;
+ goto cleanup_pernet;
+ }
+
+ ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
+ goto cleanup_hooks;
}
return ret;
- cleanup_ipv6:
- unregister_pernet_subsys(&ipv6_net_ops);
+ cleanup_hooks:
+ nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
cleanup_pernet:
+ unregister_pernet_subsys(&ipv6_net_ops);
+ cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst6);
return ret;
}
@@ -511,6 +520,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
synchronize_net();
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
unregister_pernet_subsys(&ipv6_net_ops);
nf_unregister_sockopt(&so_getorigdst6);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 3d01b90..6ab8b6e 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -212,8 +212,8 @@ static void nf_ct_l3proto_unregister_sysctl(struct net *net,
#endif
}
-static int
-nf_conntrack_l3proto_register_net(struct nf_conntrack_l3proto *proto)
+int
+nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{
int ret = 0;
struct nf_conntrack_l3proto *old;
@@ -242,9 +242,10 @@ out_unlock:
return ret;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
-int nf_conntrack_l3proto_register(struct net *net,
- struct nf_conntrack_l3proto *proto)
+int nf_conntrack_l3proto_pernet_register(struct net *net,
+ struct nf_conntrack_l3proto *proto)
{
int ret = 0;
@@ -254,22 +255,12 @@ int nf_conntrack_l3proto_register(struct net *net,
return ret;
}
- ret = nf_ct_l3proto_register_sysctl(net, proto);
- if (ret < 0)
- return ret;
-
- if (net == &init_net) {
- ret = nf_conntrack_l3proto_register_net(proto);
- if (ret < 0)
- nf_ct_l3proto_unregister_sysctl(net, proto);
- }
-
- return ret;
+ return nf_ct_l3proto_register_sysctl(net, proto);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_pernet_register);
-static void
-nf_conntrack_l3proto_unregister_net(struct nf_conntrack_l3proto *proto)
+void
+nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
{
BUG_ON(proto->l3proto >= AF_MAX);
@@ -283,19 +274,17 @@ nf_conntrack_l3proto_unregister_net(struct nf_conntrack_l3proto *proto)
synchronize_rcu();
}
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
-void nf_conntrack_l3proto_unregister(struct net *net,
- struct nf_conntrack_l3proto *proto)
+void nf_conntrack_l3proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l3proto *proto)
{
- if (net == &init_net)
- nf_conntrack_l3proto_unregister_net(proto);
-
nf_ct_l3proto_unregister_sysctl(net, proto);
/* Remove all contrack entries for this protocol */
nf_ct_iterate_cleanup(net, kill_l3proto, proto);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_pernet_unregister);
static struct nf_proto_net *nf_ct_l4proto_net(struct net *net,
struct nf_conntrack_l4proto *l4proto)
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 02/10] netfilter: expect: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_expect.h | 7 ++--
net/netfilter/nf_conntrack_core.c | 14 ++++++--
net/netfilter/nf_conntrack_expect.c | 53 ++++++++++++++---------------
3 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index cc13f37..cbbae76 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -69,8 +69,11 @@ struct nf_conntrack_expect_policy {
#define NF_CT_EXPECT_CLASS_DEFAULT 0
-int nf_conntrack_expect_init(struct net *net);
-void nf_conntrack_expect_fini(struct net *net);
+int nf_conntrack_expect_pernet_init(struct net *net);
+void nf_conntrack_expect_pernet_fini(struct net *net);
+
+int nf_conntrack_expect_init(void);
+void nf_conntrack_expect_fini(void);
struct nf_conntrack_expect *
__nf_ct_expect_find(struct net *net, u16 zone,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 79eee4e..5c7870b 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_expect_fini();
}
/*
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_conntrack_ecache_fini(net);
nf_conntrack_tstamp_fini(net);
nf_conntrack_acct_fini(net);
- nf_conntrack_expect_fini(net);
+ nf_conntrack_expect_pernet_fini(net);
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
kfree(net->ct.slabname);
free_percpu(net->ct.stat);
@@ -1497,6 +1498,11 @@ int nf_conntrack_init_start(void)
printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n",
NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
nf_conntrack_max);
+
+ ret = nf_conntrack_expect_init();
+ if (ret < 0)
+ goto err_expect;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1514,7 +1520,9 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
+ nf_conntrack_expect_fini();
#endif
+err_expect:
return ret;
}
@@ -1571,7 +1579,7 @@ int nf_conntrack_init_net(struct net *net)
printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
goto err_hash;
}
- ret = nf_conntrack_expect_init(net);
+ ret = nf_conntrack_expect_pernet_init(net);
if (ret < 0)
goto err_expect;
ret = nf_conntrack_acct_init(net);
@@ -1604,7 +1612,7 @@ err_ecache:
err_tstamp:
nf_conntrack_acct_fini(net);
err_acct:
- nf_conntrack_expect_fini(net);
+ nf_conntrack_expect_pernet_fini(net);
err_expect:
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
err_hash:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 527651a..bdd3418 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -587,53 +587,50 @@ static void exp_proc_remove(struct net *net)
module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
-int nf_conntrack_expect_init(struct net *net)
+int nf_conntrack_expect_pernet_init(struct net *net)
{
int err = -ENOMEM;
- if (net_eq(net, &init_net)) {
- if (!nf_ct_expect_hsize) {
- nf_ct_expect_hsize = net->ct.htable_size / 256;
- if (!nf_ct_expect_hsize)
- nf_ct_expect_hsize = 1;
- }
- nf_ct_expect_max = nf_ct_expect_hsize * 4;
- }
-
net->ct.expect_count = 0;
net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 0);
if (net->ct.expect_hash == NULL)
goto err1;
- if (net_eq(net, &init_net)) {
- nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
- sizeof(struct nf_conntrack_expect),
- 0, 0, NULL);
- if (!nf_ct_expect_cachep)
- goto err2;
- }
-
err = exp_proc_init(net);
if (err < 0)
- goto err3;
+ goto err2;
return 0;
-
-err3:
- if (net_eq(net, &init_net))
- kmem_cache_destroy(nf_ct_expect_cachep);
err2:
nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
err1:
return err;
}
-void nf_conntrack_expect_fini(struct net *net)
+void nf_conntrack_expect_pernet_fini(struct net *net)
{
exp_proc_remove(net);
- if (net_eq(net, &init_net)) {
- rcu_barrier(); /* Wait for call_rcu() before destroy */
- kmem_cache_destroy(nf_ct_expect_cachep);
- }
nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
}
+
+int nf_conntrack_expect_init(void)
+{
+ if (!nf_ct_expect_hsize) {
+ nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+ if (!nf_ct_expect_hsize)
+ nf_ct_expect_hsize = 1;
+ }
+ nf_ct_expect_max = nf_ct_expect_hsize * 4;
+ nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
+ sizeof(struct nf_conntrack_expect),
+ 0, 0, NULL);
+ if (!nf_ct_expect_cachep)
+ return -ENOMEM;
+ return 0;
+}
+
+void nf_conntrack_expect_fini(void)
+{
+ rcu_barrier(); /* Wait for call_rcu() before destroy */
+ kmem_cache_destroy(nf_ct_expect_cachep);
+}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 10/10] netfilter: l4proto: refactor l4proto support for netns
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
move the code that register/unregister l4proto
to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_l4proto.h | 18 +++++---
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 61 +++++++++++++++++++-------
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 59 ++++++++++++++++++-------
net/netfilter/nf_conntrack_proto.c | 31 +++++--------
net/netfilter/nf_conntrack_proto_dccp.c | 47 ++++++++++++++------
net/netfilter/nf_conntrack_proto_gre.c | 23 ++++++++--
net/netfilter/nf_conntrack_proto_sctp.c | 47 ++++++++++++++------
net/netfilter/nf_conntrack_proto_udplite.c | 44 ++++++++++++++-----
8 files changed, 232 insertions(+), 98 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index c3be4ae..74195e6 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -121,11 +121,19 @@ extern struct nf_conntrack_l4proto *
nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
-/* Protocol registration. */
-extern int nf_conntrack_l4proto_register(struct net *net,
- struct nf_conntrack_l4proto *proto);
-extern void nf_conntrack_l4proto_unregister(struct net *net,
- struct nf_conntrack_l4proto *proto);
+/* Protocol pernet registration. */
+extern int
+nf_conntrack_l4proto_pernet_register(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+extern void
+nf_conntrack_l4proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+
+/* Protocol global registration. */
+extern int
+nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
+extern void
+nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
{
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 04799da..71e32c4 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -420,39 +420,39 @@ static int ipv4_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_tcp4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_tcp4);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_tcp4 :protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_tcp4 :sysctl register failed\n");
goto out_tcp;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_udp4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_udp4);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_udp4 :protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_udp4 :sysctl register failed\n");
goto out_udp;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_icmp);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_icmp);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_icmp4 :protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_icmp4 :sysctl register failed\n");
goto out_icmp;
}
ret = nf_conntrack_l3proto_pernet_register(net,
- &nf_conntrack_l3proto_ipv4);
+ &nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_l3proto_ipv4 :sysctl register failed\n");
goto out_ipv4;
}
return 0;
out_ipv4:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_icmp);
out_icmp:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_udp4);
out_udp:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_tcp4);
out_tcp:
return ret;
@@ -462,11 +462,11 @@ static void ipv4_net_exit(struct net *net)
{
nf_conntrack_l3proto_pernet_unregister(net,
&nf_conntrack_l3proto_ipv4);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_icmp);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_udp4);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_tcp4);
}
@@ -501,10 +501,28 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
goto cleanup_pernet;
}
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv4: can't register tcp4 proto.\n");
+ goto cleanup_hooks;
+ }
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv4: can't register udp4 proto.\n");
+ goto cleanup_tcp4;
+ }
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv4: can't register icmpv4 proto.\n");
+ goto cleanup_udp4;
+ }
+
ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
- goto cleanup_hooks;
+ goto cleanup_icmpv4;
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
@@ -517,6 +535,12 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
cleanup_proto:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
#endif
+ cleanup_icmpv4:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+ cleanup_udp4:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+ cleanup_tcp4:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
cleanup_hooks:
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
cleanup_pernet:
@@ -533,6 +557,9 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
nf_conntrack_ipv4_compat_fini();
#endif
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
unregister_pernet_subsys(&ipv4_net_ops);
nf_unregister_sockopt(&so_getorigdst);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index af2756e..e6c09cc 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -421,22 +421,22 @@ static int ipv6_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_tcp6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_tcp6);
if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_l4proto_tcp6: protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_tcp6: sysctl register failed\n");
goto out;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_udp6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_udp6);
if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_l4proto_udp6: protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_udp6: sysctl register failed\n");
goto cleanup_tcp6;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_icmpv6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_icmpv6);
if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_l4proto_icmp6: protocol register failed\n");
+ pr_err("nf_conntrack_l4proto_icmp6: sysctl register failed\n");
goto cleanup_udp6;
}
ret = nf_conntrack_l3proto_pernet_register(net,
@@ -447,13 +447,13 @@ static int ipv6_net_init(struct net *net)
}
return 0;
cleanup_icmpv6:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_icmpv6);
cleanup_udp6:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_udp6);
cleanup_tcp6:
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_tcp6);
out:
return ret;
@@ -463,11 +463,11 @@ static void ipv6_net_exit(struct net *net)
{
nf_conntrack_l3proto_pernet_unregister(net,
&nf_conntrack_l3proto_ipv6);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_icmpv6);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_udp6);
- nf_conntrack_l4proto_unregister(net,
+ nf_conntrack_l4proto_pernet_unregister(net,
&nf_conntrack_l4proto_tcp6);
}
@@ -501,13 +501,37 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
goto cleanup_pernet;
}
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register tcp6 proto.\n");
+ goto cleanup_hooks;
+ }
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register udp6 proto.\n");
+ goto cleanup_tcp6;
+ }
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register icmpv6 proto.\n");
+ goto cleanup_udp6;
+ }
+
ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
- goto cleanup_hooks;
+ goto cleanup_icmpv6;
}
return ret;
+ cleanup_icmpv6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
+ cleanup_udp6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+ cleanup_tcp6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
cleanup_hooks:
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
cleanup_pernet:
@@ -521,6 +545,9 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
synchronize_net();
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
unregister_pernet_subsys(&ipv6_net_ops);
nf_unregister_sockopt(&so_getorigdst6);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 6ab8b6e..da3807d 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -365,8 +365,8 @@ void nf_ct_l4proto_unregister_sysctl(struct net *net,
/* FIXME: Allow NULL functions and sub in pointers to generic for
them. --RR */
-static int
-nf_conntrack_l4proto_register_net(struct nf_conntrack_l4proto *l4proto)
+int
+nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
@@ -420,9 +420,10 @@ out_unlock:
mutex_unlock(&nf_ct_proto_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
-int nf_conntrack_l4proto_register(struct net *net,
- struct nf_conntrack_l4proto *l4proto)
+int nf_conntrack_l4proto_pernet_register(struct net *net,
+ struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
struct nf_proto_net *pn = NULL;
@@ -441,22 +442,14 @@ int nf_conntrack_l4proto_register(struct net *net,
if (ret < 0)
goto out;
- if (net == &init_net) {
- ret = nf_conntrack_l4proto_register_net(l4proto);
- if (ret < 0) {
- nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
- goto out;
- }
- }
-
pn->users++;
out:
return ret;
}
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_pernet_register);
-static void
-nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto)
+void
+nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
{
BUG_ON(l4proto->l3proto >= PF_MAX);
@@ -471,15 +464,13 @@ nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto)
synchronize_rcu();
}
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
-void nf_conntrack_l4proto_unregister(struct net *net,
+void nf_conntrack_l4proto_pernet_unregister(struct net *net,
struct nf_conntrack_l4proto *l4proto)
{
struct nf_proto_net *pn = NULL;
- if (net == &init_net)
- nf_conntrack_l4proto_unregister_net(l4proto);
-
pn = nf_ct_l4proto_net(net, l4proto);
if (pn == NULL)
return;
@@ -490,7 +481,7 @@ void nf_conntrack_l4proto_unregister(struct net *net,
/* Remove all contrack entries for this protocol */
nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_pernet_unregister);
int nf_conntrack_proto_pernet_init(struct net *net)
{
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index a8ae287..26903fd 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -935,32 +935,32 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
static __net_init int dccp_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net,
- &dccp_proto4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &dccp_proto4);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_dccp4 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_dccp4 :sysctl register failed.\n");
goto out;
}
- ret = nf_conntrack_l4proto_register(net,
- &dccp_proto6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &dccp_proto6);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_dccp6 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_dccp6 :sysctl register failed.\n");
goto cleanup_dccp4;
}
return 0;
cleanup_dccp4:
- nf_conntrack_l4proto_unregister(net,
- &dccp_proto4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &dccp_proto4);
out:
return ret;
}
static __net_exit void dccp_net_exit(struct net *net)
{
- nf_conntrack_l4proto_unregister(net,
- &dccp_proto6);
- nf_conntrack_l4proto_unregister(net,
- &dccp_proto4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &dccp_proto6);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &dccp_proto4);
}
static struct pernet_operations dccp_net_ops = {
@@ -972,11 +972,32 @@ static struct pernet_operations dccp_net_ops = {
static int __init nf_conntrack_proto_dccp_init(void)
{
- return register_pernet_subsys(&dccp_net_ops);
+ int ret;
+ ret = nf_conntrack_l4proto_register(&dccp_proto4);
+ if (ret < 0)
+ goto out_dccp4;
+
+ ret = nf_conntrack_l4proto_register(&dccp_proto6);
+ if (ret < 0)
+ goto out_dccp6;
+
+ ret = register_pernet_subsys(&dccp_net_ops);
+ if (ret < 0)
+ goto out_pernet;
+
+ return 0;
+out_pernet:
+ nf_conntrack_l4proto_unregister(&dccp_proto6);
+out_dccp6:
+ nf_conntrack_l4proto_unregister(&dccp_proto4);
+out_dccp4:
+ return ret;
}
static void __exit nf_conntrack_proto_dccp_fini(void)
{
+ nf_conntrack_l4proto_unregister(&dccp_proto6);
+ nf_conntrack_l4proto_unregister(&dccp_proto4);
unregister_pernet_subsys(&dccp_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index b09b7af..76d698d 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -397,15 +397,16 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
static int proto_gre_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net, &nf_conntrack_l4proto_gre4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_gre4);
if (ret < 0)
- pr_err("nf_conntrack_l4proto_gre4 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_gre4 :sysctl register failed.\n");
return ret;
}
static void proto_gre_net_exit(struct net *net)
{
- nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_gre4);
+ nf_conntrack_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_gre4);
nf_ct_gre_keymap_flush(net);
}
@@ -418,11 +419,25 @@ static struct pernet_operations proto_gre_net_ops = {
static int __init nf_ct_proto_gre_init(void)
{
- return register_pernet_subsys(&proto_gre_net_ops);
+ int ret;
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
+ if (ret < 0)
+ goto out_gre4;
+
+ ret = register_pernet_subsys(&proto_gre_net_ops);
+ if (ret < 0)
+ goto out_pernet;
+
+ return 0;
+out_pernet:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
+out_gre4:
+ return ret;
}
static void __exit nf_ct_proto_gre_fini(void)
{
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
unregister_pernet_subsys(&proto_gre_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index c746d61..4e726d6 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -853,33 +853,33 @@ static int sctp_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_sctp4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_sctp4);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_sctp4 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_sctp4 :sysctl register failed.\n");
goto out;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_sctp6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_sctp6);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_sctp6 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_sctp6 :sysctl register failed.\n");
goto cleanup_sctp4;
}
return 0;
cleanup_sctp4:
- nf_conntrack_l4proto_unregister(net,
- &nf_conntrack_l4proto_sctp4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_sctp4);
out:
return ret;
}
static void sctp_net_exit(struct net *net)
{
- nf_conntrack_l4proto_unregister(net,
- &nf_conntrack_l4proto_sctp6);
- nf_conntrack_l4proto_unregister(net,
- &nf_conntrack_l4proto_sctp4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_sctp6);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_sctp4);
}
static struct pernet_operations sctp_net_ops = {
@@ -891,11 +891,32 @@ static struct pernet_operations sctp_net_ops = {
static int __init nf_conntrack_proto_sctp_init(void)
{
- return register_pernet_subsys(&sctp_net_ops);
+ int ret;
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
+ if (ret < 0)
+ goto out_sctp4;
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
+ if (ret < 0)
+ goto out_sctp6;
+
+ ret = register_pernet_subsys(&sctp_net_ops);
+ if (ret < 0)
+ goto out_pernet;
+
+ return 0;
+out_pernet:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
+out_sctp6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+out_sctp4:
+ return ret;
}
static void __exit nf_conntrack_proto_sctp_fini(void)
{
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
unregister_pernet_subsys(&sctp_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 4b66df2..5f73575 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -336,30 +336,33 @@ static int udplite_net_init(struct net *net)
{
int ret = 0;
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_udplite4);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_udplite4);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_udplite4 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_udplite4 :sysctl register failed.\n");
goto out;
}
- ret = nf_conntrack_l4proto_register(net,
- &nf_conntrack_l4proto_udplite6);
+ ret = nf_conntrack_l4proto_pernet_register(net,
+ &nf_conntrack_l4proto_udplite6);
if (ret < 0) {
- pr_err("nf_conntrack_l4proto_udplite4 :protocol register failed.\n");
+ pr_err("nf_conntrack_l4proto_udplite4 :sysctl register failed.\n");
goto cleanup_udplite4;
}
return 0;
cleanup_udplite4:
- nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_udplite4);
out:
return ret;
}
static void udplite_net_exit(struct net *net)
{
- nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite6);
- nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite4);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_udplite6);
+ nf_conntrack_l4proto_pernet_unregister(net,
+ &nf_conntrack_l4proto_udplite4);
}
static struct pernet_operations udplite_net_ops = {
@@ -371,11 +374,32 @@ static struct pernet_operations udplite_net_ops = {
static int __init nf_conntrack_proto_udplite_init(void)
{
- return register_pernet_subsys(&udplite_net_ops);
+ int ret;
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
+ if (ret < 0)
+ goto out_udplite4;
+
+ ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+ if (ret < 0)
+ goto out_udplite6;
+
+ ret = register_pernet_subsys(&udplite_net_ops);
+ if (ret < 0)
+ goto out_pernet;
+
+ return 0;
+out_pernet:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
+out_udplite6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+out_udplite4:
+ return ret;
}
static void __exit nf_conntrack_proto_udplite_exit(void)
{
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
unregister_pernet_subsys(&udplite_net_ops);
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 04/10] netfilter: tstamp: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_timestamp.h | 21 +++++++++++---
net/netfilter/nf_conntrack_core.c | 15 +++++++---
net/netfilter/nf_conntrack_timestamp.c | 39 ++++++++++----------------
3 files changed, 43 insertions(+), 32 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h
index fc9c82b..b004614 100644
--- a/include/net/netfilter/nf_conntrack_timestamp.h
+++ b/include/net/netfilter/nf_conntrack_timestamp.h
@@ -48,15 +48,28 @@ static inline void nf_ct_set_tstamp(struct net *net, bool enable)
}
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
-extern int nf_conntrack_tstamp_init(struct net *net);
-extern void nf_conntrack_tstamp_fini(struct net *net);
+extern int nf_conntrack_tstamp_pernet_init(struct net *net);
+extern void nf_conntrack_tstamp_pernet_fini(struct net *net);
+
+extern int nf_conntrack_tstamp_init(void);
+extern void nf_conntrack_tstamp_fini(void);
#else
-static inline int nf_conntrack_tstamp_init(struct net *net)
+static inline int nf_conntrack_tstamp_pernet_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_tstamp_pernet_fini(struct net *net)
+{
+ return;
+}
+
+static inline int nf_conntrack_tstamp_init(void)
{
return 0;
}
-static inline void nf_conntrack_tstamp_fini(struct net *net)
+static inline void nf_conntrack_tstamp_fini(void)
{
return;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 5b28ee9..ad8100e0c 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_tstamp_fini();
nf_conntrack_acct_fini();
nf_conntrack_expect_fini();
}
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_conntrack_helper_fini(net);
nf_conntrack_timeout_fini(net);
nf_conntrack_ecache_fini(net);
- nf_conntrack_tstamp_fini(net);
+ nf_conntrack_tstamp_pernet_fini(net);
nf_conntrack_acct_pernet_fini(net);
nf_conntrack_expect_pernet_fini(net);
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
@@ -1508,6 +1509,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_acct;
+ ret = nf_conntrack_tstamp_init();
+ if (ret < 0)
+ goto err_tstamp;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1525,8 +1530,10 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
- nf_conntrack_acct_fini();
+ nf_conntrack_tstamp_fini();
#endif
+err_tstamp:
+ nf_conntrack_acct_fini();
err_acct:
nf_conntrack_expect_fini();
err_expect:
@@ -1592,7 +1599,7 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_acct_pernet_init(net);
if (ret < 0)
goto err_acct;
- ret = nf_conntrack_tstamp_init(net);
+ ret = nf_conntrack_tstamp_pernet_init(net);
if (ret < 0)
goto err_tstamp;
ret = nf_conntrack_ecache_init(net);
@@ -1615,7 +1622,7 @@ err_helper:
err_timeout:
nf_conntrack_ecache_fini(net);
err_ecache:
- nf_conntrack_tstamp_fini(net);
+ nf_conntrack_tstamp_pernet_fini(net);
err_tstamp:
nf_conntrack_acct_pernet_fini(net);
err_acct:
diff --git a/net/netfilter/nf_conntrack_timestamp.c b/net/netfilter/nf_conntrack_timestamp.c
index 7ea8026..902fb0a 100644
--- a/net/netfilter/nf_conntrack_timestamp.c
+++ b/net/netfilter/nf_conntrack_timestamp.c
@@ -88,37 +88,28 @@ static void nf_conntrack_tstamp_fini_sysctl(struct net *net)
}
#endif
-int nf_conntrack_tstamp_init(struct net *net)
+int nf_conntrack_tstamp_pernet_init(struct net *net)
{
- int ret;
-
net->ct.sysctl_tstamp = nf_ct_tstamp;
+ return nf_conntrack_tstamp_init_sysctl(net);
+}
- if (net_eq(net, &init_net)) {
- ret = nf_ct_extend_register(&tstamp_extend);
- if (ret < 0) {
- printk(KERN_ERR "nf_ct_tstamp: Unable to register "
- "extension\n");
- goto out_extend_register;
- }
- }
+void nf_conntrack_tstamp_pernet_fini(struct net *net)
+{
+ nf_conntrack_tstamp_fini_sysctl(net);
+ nf_ct_extend_unregister(&tstamp_extend);
+}
- ret = nf_conntrack_tstamp_init_sysctl(net);
+int nf_conntrack_tstamp_init(void)
+{
+ int ret;
+ ret = nf_ct_extend_register(&tstamp_extend);
if (ret < 0)
- goto out_sysctl;
-
- return 0;
-
-out_sysctl:
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&tstamp_extend);
-out_extend_register:
+ pr_err("nf_ct_tstamp: Unable to register extension\n");
return ret;
}
-void nf_conntrack_tstamp_fini(struct net *net)
+void nf_conntrack_tstamp_fini(void)
{
- nf_conntrack_tstamp_fini_sysctl(net);
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&tstamp_extend);
+ nf_ct_extend_unregister(&tstamp_extend);
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 06/10] netfilter: timeout: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_timeout.h | 12 ++++++------
net/netfilter/nf_conntrack_core.c | 15 ++++++++-------
net/netfilter/nf_conntrack_timeout.c | 22 +++++++---------------
3 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index e41e472..b009f98 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -76,17 +76,17 @@ nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
-extern int nf_conntrack_timeout_init(struct net *net);
-extern void nf_conntrack_timeout_fini(struct net *net);
+extern int nf_conntrack_timeout_init(void);
+extern void nf_conntrack_timeout_fini(void);
#else
-static inline int nf_conntrack_timeout_init(struct net *net)
+static inline int nf_conntrack_timeout_init(void)
{
- return 0;
+ return 0;
}
-static inline void nf_conntrack_timeout_fini(struct net *net)
+static inline void nf_conntrack_timeout_fini(void)
{
- return;
+ return;
}
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8a6c7b6..9aea05f 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_timeout_fini();
nf_conntrack_ecache_fini();
nf_conntrack_tstamp_fini();
nf_conntrack_acct_fini();
@@ -1374,7 +1375,6 @@ void nf_conntrack_cleanup_net(struct net *net)
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
nf_conntrack_proto_fini(net);
nf_conntrack_helper_fini(net);
- nf_conntrack_timeout_fini(net);
nf_conntrack_ecache_pernet_fini(net);
nf_conntrack_tstamp_pernet_fini(net);
nf_conntrack_acct_pernet_fini(net);
@@ -1518,6 +1518,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_ecache;
+ ret = nf_conntrack_timeout_init();
+ if (ret < 0)
+ goto err_timeout;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
@@ -1535,8 +1539,10 @@ int nf_conntrack_init_start(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend:
- nf_conntrack_ecache_fini();
+ nf_conntrack_timeout_fini();
#endif
+err_timeout:
+ nf_conntrack_ecache_fini();
err_ecache:
nf_conntrack_tstamp_fini();
err_tstamp:
@@ -1612,9 +1618,6 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_ecache_pernet_init(net);
if (ret < 0)
goto err_ecache;
- ret = nf_conntrack_timeout_init(net);
- if (ret < 0)
- goto err_timeout;
ret = nf_conntrack_helper_init(net);
if (ret < 0)
goto err_helper;
@@ -1625,8 +1628,6 @@ int nf_conntrack_init_net(struct net *net)
err_proto:
nf_conntrack_helper_fini(net);
err_helper:
- nf_conntrack_timeout_fini(net);
-err_timeout:
nf_conntrack_ecache_pernet_fini(net);
err_ecache:
nf_conntrack_tstamp_pernet_fini(net);
diff --git a/net/netfilter/nf_conntrack_timeout.c b/net/netfilter/nf_conntrack_timeout.c
index a878ce5..5b6d25b 100644
--- a/net/netfilter/nf_conntrack_timeout.c
+++ b/net/netfilter/nf_conntrack_timeout.c
@@ -37,24 +37,16 @@ static struct nf_ct_ext_type timeout_extend __read_mostly = {
.id = NF_CT_EXT_TIMEOUT,
};
-int nf_conntrack_timeout_init(struct net *net)
+int nf_conntrack_timeout_init(void)
{
int ret = 0;
-
- if (net_eq(net, &init_net)) {
- ret = nf_ct_extend_register(&timeout_extend);
- if (ret < 0) {
- printk(KERN_ERR "nf_ct_timeout: Unable to register "
- "timeout extension.\n");
- return ret;
- }
- }
-
- return 0;
+ ret = nf_ct_extend_register(&timeout_extend);
+ if (ret < 0) {
+ pr_err("nf_ct_timeout: Unable to register timeout extension.\n");
+ return ret;
}
-void nf_conntrack_timeout_fini(struct net *net)
+void nf_conntrack_timeout_fini(void)
{
- if (net_eq(net, &init_net))
- nf_ct_extend_unregister(&timeout_extend);
+ nf_ct_extend_unregister(&timeout_extend);
}
--
1.7.11.7
^ permalink raw reply related
* [PATCH RESEND 08/10] netfilter: proto: move initial codes out of pernet_operations
From: Gao feng @ 2013-01-18 10:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, kaber, ebiederm, canqunzhang, Gao feng
In-Reply-To: <1358504190-6094-1-git-send-email-gaofeng@cn.fujitsu.com>
Move the global initial codes to the module_init/exit context.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_core.h | 7 +++++--
net/netfilter/nf_conntrack_core.c | 13 +++++++++---
net/netfilter/nf_conntrack_proto.c | 35 +++++++++++++++++--------------
3 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index e05c1f6..3952e92 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -28,8 +28,11 @@ extern unsigned int nf_conntrack_in(struct net *net,
extern int nf_conntrack_init_net(struct net *net);
extern void nf_conntrack_cleanup_net(struct net *net);
-extern int nf_conntrack_proto_init(struct net *net);
-extern void nf_conntrack_proto_fini(struct net *net);
+extern int nf_conntrack_proto_init(void);
+extern void nf_conntrack_proto_fini(void);
+
+extern int nf_conntrack_proto_pernet_init(struct net *net);
+extern void nf_conntrack_proto_pernet_fini(struct net *net);
extern int nf_conntrack_init_start(void);
extern void nf_conntrack_cleanup_start(void);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 91b240c..be43427 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1345,6 +1345,7 @@ void nf_conntrack_cleanup_end(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_proto_fini();
nf_conntrack_helper_fini();
nf_conntrack_timeout_fini();
nf_conntrack_ecache_fini();
@@ -1374,7 +1375,7 @@ void nf_conntrack_cleanup_net(struct net *net)
}
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
- nf_conntrack_proto_fini(net);
+ nf_conntrack_proto_pernet_fini(net);
nf_conntrack_helper_pernet_fini(net);
nf_conntrack_ecache_pernet_fini(net);
nf_conntrack_tstamp_pernet_fini(net);
@@ -1532,6 +1533,10 @@ int nf_conntrack_init_start(void)
if (ret < 0)
goto err_extend;
#endif
+ ret = nf_conntrack_proto_init();
+ if (ret < 0)
+ goto err_proto;
+
/* Set up fake conntrack: to never be deleted, not in any hashes */
for_each_possible_cpu(cpu) {
struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
@@ -1542,10 +1547,12 @@ int nf_conntrack_init_start(void)
nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED);
return 0;
+err_proto:
#ifdef CONFIG_NF_CONNTRACK_ZONES
+ nf_ct_extend_unregister(&nf_ct_zone_extend);
err_extend:
- nf_conntrack_helper_fini();
#endif
+ nf_conntrack_helper_fini();
err_helper:
nf_conntrack_timeout_fini();
err_timeout:
@@ -1628,7 +1635,7 @@ int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_helper_pernet_init(net);
if (ret < 0)
goto err_helper;
- ret = nf_conntrack_proto_init(net);
+ ret = nf_conntrack_proto_pernet_init(net);
if (ret < 0)
goto err_proto;
return 0;
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 51e928d..3d01b90 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -503,9 +503,8 @@ void nf_conntrack_l4proto_unregister(struct net *net,
}
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
-int nf_conntrack_proto_init(struct net *net)
+int nf_conntrack_proto_pernet_init(struct net *net)
{
- unsigned int i;
int err;
struct nf_proto_net *pn = nf_ct_l4proto_net(net,
&nf_conntrack_l4proto_generic);
@@ -520,29 +519,33 @@ int nf_conntrack_proto_init(struct net *net)
if (err < 0)
return err;
- if (net == &init_net) {
- for (i = 0; i < AF_MAX; i++)
- rcu_assign_pointer(nf_ct_l3protos[i],
- &nf_conntrack_l3proto_generic);
- }
-
pn->users++;
return 0;
}
-void nf_conntrack_proto_fini(struct net *net)
+void nf_conntrack_proto_pernet_fini(struct net *net)
{
- unsigned int i;
struct nf_proto_net *pn = nf_ct_l4proto_net(net,
&nf_conntrack_l4proto_generic);
-
pn->users--;
nf_ct_l4proto_unregister_sysctl(net,
pn,
&nf_conntrack_l4proto_generic);
- if (net == &init_net) {
- /* free l3proto protocol tables */
- for (i = 0; i < PF_MAX; i++)
- kfree(nf_ct_protos[i]);
- }
+}
+
+int nf_conntrack_proto_init(void)
+{
+ unsigned int i;
+ for (i = 0; i < AF_MAX; i++)
+ rcu_assign_pointer(nf_ct_l3protos[i],
+ &nf_conntrack_l3proto_generic);
+ return 0;
+}
+
+void nf_conntrack_proto_fini(void)
+{
+ unsigned int i;
+ /* free l3proto protocol tables */
+ for (i = 0; i < PF_MAX; i++)
+ kfree(nf_ct_protos[i]);
}
--
1.7.11.7
^ permalink raw reply related
* Re: Redefinition of struct in6_addr in <netinet/in.h> and <linux/in6.h>
From: Pedro Alves @ 2013-01-18 10:44 UTC (permalink / raw)
To: Carlos O'Donell
Cc: Mike Frysinger, David Miller, libc-alpha, bhutchings, yoshfuji,
amwang, tmb, eblake, netdev, linux-kernel, libvirt-list, tgraf,
schwab
In-Reply-To: <CAE2sS1jMhnRcoo1oe7wQ+SP=40u9mkps6vXua8TQQ4Tbf2qKOQ@mail.gmail.com>
On 01/18/2013 04:22 AM, Carlos O'Donell wrote:
> On Thu, Jan 17, 2013 at 11:20 PM, Mike Frysinger <vapier@gentoo.org> wrote:
>> On Wednesday 16 January 2013 22:15:38 David Miller wrote:
>>> From: Carlos O'Donell <carlos@systemhalted.org>
>>> Date: Wed, 16 Jan 2013 21:15:03 -0500
>>>
>>>> +/* If a glibc-based userspace has already included in.h, then we will
>>>> not + * define in6_addr (nor the defines), sockaddr_in6, or ipv6_mreq.
>>>> The + * ABI used by the kernel and by glibc match exactly. Neither the
>>>> kernel + * nor glibc should break this ABI without coordination.
>>>> + */
>>>> +#ifndef _NETINET_IN_H
>>>> +
>>>
>>> I think we should shoot for a non-glibc-centric solution.
>>>
>>> I can't imagine that other libc's won't have the same exact problem
>>> with their netinet/in.h conflicting with the kernel's, redefining
>>> structures like in6_addr, that we'd want to provide a protection
>>> scheme for here as well.
>>
>> yes, the kernel's use of __GLIBC__ in exported headers has already caused
>> problems in the past. fortunately, it's been reduced down to just one case
>> now (stat.h). let's not balloon it back up.
>> -mike
>
> I also see coda.h has grown a __GLIBC__ usage.
>
> In the next revision of the patch I created a single libc-compat.h header
> which encompasses the logic for any libc that wants to coordinate with
> the kernel headers.
> It's simple enough to move all of the __GLIBC__ uses into libc-compat.h,
> then you control userspace libc coordination from one file.
How about just deciding on a single macro/symbol both the
kernel and libc (any libc that needs this) define? Something
like both the kernel and userland doing:
#ifndef __IPV6_BITS_DEFINED
#define __IPV6_BITS_DEFINED
...
define in6_addr, sockaddr_in6, ipv6_mreq, whatnot
#endif
So whichever the application includes first, wins.
Too naive? I didn't see this option being discarded, so
not sure it was considered.
--
Pedro Alves
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox