Netdev List
 help / color / mirror / Atom feed
* Re: [net-next-2.6 PATCH RFC] TCPCT part 1d: generate Responder Cookie
From: Eric Dumazet @ 2009-11-05 13:19 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: paulmck, Linux Kernel Developers, Linux Kernel Network Developers
In-Reply-To: <4AF2C266.1010603@gmail.com>

William Allen Simpson a écrit :
> Paul E. McKenney wrote:
>> On Tue, Nov 03, 2009 at 05:38:10PM -0500, William Allen Simpson wrote:
>>> Documentation/RCU/checklist.txt #7 says:
>>>
>>>   One exception to this rule: rcu_read_lock() and rcu_read_unlock()
>>>   may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
>>>   in cases where local bottom halves are already known to be
>>>   disabled, for example, in irq or softirq context.  Commenting
>>>   such cases is a must, of course!  And the jury is still out on
>>>   whether the increased speed is worth it.
>>
>> I strongly suggest using the matching primitives unless you have a
>> really strong reason not to.
>>
> Eric gave contrary advice.  But he also suggested (in an earlier message)
> clearing the secrets with a timer, which could be a separate context --
> although much later in time.
> 
> As you suggest, I'll use the _bh suffix everywhere until every i is dotted
> and t is crossed.  Then, check for efficiency later after thorough
> analysis by experts such as yourself.
> 
> This code will be hit on every SYN and SYNACK that has a cookie option.
> But it's just prior to a CPU intensive sha_transform -- in comparison,
> it's trivial.
>

I think you misunderstood my advice ;)

In the same function, you *cannot* use both variants like your last patch did :

		spin_lock(&tcp_secret_locker);  

...

		rcu_read_lock_bh();
		memcpy(&xvp->cookie_bakery[0],
		       &rcu_dereference(tcp_secret_generating)->secrets[0],
		       sizeof(tcp_secret_generating->secrets));
		rcu_read_unlock_bh();



Reasoning is :

If you need _bh() for the rcu_read_lock_bh(), thats because you know
soft irq can happen anytime (they are not masked).

Then you also need _bh for the spin_lock() call, or risk deadlock.

-> tcp_cookie_generator();
spin_lock();
-> interrupt  -> softirq -> SYN frame received -> tcp_cookie_generator() -> spin_lock(); hang



Your choices are :
------------------

1) Caller took care of disabling softirqs (or is only called from softirq handler),
then _bh suffixes are not necessary in tcp_cookie_generator().
 -> spin_lock() & rcu_read_lock();

2) You dont know what called you (process context or softirq context)
-> you MUST use _bh prefixes on spin_lock_bh() & rcu_read_lock_bh();



^ permalink raw reply

* Re: [PATCH] tcp: set SPLICE_F_NONBLOCK after first buffer has been spliced
From: Max Kellermann @ 2009-11-05 13:23 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-kernel, jens.axboe, Linux Netdev List
In-Reply-To: <4AF2B551.6010302@gmail.com>

On 2009/11/05 12:21, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Max Kellermann a écrit :
> > Do you think that a splice() should block if the socket is readable
> > and the pipe is writable according to select()?
> > 
> 
> Yes, this is perfectly legal
> 
> select() can return "OK to write on fd",
> and still, write(fd, buffer, 10000000) is supposer/allowed to block if fd is not O_NDELAY

From the select() manpage: "those in writefds will be watched to see
if a write will not block"

From the poll() manpage: "Writing now will not block."

This looks unambiguous to me, and contradicts with your thesis.  Can
you provide sources?

What is your interpretation of the guarantees provided by select() and
poll()?  Which byte count is "ok" to write after POLLOUT, and how much
is "too much"?  How does the application know?

> Please read recent commit on this area and why I think your patch
> conflicts with this commit.

I understand your patch, but I don't understand the conflict with my
patch.  Can you describe a breakage caused by my patch?

^ permalink raw reply

* RE: [PATCH 16/25] mlx4_core: boot sriov
From: Liran Liss @ 2009-11-05 13:26 UTC (permalink / raw)
  To: Roland Dreier, Yevgeny Petrilin; +Cc: linux-rdma, netdev, Tziporet Koren
In-Reply-To: <aday6mmyshm.fsf@cisco.com>

 S.B.
--Liran

-----Original Message-----
From: Roland Dreier [mailto:rdreier@cisco.com] 
Sent: Wednesday, November 04, 2009 9:56 PM
To: Yevgeny Petrilin
Cc: linux-rdma@vger.kernel.org; netdev@vger.kernel.org; Liran Liss;
Tziporet Koren
Subject: Re: [PATCH 16/25] mlx4_core: boot sriov


 > +	/* Detect if this device is a virtual function */
 > +	switch (id->device) {
 > +	case 0x6341:
 > +	case 0x634b:
 > +	case 0x6733:
 > +	case 0x673d:
 > +	case 0x6369:
 > +	case 0x6751:
 > +	case 0x6765:

This isn't be maintainable or sane.  How about using driver_data in the
PCI device table?
LL: good idea; 10x.

 > +#ifdef CONFIG_PCI_IOV
 > +		if (sr_iov) {

Can we avoid a lot of these ifdefs by just doing

#else
#define sr_iov	0
#endif /* CONFIG_PCI_IOV */

at the beginning and letting the IOV code be optimized away?

LL: I think that this won't pass -Wall when compiling against a kernel
with sriov compiled out.

 - R.

^ permalink raw reply

* Re: [net-next-2.6 PATCH RFC] TCPCT part 1d: generate Responder Cookie
From: Eric Dumazet @ 2009-11-05 13:34 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: paulmck, Linux Kernel Developers, Linux Kernel Network Developers
In-Reply-To: <4AF2C8E4.9020202@gmail.com>

William Allen Simpson a écrit :
> William Allen Simpson wrote:
>> Yes.  Just shuffling the pointers without ever freeing anything.  So,
>> there's nothing for call_rcu() to do, and nothing else to synchronize
>> (only the pointers).  This assumes that after _unlock_ any CPU cache
>> with an old pointer->expires will hit the _lock_ code, and that will
>> update *both* ->expires and the other array elements concurrently?
>>
> Reiterating, I've not found Documentation showing that this code works:
> 
> +    unsigned long jiffy = jiffies;
> +
> +    if (unlikely(time_after(jiffy, tcp_secret_generating->expires))) {
> +        spin_lock_bh(&tcp_secret_locker);
> +        if (!time_after(jiffy, tcp_secret_generating->expires)) {
> +            /* refreshed by another */
> +            spin_unlock_bh(&tcp_secret_locker);
> +            memcpy(&xvp->cookie_bakery[0],
> +                   &tcp_secret_generating->secrets[0],
> +                   sizeof(tcp_secret_generating->secrets));
> +        } else {
> 
> How is it ensured that an old tcp_secret_generating or an old ->expires,
> followed by a spin_lock, has updated both?
> 
> And even when both are updated, then every word of the ->secrets array has
> also been updated in the local cache?
> 
> Is this a property of spin_lock()?  Or spin_unlock()?

Yes,  

$ vi +1121 Documentation/memory-barriers.txt

 (1) LOCK operation implication:

     Memory operations issued after the LOCK will be completed after the LOCK
     operation has completed.

     Memory operations issued before the LOCK may be completed after the LOCK
     operation has completed.

 (2) UNLOCK operation implication:

     Memory operations issued before the UNLOCK will be completed before the
     UNLOCK operation has completed.

     Memory operations issued after the UNLOCK may be completed before the
     UNLOCK operation has completed.

^ permalink raw reply

* Re: [PATCH 1/3] net: TCP thin-stream detection
From: Andreas Petlund @ 2009-11-05 13:34 UTC (permalink / raw)
  To: Arnd Hannemann
  Cc: William Allen Simpson, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, shemminger@vyatta.com,
	ilpo.jarvinen@helsinki.fi, davem@davemloft.net
In-Reply-To: <4AEB0512.4010804@nets.rwth-aachen.de>

Arnd Hannemann wrote:
> Both mechanism prevent retransmission timeouts, thereby reducing latency.
> Who cares, that they were motivated by performance?

The essence of motivation is that there exist an incentive for performing an 
action. If the motivation for fast retransmitting earlier is to keep the cwnd 
open for a greedy application with small time-dependency, the question may be 
posed whether it is worth the effort of the proposed changes. With the 
thin-stream applications, we have confirmed that this is very often an 
indication of time-dependent/interactive applications (like SSH-text sessions, 
RDP, sensor networks, stock trading systems, interactive games etc). We have 
further shown that such applications are prone to lag upon retransmissions due 
to the inadequacies of TCP to deal with thin streams. We have also shown that 
by performing the proposed adjustments, we can drastically improve the 
situation. 

Since we now know that the modifications can drastically improve the user 
experience, the motivation/incentive for implementing the modifications is 
increased. 

> I agree, that you are more aggressive, and that your scheme may have
> latency advantages, at least for the Limited Transmit case. And there are
> probably good reasons for your proposal. But I really think you should
> bring your proposal up in IETF TCPM WG. I have the feeling that there are
> a lot of corner cases we didn't think of.
> 
> One example: Consider standard NewReno non-SACK enabled flow:
> For some reasons two data packets get reordered.
> The TCP sender will produce a dupACK and an ACK.
> The dupACK will trigger (because of your logic) a spurious retransmit.
> The spurious retransmit will trigger a dupACK.
> This dupACK will again trigger a spurious retransmit.
> And this game will continue, unless a packet is dropped by coincidence.

Such an effect will be extremely rare. It will depend on the application 
producing an extremely even flow of packets with just the right 
interarrival time, and also on reordering of data (which also will 
happen very seldom when the number of packets in flight are so low). 
Even though it can happen, the data flow will progress (with spurious 
retransmissions). The effect will stop as soon as the application sends 
more than 4 segments in an RTT (which will disable the thin-stream 
modifications) or less than 1 (which will cause all segments to be 
successfully ACKed), or if, as you say, a packet is dropped.

I will be thankful for more input on eventual corner cases and also on 
test cases that we may perform to evaluate the modifications for 
scenarios that are of concern.

Best regards,
Andreas

^ permalink raw reply

* Re: [PATCH 1/3] net: TCP thin-stream detection
From: Andreas Petlund @ 2009-11-05 13:36 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: Linux Kernel Network Developers, Ilpo Järvinen,
	Arnd Hannemann, linux-kernel@vger.kernel.org,
	shemminger@vyatta.com, davem@davemloft.net, Christian Samsel
In-Reply-To: <4AEB109A.7090506@gmail.com>

William Allen Simpson wrote:
> I'm finding it hard to follow 3 threads, for the 3 parts of the patch.
> 
> As I mentioned in one of these threads, I've plenty of experience with
> designing and implementing protocols for gaming.  And it seems to me that
> you're making changes to the entire TCP stack to make up for shortcomings
> in the implementor's design.  Yet, these changes require application
> implementors to set a sockopt that's only available in Linux.  Unlikely,
> as they probably don't even keep track of such things....
>

The target is not only games, but for instance SSH sessions, RDP or VNC, 
stock trading services, sensor networks and so forth. There are a lot of 
time-dependent applications that shows thin stream properties. Many of 
these use TCP, and will continue to use it. Some of these applications 
use UDP as default, but fall back to TCP if there is a problem with the 
UDP connection (for instance Skype). By providing better latency for thin 
streams, we can increase the service level for all these applications. 

Our experience is that at least some designers of interactive/time-dependent 
applications are skilled enough and concerned enough to investigate whether 
options exist that may improve the applications they are designing. Of 
course there are exceptions, but for open-sourced software, there will be 
people who can provide this input. If the argument is that there is no need 
for customised options because developers are stupid, we could strip away a 
lot of the existing network code.

> I've already suggested the end-to-end interest list, where you'll find many
> of us with a strong interest in this topic.

I've been reading end-to-end for several years, and I think I will take this 
discussion to that list eventually. We have discussed whether we should take 
this to end-to-end first, and netdev after, but decided to go here for the 
following reasons: 1) We have working patches that we wanted to contribute. 
2) The modifications are implemented as optional. 3) When active, the 
modifications handle a special case of TCP streams that we have shown to 
have minimal impact on general TCP behaviour.

Also, in my experience, the end-to-end list discussions tend to digress, 
making it difficult to keep the discussion to the special case that we 
address. Since we wanted technical and practical feedback that would help us
to refine the modifications in the patches in addition to the discussion on 
transport protocols, we chose to go to netdev first.

> The IETF has two related working groups:
>   tcpm -- tcp modifications
>   tsvwg -- general transport, including sctp modifications

There are plenty of examples of TCP mechanisms present in the Linux 
kernel that has not been standardised, for instance TCP CUBIC, the 
default congestion control for many Linux distributions at this time.

We have a set of patches, and a large body of experiments that shows them to
be effective for the thin-stream scenario without any significant disadvantages.
Please consider this before discarding the proposition based on a general 
principle of standardisation. We believe that the thin-stream modifications 
will provide extra value to Linux networking.

Best regards,
Andreas



^ permalink raw reply

* Re: [PATCH 2/3] net: TCP thin linear timeouts
From: Andreas Petlund @ 2009-11-05 13:37 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: Rick Jones, Ilpo Järvinen, Arnd Hannemann, Eric Dumazet,
	Netdev, LKML, shemminger, David Miller
In-Reply-To: <4AEB2C55.7040208@gmail.com>

William Allen Simpson wrote:
>> Further blue-skying...
>>
>> If SACK were also enabled, it would seem that only loss of the last
>> segment in the "thin train" would be an issue?  Presumably, the thin
>> stream receiver would be in a position to detect this, perhaps with an
>> application-level timeout. Whether then it would suffice to allow the
>> receiving app to make a setsockopt() call to force an extra ACK or two
>> I'm not sure.  Perhaps if the thin-stream had a semi-aggressive
>> "heartbeat" going...
>>
> Heartbeats are the usual solution for gaming.  Handles a host of
> issues, including detection of clients that have become unreachable.
> 
> (No, these are not the same as TCP keep-alives.)
>
> Beside my code in the field and widespread discussion, I know that Paul
> Francis had several related papers a decade or so ago.  My memory is that
> younger game coders weren't particularly avid readers....
>
>> But it does seem that it should be possible to deal with this sort of
>> thing without having to make wholesale changes to TCP's RTO policies
>> and whatnot?
>>
> Yep.

We recognise the possibility of increasing the aggressiveness of application 
send rate in order to counteract the effect of thin streams on retransmission 
latency. Applications are by nature uninformed about the state of the layers 
below. To work around the fast-retransmit latency problems, an application 
would have to keep a very aggressive heartbeat rate even though there is no 
data to send, thus spamming the network with unneeded traffic.

To exemplify this, let's choose an SSH session from this set of statistics:
http://folk.uio.no/apetlund/lktmp/thin_apps_table.pdf. This thin stream has 
an averge packet interarrival time of 323ms. The application developer would 
have to consider how many "duds" to send in order to ensure a low 
retransmission latency. Let's say he considers RTTs lower than 60ms harmless, 
he would need to send more than 4 packets per 60ms. This would mean a 
heartbeat rate of one packet each 15ms. Considering this, the aggressively 
heartbeated application would send 67 packets per second compared to 3 in 
the original stream.

By including thin-stream semantics into the TCP code, informed decisions 
can be made to minimise the overhead while still reducing the retransmission 
latency.

Best regards,
Andreas



^ permalink raw reply

* RE: [PATCH 19/25] mlx4: Randomizing mac addresses for slaves
From: Liran Liss @ 2009-11-05 13:38 UTC (permalink / raw)
  To: Or Gerlitz, Roland Dreier
  Cc: Yevgeny Petrilin, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Tziporet Koren
In-Reply-To: <15ddcffd0911041333l165ee274mfae3508a3db755e7-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

This approach seems to be common practice now (e.g., drivers/net/igb/igb_main.c:1332).
In any case, the user can change the randomized mac.
--Liran

-----Original Message-----
From: Or Gerlitz [mailto:or.gerlitz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org] 
Sent: Wednesday, November 04, 2009 11:33 PM
To: Roland Dreier
Cc: Yevgeny Petrilin; linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; netdev-u79uwXL29TaqPxH82wqD4g@public.gmane.orgg; Liran Liss; Tziporet Koren
Subject: Re: [PATCH 19/25] mlx4: Randomizing mac addresses for slaves

On Wed, Nov 4, 2009 at 10:04 PM, Roland Dreier <rdreier-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org> wrote:
>> +#define MLX4_MAC_HEAD               0x2c9000000ULL

> Is this a good idea?  You're basically choosing 24 random bits within your OUI...
> seems the chance of collision with another MAC used on the same 
> network is high enough that it could easily happen in practice on a moderately big network.

yes, this has been brought by Stephen and others on this last back on September 11th, this year @
http://marc.info/?l=linux-netdev&m=125263488409128

> Can you pick a reserved range or something?

Using different OUI for the VF device wouldn't help either I think, since the #VF becomes fairly big even on a modest side cluster with
(say) a VM consuming VF per 1-2 cores.

Or.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/3] net: TCP thin-stream detection
From: Ilpo Järvinen @ 2009-11-05 13:45 UTC (permalink / raw)
  To: Andreas Petlund
  Cc: Arnd Hannemann, William Allen Simpson, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, shemminger@vyatta.com,
	davem@davemloft.net
In-Reply-To: <4AF2D47F.4030701@simula.no>

On Thu, 5 Nov 2009, Andreas Petlund wrote:

> Arnd Hannemann wrote:
> > 
> > One example: Consider standard NewReno non-SACK enabled flow:
> > For some reasons two data packets get reordered.
> > The TCP sender will produce a dupACK and an ACK.
> > The dupACK will trigger (because of your logic) a spurious retransmit.
> > The spurious retransmit will trigger a dupACK.
> > This dupACK will again trigger a spurious retransmit.
> > And this game will continue, unless a packet is dropped by coincidence.
> 
> Such an effect will be extremely rare. It will depend on the application 
> producing an extremely even flow of packets with just the right 
> interarrival time, and also on reordering of data (which also will 
> happen very seldom when the number of packets in flight are so low). 
> Even though it can happen, the data flow will progress (with spurious 
> retransmissions). The effect will stop as soon as the application sends 
> more than 4 segments in an RTT (which will disable the thin-stream 
> modifications) or less than 1 (which will cause all segments to be 
> successfully ACKed), or if, as you say, a packet is dropped.

I'd simply workaround this problem by requiring SACK to be enabled for 
such a connection. This is reinforced by the fact that small windowed 
transfers want it certainly to be on anyway to get the best out of ACK 
flow even if there were some ACK losses.


-- 
 i.

^ permalink raw reply

* Re: Shared i2c adapter locking
From: Ben Hutchings @ 2009-11-05 13:57 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Stephen Rothwell, David Miller, netdev, linux-next, linux-kernel,
	Mika Kuoppala, Linux I2C
In-Reply-To: <20091105141122.56b6b4f8@hyperion.delvare>

On Thu, 2009-11-05 at 14:11 +0100, Jean Delvare wrote:
[...]
> What about the following patch?
> 
> From: Jean Delvare <khali@linux-fr.org>
> Subject: i2c: Add an interface to lock/unlock I2C bus segment
> 
> Some drivers need to be able to prevent access to an I2C bus segment
> for a specific period of time. Add an interface for them to do so
> without twiddling with i2c-core internals.
> 
> Signed-off-by: Jean Delvare <khali@linux-fr.org>
> Cc: Ben Hutchings <bhutchings@solarflare.com>
Acked-by: Ben Hutchings <bhutchings@solarflare.com>

Presumably this is meant for net-next-2.6, and you'll implement
i2c_{lock,unlock}_adapter() using rt_mutex in your i2c tree?

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: Shared i2c adapter locking
From: Jean Delvare @ 2009-11-05 14:07 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: Stephen Rothwell, David Miller, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-next-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mika Kuoppala, Linux I2C
In-Reply-To: <1257429444.2793.2.camel-xQnnTUlwzDrdvaEqJLTMTA9jg9n5Vt1AMm0uRHvK7Nw@public.gmane.org>

On Thu, 05 Nov 2009 13:57:24 +0000, Ben Hutchings wrote:
> On Thu, 2009-11-05 at 14:11 +0100, Jean Delvare wrote:
> [...]
> > What about the following patch?
> > 
> > From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> > Subject: i2c: Add an interface to lock/unlock I2C bus segment
> > 
> > Some drivers need to be able to prevent access to an I2C bus segment
> > for a specific period of time. Add an interface for them to do so
> > without twiddling with i2c-core internals.
> > 
> > Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> > Cc: Ben Hutchings <bhutchings-s/n/eUQHGBpZroRs9YW3xA@public.gmane.org>
> Acked-by: Ben Hutchings <bhutchings-s/n/eUQHGBpZroRs9YW3xA@public.gmane.org>
> 
> Presumably this is meant for net-next-2.6, and you'll implement

Actually I meant to push this to Linus immediately, through my i2c
tree. This is essentially a no-op: the binary code will be the same as
before the patch, so guaranteed to be safe, and this will solve
conflicts in linux-next.

> i2c_{lock,unlock}_adapter() using rt_mutex in your i2c tree?

Correct.

-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH] tcp: set SPLICE_F_NONBLOCK after first buffer has been spliced
From: Eric Dumazet @ 2009-11-05 14:11 UTC (permalink / raw)
  To: Max Kellermann; +Cc: linux-kernel, jens.axboe, Linux Netdev List
In-Reply-To: <20091105132352.GA14453@rabbit.intern.cm-ag>

Max Kellermann a écrit :
> On 2009/11/05 12:21, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> Max Kellermann a écrit :
>>> Do you think that a splice() should block if the socket is readable
>>> and the pipe is writable according to select()?
>>>
>> Yes, this is perfectly legal
>>
>> select() can return "OK to write on fd",
>> and still, write(fd, buffer, 10000000) is supposer/allowed to block if fd is not O_NDELAY
> 
>>From the select() manpage: "those in writefds will be watched to see
> if a write will not block"
> 
>>From the poll() manpage: "Writing now will not block."
> 
> This looks unambiguous to me, and contradicts with your thesis.  Can
> you provide sources?
> 
> What is your interpretation of the guarantees provided by select() and
> poll()?  Which byte count is "ok" to write after POLLOUT, and how much
> is "too much"?  How does the application know?

It cannot, therefore an application uses O_NDELAY to avoid blocking.

Try following program if you are not convinced

#include <unistd.h>
#include <sys/poll.h>
#include <stdio.h>

char buffer[1000000];

int main(int argc, char *argv[])
{
	int fds[2];
	struct pollfd pfd;
	int res;
	
	pipe(fds);
	pfd.fd = fds[1];
	pfd.events = POLLOUT;
	res = poll(&pfd, 1, -1);
	if (res > 0 && pfd.revents & POLLOUT)
		printf("OK to write on pipe\n");
	write(fds[1], buffer, sizeof(buffer)); // why it blocks, did poll() lied ???
	return 0;
}



> I understand your patch, but I don't understand the conflict with my
> patch.  Can you describe a breakage caused by my patch?

I only pointed out that using splice(tcp -> pipe) and blocking on pipe
_can_ block, even on _first_ frame received from tcp, as you discovered.


Your only choices to avoid a deadlock are :
1) to use SPLICE_F_NONBLOCK.
2) Using a second thread to read the pipe and empty it. First thread will
   happily transfert 1000000 bytes in one syscall...
3) or limit your splice(... len, flags) length to 16 (16 buffers of one byte
   in pathological cases)

Your patch basically makes SPLICE_F_NONBLOCK option always set (choice 1) above)

So users wanting option 3) are stuck. You force them to use a poll()/select()
thing while they dont want to poll : They have a producer thread(s), and a consumer
thread(s).

producer()
{
	while (1)
		splice(tcp, &offset, pfds[1], NULL, 10000000,
		       SPLICE_F_MORE | SPLICE_F_MOVE);
}

Why in the first place have an option if it is always set ?

^ permalink raw reply

* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Anton Vorontsov @ 2009-11-05 14:20 UTC (permalink / raw)
  To: Jon Loeliger
  Cc: David Miller, linuxppc-dev, netdev, Andy Fleming, Jason Wessel
In-Reply-To: <E1N62ti-0003iS-K2@jdl.com>

On Thu, Nov 05, 2009 at 08:01:10AM -0600, Jon Loeliger wrote:
> > When using KGDBoE, gianfar driver spits 'Interrupt problem' messages,
> > which appears to be a legitimate warning, i.e. we may end up calling
> > netif_receive_skb() or vlan_hwaccel_receive_skb() with IRQs disabled.
> > 
> > This patch reworks the RX path so that if netpoll is enabled (the
> > only case when the driver don't know from what context the polling
> > may be called), we check whether IRQs are disabled, and if so we
> > fall back to safe variants of skb receiving functions.
> > 
> > Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> > ---
> > 
> > I'm not sure if this is suitable for mainline since it doesn't
> > have KGDBoE support. Jason, if the patch is OK, would you like
> > to merge it into KGDB tree?
> 
> It's a legitimate problem with or without KGDBoE.  I see it
> occasionally when conn_track is enabled as well, for example.

Hm, then I'd better remove the #ifdef CONFIG_NETPOLL.

Interestingly though, why conn_track does the polling with irqs
disabled, could be a bug in the conn_track? Because pretty much
drivers assume that polling is called with IRQs enabled.

If it's easily reproducible, could you replace the printk() with
WARN_ON(1) and post the backtrace? Or I can try to reproduce the
issue if you tell me how.

Thanks!

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH] tcp: set SPLICE_F_NONBLOCK after first buffer has been spliced
From: Max Kellermann @ 2009-11-05 14:33 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-kernel, jens.axboe, Linux Netdev List
In-Reply-To: <4AF2DD21.8060604@gmail.com>

On 2009/11/05 15:11, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> It cannot, therefore an application uses O_NDELAY to avoid blocking.
> 
> Try following program if you are not convinced

Indeed, I'm surprised by the result rendered by the Linux kernel.
That however still contradicts with the poll() documentation.

So this boils down to the question: kernel bug or documentation bug?

http://www.opengroup.org/onlinepubs/9699919799/functions/pselect.html

"A descriptor shall be considered ready for writing when a call to an
output function with O_NONBLOCK clear would not block, whether or not
the function would transfer data successfully."

There is no size limit mentioned here.  Your program reveals that the
kernel violates this definition.

> Your patch basically makes SPLICE_F_NONBLOCK option always set
> (choice 1) above)
[...]
> Why in the first place have an option if it is always set ?

It is not, you misunderstood my patch.  If there's no room in the pipe
buffer, then the first iteration of the "while" loop will block (as
usual).  *After* the first iteration has finished (and at least one
buffer has been moved already), the flag is set, and further
iterations will not block.

^ permalink raw reply

* [PATCH 1/5] net/appletalk: push down BKL into a atalk_dgram_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
	Arnd Bergmann, Arnaldo Carvalho de Melo, Stephen Hemminger,
	netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>

Making the BKL usage explicit in appletalk makes it more
obvious where it is used, reduces code size and helps
getting rid of the BKL in common code.

I did not analyse how to kill lock_kernel from appletalk
entirely, this will involve either proving that it's not
needed, or replacing with a proper mutex or spinlock,
after finding out which data structures are protected
by the lock.

Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/appletalk/ddp.c |  105 +++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index b1a4290..3b831c0 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1054,11 +1054,13 @@ static int atalk_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
 
+	lock_kernel();
 	if (sk) {
 		sock_orphan(sk);
 		sock->sk = NULL;
 		atalk_destroy_socket(sk);
 	}
+	unlock_kernel();
 	return 0;
 }
 
@@ -1134,6 +1136,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	struct sockaddr_at *addr = (struct sockaddr_at *)uaddr;
 	struct sock *sk = sock->sk;
 	struct atalk_sock *at = at_sk(sk);
+	int err;
 
 	if (!sock_flag(sk, SOCK_ZAPPED) ||
 	    addr_len != sizeof(struct sockaddr_at))
@@ -1142,37 +1145,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (addr->sat_family != AF_APPLETALK)
 		return -EAFNOSUPPORT;
 
+	lock_kernel();
 	if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
 		struct atalk_addr *ap = atalk_find_primary();
 
+		err = -EADDRNOTAVAIL;
 		if (!ap)
-			return -EADDRNOTAVAIL;
+			goto out;
 
 		at->src_net  = addr->sat_addr.s_net = ap->s_net;
 		at->src_node = addr->sat_addr.s_node= ap->s_node;
 	} else {
+		err = -EADDRNOTAVAIL;
 		if (!atalk_find_interface(addr->sat_addr.s_net,
 					  addr->sat_addr.s_node))
-			return -EADDRNOTAVAIL;
+			goto out;
 
 		at->src_net  = addr->sat_addr.s_net;
 		at->src_node = addr->sat_addr.s_node;
 	}
 
 	if (addr->sat_port == ATADDR_ANYPORT) {
-		int n = atalk_pick_and_bind_port(sk, addr);
+		err = atalk_pick_and_bind_port(sk, addr);
 
-		if (n < 0)
-			return n;
+		if (err < 0)
+			goto out;
 	} else {
 		at->src_port = addr->sat_port;
 
+		err = -EADDRINUSE;
 		if (atalk_find_or_insert_socket(sk, addr))
-			return -EADDRINUSE;
+			goto out;
 	}
 
 	sock_reset_flag(sk, SOCK_ZAPPED);
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /* Set the address we talk to */
@@ -1182,6 +1192,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 	struct sock *sk = sock->sk;
 	struct atalk_sock *at = at_sk(sk);
 	struct sockaddr_at *addr;
+	int err;
 
 	sk->sk_state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
@@ -1206,12 +1217,15 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 #endif
 	}
 
+	lock_kernel();
+	err = -EBUSY;
 	if (sock_flag(sk, SOCK_ZAPPED))
 		if (atalk_autobind(sk) < 0)
-			return -EBUSY;
+			goto out;
 
+	err = -ENETUNREACH;
 	if (!atrtr_get_dev(&addr->sat_addr))
-		return -ENETUNREACH;
+		goto out;
 
 	at->dest_port = addr->sat_port;
 	at->dest_net  = addr->sat_addr.s_net;
@@ -1219,7 +1233,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 
 	sock->state  = SS_CONNECTED;
 	sk->sk_state = TCP_ESTABLISHED;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -1232,17 +1249,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
 	struct sockaddr_at sat;
 	struct sock *sk = sock->sk;
 	struct atalk_sock *at = at_sk(sk);
+	int err;
 
+	lock_kernel();
+	err = -ENOBUFS;
 	if (sock_flag(sk, SOCK_ZAPPED))
 		if (atalk_autobind(sk) < 0)
-			return -ENOBUFS;
+			goto out;
 
 	*uaddr_len = sizeof(struct sockaddr_at);
 	memset(&sat.sat_zero, 0, sizeof(sat.sat_zero));
 
 	if (peer) {
+		err = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
 		sat.sat_addr.s_net  = at->dest_net;
 		sat.sat_addr.s_node = at->dest_node;
@@ -1253,9 +1274,23 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
 		sat.sat_port	    = at->src_port;
 	}
 
+	err = 0;
 	sat.sat_family = AF_APPLETALK;
 	memcpy(uaddr, &sat, sizeof(sat));
-	return 0;
+
+out:
+	unlock_kernel();
+	return err;
+}
+
+static unsigned int atalk_poll(struct file *file, struct socket *sock,
+			   poll_table *wait)
+{
+	int err;
+	lock_kernel();
+	err = datagram_poll(file, sock, wait);
+	unlock_kernel();
+	return err;
 }
 
 #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
@@ -1563,23 +1598,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	if (len > DDP_MAXSZ)
 		return -EMSGSIZE;
 
+	lock_kernel();
 	if (usat) {
+		err = -EBUSY;
 		if (sock_flag(sk, SOCK_ZAPPED))
 			if (atalk_autobind(sk) < 0)
-				return -EBUSY;
+				goto out;
 
+		err = -EINVAL;
 		if (msg->msg_namelen < sizeof(*usat) ||
 		    usat->sat_family != AF_APPLETALK)
-			return -EINVAL;
+			goto out;
 
+		err = -EPERM;
 		/* netatalk didn't implement this check */
 		if (usat->sat_addr.s_node == ATADDR_BCAST &&
 		    !sock_flag(sk, SOCK_BROADCAST)) {
-			return -EPERM;
+			goto out;
 		}
 	} else {
+		err = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 		usat = &local_satalk;
 		usat->sat_family      = AF_APPLETALK;
 		usat->sat_port	      = at->dest_port;
@@ -1603,8 +1643,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
 		rt = atrtr_find(&at_hint);
 	}
+	err = ENETUNREACH;
 	if (!rt)
-		return -ENETUNREACH;
+		goto out;
 
 	dev = rt->dev;
 
@@ -1614,7 +1655,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	size += dev->hard_header_len;
 	skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
 	if (!skb)
-		return err;
+		goto out;
 
 	skb->sk = sk;
 	skb_reserve(skb, ddp_dl->header_length);
@@ -1637,7 +1678,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 	if (err) {
 		kfree_skb(skb);
-		return -EFAULT;
+		err = -EFAULT;
+		goto out;
 	}
 
 	if (sk->sk_no_check == 1)
@@ -1676,7 +1718,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 			rt = atrtr_find(&at_lo);
 			if (!rt) {
 				kfree_skb(skb);
-				return -ENETUNREACH;
+				err = -ENETUNREACH;
+				goto out;
 			}
 			dev = rt->dev;
 			skb->dev = dev;
@@ -1696,7 +1739,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	}
 	SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
 
-	return len;
+out:
+	unlock_kernel();
+	return err ? : len;
 }
 
 static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
@@ -1708,10 +1753,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	int copied = 0;
 	int offset = 0;
 	int err = 0;
-	struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+	struct sk_buff *skb;
+
+	lock_kernel();
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 						flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return err;
+		goto out;
 
 	/* FIXME: use skb->cb to be able to use shared skbs */
 	ddp = ddp_hdr(skb);
@@ -1739,6 +1787,9 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	}
 
 	skb_free_datagram(sk, skb);	/* Free the datagram. */
+
+out:
+	unlock_kernel();
 	return err ? : copied;
 }
 
@@ -1827,7 +1878,7 @@ static struct net_proto_family atalk_family_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops atalk_dgram_ops = {
 	.family		= PF_APPLETALK,
 	.owner		= THIS_MODULE,
 	.release	= atalk_release,
@@ -1836,7 +1887,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
 	.socketpair	= sock_no_socketpair,
 	.accept		= sock_no_accept,
 	.getname	= atalk_getname,
-	.poll		= datagram_poll,
+	.poll		= atalk_poll,
 	.ioctl		= atalk_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= atalk_compat_ioctl,
@@ -1851,8 +1902,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
 	.sendpage	= sock_no_sendpage,
 };
 
-SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);
-
 static struct notifier_block ddp_notifier = {
 	.notifier_call	= ddp_device_event,
 };
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 2/5] net/ipx: push down BKL into a ipx_dgram_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
	Arnd Bergmann, Arnaldo Carvalho de Melo, Stephen Hemminger,
	netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>

Making the BKL usage explicit in ipx makes it more
obvious where it is used, reduces code size and helps
getting rid of the BKL in common code.

I did not analyse how to kill lock_kernel from ipx
entirely, this will involve either proving that it's not
needed, or replacing with a proper mutex or spinlock,
after finding out which data structures are protected
by the lock.

Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/ipx/af_ipx.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 66c7a20..f542c5b 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1298,6 +1298,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
 	int opt;
 	int rc = -EINVAL;
 
+	lock_kernel();
 	if (optlen != sizeof(int))
 		goto out;
 
@@ -1312,6 +1313,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
 	ipx_sk(sk)->type = opt;
 	rc = 0;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1323,6 +1325,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
 	int len;
 	int rc = -ENOPROTOOPT;
 
+	lock_kernel();
 	if (!(level == SOL_IPX && optname == IPX_TYPE))
 		goto out;
 
@@ -1343,6 +1346,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
 
 	rc = 0;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1390,6 +1394,7 @@ static int ipx_release(struct socket *sock)
 	if (!sk)
 		goto out;
 
+	lock_kernel();
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_state_change(sk);
 
@@ -1397,6 +1402,7 @@ static int ipx_release(struct socket *sock)
 	sock->sk = NULL;
 	sk_refcnt_debug_release(sk);
 	ipx_destroy_socket(sk);
+	unlock_kernel();
 out:
 	return 0;
 }
@@ -1424,7 +1430,8 @@ static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
 	return htons(socketNum);
 }
 
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int __ipx_bind(struct socket *sock,
+			struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk = sock->sk;
 	struct ipx_sock *ipxs = ipx_sk(sk);
@@ -1519,6 +1526,17 @@ out:
 	return rc;
 }
 
+static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+	int rc;
+
+	lock_kernel();
+	rc = __ipx_bind(sock, uaddr, addr_len);
+	unlock_kernel();
+
+	return rc;
+}
+
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 	int addr_len, int flags)
 {
@@ -1531,6 +1549,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 	sk->sk_state	= TCP_CLOSE;
 	sock->state 	= SS_UNCONNECTED;
 
+	lock_kernel();
 	if (addr_len != sizeof(*addr))
 		goto out;
 	addr = (struct sockaddr_ipx *)uaddr;
@@ -1550,7 +1569,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 			IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
-		rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+		rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
 			      sizeof(struct sockaddr_ipx));
 		if (rc)
 			goto out;
@@ -1577,6 +1596,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 		ipxrtr_put(rt);
 	rc = 0;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1592,6 +1612,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
 	*uaddr_len = sizeof(struct sockaddr_ipx);
 
+	lock_kernel();
 	if (peer) {
 		rc = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
@@ -1626,6 +1647,19 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
 	rc = 0;
 out:
+	unlock_kernel();
+	return rc;
+}
+
+static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock,
+			   poll_table *wait)
+{
+	int rc;
+
+	lock_kernel();
+	rc = datagram_poll(file, sock, wait);
+	unlock_kernel();
+
 	return rc;
 }
 
@@ -1700,6 +1734,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
 	int rc = -EINVAL;
 	int flags = msg->msg_flags;
 
+	lock_kernel();
 	/* Socket gets bound below anyway */
 /*	if (sk->sk_zapped)
 		return -EIO; */	/* Socket not bound */
@@ -1723,7 +1758,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
 			memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
 				IPX_NODE_LEN);
 #endif
-			rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+			rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
 					sizeof(struct sockaddr_ipx));
 			if (rc)
 				goto out;
@@ -1751,6 +1786,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
 	if (rc >= 0)
 		rc = len;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1765,6 +1801,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 	struct sk_buff *skb;
 	int copied, rc;
 
+	lock_kernel();
 	/* put the autobinding in */
 	if (!ipxs->port) {
 		struct sockaddr_ipx uaddr;
@@ -1779,7 +1816,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 		memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
-		rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+		rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
 			      sizeof(struct sockaddr_ipx));
 		if (rc)
 			goto out;
@@ -1823,6 +1860,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 out_free:
 	skb_free_datagram(sk, skb);
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1834,6 +1872,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	struct sock *sk = sock->sk;
 	void __user *argp = (void __user *)arg;
 
+	lock_kernel();
 	switch (cmd) {
 	case TIOCOUTQ:
 		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1896,6 +1935,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		rc = -ENOIOCTLCMD;
 		break;
 	}
+	unlock_kernel();
 
 	return rc;
 }
@@ -1933,7 +1973,7 @@ static struct net_proto_family ipx_family_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
+static const struct proto_ops ipx_dgram_ops = {
 	.family		= PF_IPX,
 	.owner		= THIS_MODULE,
 	.release	= ipx_release,
@@ -1942,7 +1982,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
 	.socketpair	= sock_no_socketpair,
 	.accept		= sock_no_accept,
 	.getname	= ipx_getname,
-	.poll		= datagram_poll,
+	.poll		= ipx_datagram_poll,
 	.ioctl		= ipx_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ipx_compat_ioctl,
@@ -1957,8 +1997,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
 	.sendpage	= sock_no_sendpage,
 };
 
-SOCKOPS_WRAP(ipx_dgram, PF_IPX);
-
 static struct packet_type ipx_8023_packet_type __read_mostly = {
 	.type		= cpu_to_be16(ETH_P_802_3),
 	.func		= ipx_rcv,
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 4/5] net/x25: push BKL usage into x25_proto
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
	Arnd Bergmann, Henner Eisen, linux-x25, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>

The x25 driver uses lock_kernel() implicitly through
its proto_ops wrapper. The makes the usage explicit
in order to get rid of that wrapper and to better document
the usage of the BKL.

The next step should be to get rid of the usage of the BKL
in x25 entirely, which requires understanding what data
structures need serialized accesses.

Cc: Henner Eisen <eis@baty.hanse.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-x25@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/x25/af_x25.c |   71 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 7fa9c7a..a7a4bc2 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
 	struct sock *sk = sock->sk;
 	int rc = -ENOPROTOOPT;
 
+	lock_kernel();
 	if (level != SOL_X25 || optname != X25_QBITINCL)
 		goto out;
 
@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
 	x25_sk(sk)->qbitincl = !!opt;
 	rc = 0;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
 	struct sock *sk = sock->sk;
 	int val, len, rc = -ENOPROTOOPT;
 
+	lock_kernel();
 	if (level != SOL_X25 || optname != X25_QBITINCL)
 		goto out;
 
@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
 	val = x25_sk(sk)->qbitincl;
 	rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog)
 	struct sock *sk = sock->sk;
 	int rc = -EOPNOTSUPP;
 
+	lock_kernel();
 	if (sk->sk_state != TCP_LISTEN) {
 		memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
 		sk->sk_max_ack_backlog = backlog;
 		sk->sk_state           = TCP_LISTEN;
 		rc = 0;
 	}
+	unlock_kernel();
 
 	return rc;
 }
@@ -597,6 +603,7 @@ static int x25_release(struct socket *sock)
 	struct sock *sk = sock->sk;
 	struct x25_sock *x25;
 
+	lock_kernel();
 	if (!sk)
 		goto out;
 
@@ -627,6 +634,7 @@ static int x25_release(struct socket *sock)
 
 	sock_orphan(sk);
 out:
+	unlock_kernel();
 	return 0;
 }
 
@@ -634,18 +642,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
+	int rc = 0;
 
+	lock_kernel();
 	if (!sock_flag(sk, SOCK_ZAPPED) ||
 	    addr_len != sizeof(struct sockaddr_x25) ||
-	    addr->sx25_family != AF_X25)
-		return -EINVAL;
+	    addr->sx25_family != AF_X25) {
+		rc = -EINVAL;
+		goto out;
+	}
 
 	x25_sk(sk)->source_addr = addr->sx25_addr;
 	x25_insert_socket(sk);
 	sock_reset_flag(sk, SOCK_ZAPPED);
 	SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
-
-	return 0;
+out:
+	unlock_kernel();
+	return rc;
 }
 
 static int x25_wait_for_connection_establishment(struct sock *sk)
@@ -686,6 +699,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
 	struct x25_route *rt;
 	int rc = 0;
 
+	lock_kernel();
 	lock_sock(sk);
 	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -763,6 +777,7 @@ out_put_route:
 	x25_route_put(rt);
 out:
 	release_sock(sk);
+	unlock_kernel();
 	return rc;
 }
 
@@ -802,6 +817,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
 	struct sk_buff *skb;
 	int rc = -EINVAL;
 
+	lock_kernel();
 	if (!sk || sk->sk_state != TCP_LISTEN)
 		goto out;
 
@@ -829,6 +845,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
 out2:
 	release_sock(sk);
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -838,10 +855,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
 	struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
 	struct sock *sk = sock->sk;
 	struct x25_sock *x25 = x25_sk(sk);
+	int rc = 0;
 
+	lock_kernel();
 	if (peer) {
-		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+		if (sk->sk_state != TCP_ESTABLISHED) {
+			rc = -ENOTCONN;
+			goto out;
+		}
 		sx25->sx25_addr = x25->dest_addr;
 	} else
 		sx25->sx25_addr = x25->source_addr;
@@ -849,7 +870,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
 	sx25->sx25_family = AF_X25;
 	*uaddr_len = sizeof(*sx25);
 
-	return 0;
+out:
+	unlock_kernel();
+	return rc;
+}
+
+static unsigned int x25_datagram_poll(struct file *file, struct socket *sock,
+			   poll_table *wait)
+{
+	int rc;
+
+	lock_kernel();
+	rc = datagram_poll(file, sock, wait);
+	unlock_kernel();
+
+	return rc;
 }
 
 int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
@@ -1002,6 +1037,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
 	size_t size;
 	int qbit = 0, rc = -EINVAL;
 
+	lock_kernel();
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
 		goto out;
 
@@ -1166,6 +1202,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
 	release_sock(sk);
 	rc = len;
 out:
+	unlock_kernel();
 	return rc;
 out_kfree_skb:
 	kfree_skb(skb);
@@ -1186,6 +1223,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 	unsigned char *asmptr;
 	int rc = -ENOTCONN;
 
+	lock_kernel();
 	/*
 	 * This works for seqpacket too. The receiver has ordered the queue for
 	 * us! We do one quick check first though
@@ -1259,6 +1297,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 out_free_dgram:
 	skb_free_datagram(sk, skb);
 out:
+	unlock_kernel();
 	return rc;
 }
 
@@ -1270,6 +1309,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	void __user *argp = (void __user *)arg;
 	int rc;
 
+	lock_kernel();
 	switch (cmd) {
 		case TIOCOUTQ: {
 			int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1472,6 +1512,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 			rc = -ENOIOCTLCMD;
 			break;
 	}
+	unlock_kernel();
 
 	return rc;
 }
@@ -1542,15 +1583,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
 		break;
 	case SIOCGSTAMP:
 		rc = -EINVAL;
+		lock_kernel();
 		if (sk)
 			rc = compat_sock_get_timestamp(sk,
 					(struct timeval __user*)argp);
+		unlock_kernel();
 		break;
 	case SIOCGSTAMPNS:
 		rc = -EINVAL;
+		lock_kernel();
 		if (sk)
 			rc = compat_sock_get_timestampns(sk,
 					(struct timespec __user*)argp);
+		unlock_kernel();
 		break;
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
@@ -1569,16 +1614,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
 		rc = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
 			break;
+		lock_kernel();
 		rc = x25_route_ioctl(cmd, argp);
+		unlock_kernel();
 		break;
 	case SIOCX25GSUBSCRIP:
+		lock_kernel();
 		rc = compat_x25_subscr_ioctl(cmd, argp);
+		unlock_kernel();
 		break;
 	case SIOCX25SSUBSCRIP:
 		rc = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
 			break;
+		lock_kernel();
 		rc = compat_x25_subscr_ioctl(cmd, argp);
+		unlock_kernel();
 		break;
 	case SIOCX25GFACILITIES:
 	case SIOCX25SFACILITIES:
@@ -1600,7 +1651,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
 }
 #endif
 
-static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
+static const struct proto_ops x25_proto_ops = {
 	.family =	AF_X25,
 	.owner =	THIS_MODULE,
 	.release =	x25_release,
@@ -1609,7 +1660,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
 	.socketpair =	sock_no_socketpair,
 	.accept =	x25_accept,
 	.getname =	x25_getname,
-	.poll =		datagram_poll,
+	.poll =		x25_datagram_poll,
 	.ioctl =	x25_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = compat_x25_ioctl,
@@ -1624,8 +1675,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
 	.sendpage =	sock_no_sendpage,
 };
 
-SOCKOPS_WRAP(x25_proto, AF_X25);
-
 static struct packet_type x25_packet_type __read_mostly = {
 	.type =	cpu_to_be16(ETH_P_X25),
 	.func =	x25_lapb_receive_frame,
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 5/5] net: kill proto_ops wrapper
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
	Arnd Bergmann, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>

All users of wrapped proto_ops are now gone, so we can safely remove
the wrappers as well.

Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/net.h |   83 ---------------------------------------------------
 1 files changed, 0 insertions(+), 83 deletions(-)

diff --git a/include/linux/net.h b/include/linux/net.h
index 529a093..041a8e4 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -263,89 +263,6 @@ extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
 extern int kernel_sock_shutdown(struct socket *sock,
 				enum sock_shutdown_cmd how);
 
-#ifndef CONFIG_SMP
-#define SOCKOPS_WRAPPED(name) name
-#define SOCKOPS_WRAP(name, fam)
-#else
-
-#define SOCKOPS_WRAPPED(name) __unlocked_##name
-
-#define SOCKCALL_WRAP(name, call, parms, args)		\
-static int __lock_##name##_##call  parms		\
-{							\
-	int ret;					\
-	lock_kernel();					\
-	ret = __unlocked_##name##_ops.call  args ;\
-	unlock_kernel();				\
-	return ret;					\
-}
-
-#define SOCKCALL_UWRAP(name, call, parms, args)		\
-static unsigned int __lock_##name##_##call  parms	\
-{							\
-	int ret;					\
-	lock_kernel();					\
-	ret = __unlocked_##name##_ops.call  args ;\
-	unlock_kernel();				\
-	return ret;					\
-}
-
-
-#define SOCKOPS_WRAP(name, fam)					\
-SOCKCALL_WRAP(name, release, (struct socket *sock), (sock))	\
-SOCKCALL_WRAP(name, bind, (struct socket *sock, struct sockaddr *uaddr, int addr_len), \
-	      (sock, uaddr, addr_len))				\
-SOCKCALL_WRAP(name, connect, (struct socket *sock, struct sockaddr * uaddr, \
-			      int addr_len, int flags), 	\
-	      (sock, uaddr, addr_len, flags))			\
-SOCKCALL_WRAP(name, socketpair, (struct socket *sock1, struct socket *sock2), \
-	      (sock1, sock2))					\
-SOCKCALL_WRAP(name, accept, (struct socket *sock, struct socket *newsock, \
-			 int flags), (sock, newsock, flags)) \
-SOCKCALL_WRAP(name, getname, (struct socket *sock, struct sockaddr *uaddr, \
-			 int *addr_len, int peer), (sock, uaddr, addr_len, peer)) \
-SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_table_struct *wait), \
-	      (file, sock, wait)) \
-SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \
-			 unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \
-			 unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \
-SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
-SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
-			 char __user *optval, unsigned int optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
-			 char __user *optval, int __user *optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len), \
-	      (iocb, sock, m, len)) \
-SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags), \
-	      (iocb, sock, m, len, flags)) \
-SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
-	      (file, sock, vma)) \
-	      \
-static const struct proto_ops name##_ops = {			\
-	.family		= fam,				\
-	.owner		= THIS_MODULE,			\
-	.release	= __lock_##name##_release,	\
-	.bind		= __lock_##name##_bind,		\
-	.connect	= __lock_##name##_connect,	\
-	.socketpair	= __lock_##name##_socketpair,	\
-	.accept		= __lock_##name##_accept,	\
-	.getname	= __lock_##name##_getname,	\
-	.poll		= __lock_##name##_poll,		\
-	.ioctl		= __lock_##name##_ioctl,	\
-	.compat_ioctl	= __lock_##name##_compat_ioctl,	\
-	.listen		= __lock_##name##_listen,	\
-	.shutdown	= __lock_##name##_shutdown,	\
-	.setsockopt	= __lock_##name##_setsockopt,	\
-	.getsockopt	= __lock_##name##_getsockopt,	\
-	.sendmsg	= __lock_##name##_sendmsg,	\
-	.recvmsg	= __lock_##name##_recvmsg,	\
-	.mmap		= __lock_##name##_mmap,		\
-};
-
-#endif
-
 #define MODULE_ALIAS_NETPROTO(proto) \
 	MODULE_ALIAS("net-pf-" __stringify(proto))
 
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 3/5] net/irda: push BKL into proto_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
	Arnd Bergmann, Samuel Ortiz, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>

The irda driver uses the BKL implicitly in its protocol
operations. Replace the wrapped proto_ops with explicit
lock_kernel() calls makes the usage more obvious and
shrinks the size of the object code.

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out
which data actually needs protection.

Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/irda/af_irda.c |  331 +++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 224 insertions(+), 107 deletions(-)

diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index dd35641..7f84866 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
 	struct sockaddr_irda saddr;
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
+	int err;
 
+	lock_kernel();
 	memset(&saddr, 0, sizeof(saddr));
 	if (peer) {
+		err  = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
 		saddr.sir_family = AF_IRDA;
 		saddr.sir_lsap_sel = self->dtsap_sel;
@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
 	/* uaddr_len come to us uninitialised */
 	*uaddr_len = sizeof (struct sockaddr_irda);
 	memcpy(uaddr, &saddr, *uaddr_len);
-
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
 static int irda_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
+	int err = -EOPNOTSUPP;
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
+	lock_kernel();
 	if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
 	    (sk->sk_type != SOCK_DGRAM))
-		return -EOPNOTSUPP;
+		goto out;
 
 	if (sk->sk_state != TCP_LISTEN) {
 		sk->sk_max_ack_backlog = backlog;
 		sk->sk_state           = TCP_LISTEN;
 
-		return 0;
+		err = 0;
 	}
+out:
+	unlock_kernel();
 
-	return -EOPNOTSUPP;
+	return err;
 }
 
 /*
@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
+	lock_kernel();
 #ifdef CONFIG_IRDA_ULTRA
 	/* Special care for Ultra sockets */
 	if ((sk->sk_type == SOCK_DGRAM) &&
 	    (sk->sk_protocol == IRDAPROTO_ULTRA)) {
 		self->pid = addr->sir_lsap_sel;
+		err = -EOPNOTSUPP;
 		if (self->pid & 0x80) {
 			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
-			return -EOPNOTSUPP;
+			goto out;
 		}
 		err = irda_open_lsap(self, self->pid);
 		if (err < 0)
-			return err;
+			goto out;
 
 		/* Pretend we are connected */
 		sock->state = SS_CONNECTED;
 		sk->sk_state   = TCP_ESTABLISHED;
+		err = 0;
 
-		return 0;
+		goto out;
 	}
 #endif /* CONFIG_IRDA_ULTRA */
 
 	self->ias_obj = irias_new_object(addr->sir_name, jiffies);
+	err = -ENOMEM;
 	if (self->ias_obj == NULL)
-		return -ENOMEM;
+		goto out;
 
 	err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
 	if (err < 0) {
 		kfree(self->ias_obj->name);
 		kfree(self->ias_obj);
-		return err;
+		goto out;
 	}
 
 	/*  Register with LM-IAS */
@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 				 self->stsap_sel, IAS_KERNEL_ATTR);
 	irias_insert_object(self->ias_obj);
 
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
+	lock_kernel();
 	err = irda_create(sock_net(sk), newsock, sk->sk_protocol);
 	if (err)
-		return err;
+		goto out;;
 
+	err = -EINVAL;
 	if (sock->state != SS_UNCONNECTED)
-		return -EINVAL;
+		goto out;
 
 	if ((sk = sock->sk) == NULL)
-		return -EINVAL;
+		goto out;
 
+	err = -EOPNOTSUPP;
 	if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
 	    (sk->sk_type != SOCK_DGRAM))
-		return -EOPNOTSUPP;
+		goto out;
 
+	err = -EINVAL;
 	if (sk->sk_state != TCP_LISTEN)
-		return -EINVAL;
+		goto out;
 
 	/*
 	 *	The read queue this time is holding sockets ready to use
@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
 			break;
 
 		/* Non blocking operation */
+		err = -EWOULDBLOCK;
 		if (flags & O_NONBLOCK)
-			return -EWOULDBLOCK;
+			goto out;
 
 		err = wait_event_interruptible(*(sk->sk_sleep),
 					skb_peek(&sk->sk_receive_queue));
 		if (err)
-			return err;
+			goto out;
 	}
 
 	newsk = newsock->sk;
+	err = -EIO;
 	if (newsk == NULL)
-		return -EIO;
+		goto out;
 
 	newsk->sk_state = TCP_ESTABLISHED;
 
@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
 
 	/* Now attach up the new socket */
 	new->tsap = irttp_dup(self->tsap, new);
+	err = -EPERM; /* value does not seem to make sense. -arnd */
 	if (!new->tsap) {
 		IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
 		kfree_skb(skb);
-		return -1;
+		goto out;
 	}
 
 	new->stsap_sel = new->tsap->stsap_sel;
@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
 	newsock->state = SS_CONNECTED;
 
 	irda_connect_response(new);
-
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
 
 	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
 
+	lock_kernel();
 	/* Don't allow connect for Ultra sockets */
+	err = -ESOCKTNOSUPPORT;
 	if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
-		return -ESOCKTNOSUPPORT;
+		goto out;
 
 	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
-		return 0;   /* Connect completed during a ERESTARTSYS event */
+		err = 0;
+		goto out;   /* Connect completed during a ERESTARTSYS event */
 	}
 
 	if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
 		sock->state = SS_UNCONNECTED;
-		return -ECONNREFUSED;
+		err = -ECONNREFUSED;
+		goto out;
 	}
 
+	err = -EISCONN;      /* No reconnect on a seqpacket socket */
 	if (sk->sk_state == TCP_ESTABLISHED)
-		return -EISCONN;      /* No reconnect on a seqpacket socket */
+		goto out;
 
 	sk->sk_state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
+	err = -EINVAL;
 	if (addr_len != sizeof(struct sockaddr_irda))
-		return -EINVAL;
+		goto out;
 
 	/* Check if user supplied any destination device address */
 	if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) {
@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
 		err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
 		if (err) {
 			IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
-			return err;
+			goto out;
 		}
 	} else {
 		/* Use the one provided by the user */
@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
 			err = irda_find_lsap_sel(self, addr->sir_name);
 			if (err) {
 				IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
-				return err;
+				goto out;
 			}
 		} else {
 			/* Directly connect to the remote LSAP
@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
 				    self->max_sdu_size_rx, NULL);
 	if (err) {
 		IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
-		return err;
+		goto out;
 	}
 
 	/* Now the loop */
+	err = -EINPROGRESS;
 	if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
-		return -EINPROGRESS;
+		goto out;
 
+	err = -ERESTARTSYS;
 	if (wait_event_interruptible(*(sk->sk_sleep),
 				     (sk->sk_state != TCP_SYN_SENT)))
-		return -ERESTARTSYS;
+		goto out;
 
 	if (sk->sk_state != TCP_ESTABLISHED) {
 		sock->state = SS_UNCONNECTED;
 		err = sock_error(sk);
-		return err? err : -ECONNRESET;
+		if (!err)
+			err = -ECONNRESET;
+		goto out;
 	}
 
 	sock->state = SS_CONNECTED;
 
 	/* At this point, IrLMP has assigned our source address */
 	self->saddr = irttp_get_saddr(self->tsap);
-
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 static struct proto irda_proto = {
@@ -1192,6 +1229,7 @@ static int irda_release(struct socket *sock)
 	if (sk == NULL)
 		return 0;
 
+	lock_kernel();
 	lock_sock(sk);
 	sk->sk_state       = TCP_CLOSE;
 	sk->sk_shutdown   |= SEND_SHUTDOWN;
@@ -1210,6 +1248,7 @@ static int irda_release(struct socket *sock)
 	/* Destroy networking socket if we are the last reference on it,
 	 * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */
 	sock_put(sk);
+	unlock_kernel();
 
 	/* Notes on socket locking and deallocation... - Jean II
 	 * In theory we should put pairs of sock_hold() / sock_put() to
@@ -1257,28 +1296,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
+	lock_kernel();
 	/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
 	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
-			       MSG_NOSIGNAL))
-		return -EINVAL;
+			       MSG_NOSIGNAL)) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (sk->sk_shutdown & SEND_SHUTDOWN)
 		goto out_err;
 
-	if (sk->sk_state != TCP_ESTABLISHED)
-		return -ENOTCONN;
+	if (sk->sk_state != TCP_ESTABLISHED) {
+		err = -ENOTCONN;
+		goto out;
+	}
 
 	self = irda_sk(sk);
 
 	/* Check if IrTTP is wants us to slow down */
 
 	if (wait_event_interruptible(*(sk->sk_sleep),
-	    (self->tx_flow != FLOW_STOP  ||  sk->sk_state != TCP_ESTABLISHED)))
-		return -ERESTARTSYS;
+	    (self->tx_flow != FLOW_STOP  ||  sk->sk_state != TCP_ESTABLISHED))) {
+		err = -ERESTARTSYS;
+		goto out;
+	}
 
 	/* Check if we are still connected */
-	if (sk->sk_state != TCP_ESTABLISHED)
-		return -ENOTCONN;
+	if (sk->sk_state != TCP_ESTABLISHED) {
+		err = -ENOTCONN;
+		goto out;
+	}
 
 	/* Check that we don't send out too big frames */
 	if (len > self->max_data_size) {
@@ -1310,11 +1358,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
 		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
 		goto out_err;
 	}
+
+	unlock_kernel();
 	/* Tell client how much data we actually sent */
 	return len;
 
- out_err:
-	return sk_stream_error(sk, msg->msg_flags, err);
+out_err:
+	err = sk_stream_error(sk, msg->msg_flags, err);
+out:
+	unlock_kernel();
+	return err;
 
 }
 
@@ -1335,13 +1388,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
+	lock_kernel();
 	if ((err = sock_error(sk)) < 0)
-		return err;
+		goto out;
 
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return err;
+		goto out;
 
 	skb_reset_transport_header(skb);
 	copied = skb->len;
@@ -1369,8 +1423,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
 	}
-
+	unlock_kernel();
 	return copied;
+
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -1388,15 +1446,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
 
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
+	lock_kernel();
 	if ((err = sock_error(sk)) < 0)
-		return err;
+		goto out;
 
+	err = -EINVAL;
 	if (sock->flags & __SO_ACCEPTCON)
-		return(-EINVAL);
+		goto out;
 
+	err =-EOPNOTSUPP;
 	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
+		goto out;
 
+	err = 0;
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
 	timeo = sock_rcvtimeo(sk, noblock);
 
@@ -1408,7 +1470,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
 
 		if (skb == NULL) {
 			DEFINE_WAIT(wait);
-			int ret = 0;
+			err = 0;
 
 			if (copied >= target)
 				break;
@@ -1418,25 +1480,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
 			/*
 			 *	POSIX 1003.1g mandates this order.
 			 */
-			ret = sock_error(sk);
-			if (ret)
+			err = sock_error(sk);
+			if (err)
 				;
 			else if (sk->sk_shutdown & RCV_SHUTDOWN)
 				;
 			else if (noblock)
-				ret = -EAGAIN;
+				err = -EAGAIN;
 			else if (signal_pending(current))
-				ret = sock_intr_errno(timeo);
+				err = sock_intr_errno(timeo);
 			else if (sk->sk_state != TCP_ESTABLISHED)
-				ret = -ENOTCONN;
+				err = -ENOTCONN;
 			else if (skb_peek(&sk->sk_receive_queue) == NULL)
 				/* Wait process until data arrives */
 				schedule();
 
 			finish_wait(sk->sk_sleep, &wait);
 
-			if (ret)
-				return ret;
+			if (err)
+				goto out;
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
 				break;
 
@@ -1489,7 +1551,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
 		}
 	}
 
-	return copied;
+out:
+	unlock_kernel();
+	return err ? : copied;
 }
 
 /*
@@ -1507,18 +1571,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
 	struct sk_buff *skb;
 	int err;
 
+	lock_kernel();
+
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
+	err = -EINVAL;
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
-		return -EINVAL;
+		goto out;
 
 	if (sk->sk_shutdown & SEND_SHUTDOWN) {
 		send_sig(SIGPIPE, current, 0);
-		return -EPIPE;
+		err = -EPIPE;
+		goto out;
 	}
 
+	err = -ENOTCONN;
 	if (sk->sk_state != TCP_ESTABLISHED)
-		return -ENOTCONN;
+		goto out;
 
 	self = irda_sk(sk);
 
@@ -1535,8 +1604,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
 
 	skb = sock_alloc_send_skb(sk, len + self->max_header_size,
 				  msg->msg_flags & MSG_DONTWAIT, &err);
+	err = -ENOBUFS;
 	if (!skb)
-		return -ENOBUFS;
+		goto out;
 
 	skb_reserve(skb, self->max_header_size);
 	skb_reset_transport_header(skb);
@@ -1546,7 +1616,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
 	err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
 	if (err) {
 		kfree_skb(skb);
-		return err;
+		goto out;
 	}
 
 	/*
@@ -1556,9 +1626,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
 	err = irttp_udata_request(self->tsap, skb);
 	if (err) {
 		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
-		return err;
+		goto out;
 	}
+	unlock_kernel();
 	return len;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -1580,12 +1654,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
 
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
+	lock_kernel();
+	err = -EINVAL;
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
-		return -EINVAL;
+		goto out;
 
+	err = -EPIPE;
 	if (sk->sk_shutdown & SEND_SHUTDOWN) {
 		send_sig(SIGPIPE, current, 0);
-		return -EPIPE;
+		goto out;
 	}
 
 	self = irda_sk(sk);
@@ -1593,16 +1670,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
 	/* Check if an address was specified with sendto. Jean II */
 	if (msg->msg_name) {
 		struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name;
+		err = -EINVAL;
 		/* Check address, extract pid. Jean II */
 		if (msg->msg_namelen < sizeof(*addr))
-			return -EINVAL;
+			goto out;
 		if (addr->sir_family != AF_IRDA)
-			return -EINVAL;
+			goto out;
 
 		pid = addr->sir_lsap_sel;
 		if (pid & 0x80) {
 			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
-			return -EOPNOTSUPP;
+			err = -EOPNOTSUPP;
+			goto out;
 		}
 	} else {
 		/* Check that the socket is properly bound to an Ultra
@@ -1611,7 +1690,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
 		    (sk->sk_state != TCP_ESTABLISHED)) {
 			IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
 				   __func__);
-			return -ENOTCONN;
+			err = -ENOTCONN;
+			goto out;
 		}
 		/* Use PID from socket */
 		bound = 1;
@@ -1630,8 +1710,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
 
 	skb = sock_alloc_send_skb(sk, len + self->max_header_size,
 				  msg->msg_flags & MSG_DONTWAIT, &err);
+	err = -ENOBUFS;
 	if (!skb)
-		return -ENOBUFS;
+		goto out;
 
 	skb_reserve(skb, self->max_header_size);
 	skb_reset_transport_header(skb);
@@ -1641,16 +1722,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
 	err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
 	if (err) {
 		kfree_skb(skb);
-		return err;
+		goto out;
 	}
 
 	err = irlmp_connless_data_request((bound ? self->lsap : NULL),
 					  skb, pid);
-	if (err) {
+	if (err)
 		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
-		return err;
-	}
-	return len;
+out:
+	unlock_kernel();
+	return err ? : len;
 }
 #endif /* CONFIG_IRDA_ULTRA */
 
@@ -1664,6 +1745,8 @@ static int irda_shutdown(struct socket *sock, int how)
 
 	IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
 
+	lock_kernel();
+
 	sk->sk_state       = TCP_CLOSE;
 	sk->sk_shutdown   |= SEND_SHUTDOWN;
 	sk->sk_state_change(sk);
@@ -1684,6 +1767,8 @@ static int irda_shutdown(struct socket *sock, int how)
 	self->daddr = DEV_ADDR_ANY;	/* Until we get re-connected */
 	self->saddr = 0x0;		/* so IrLMP assign us any link */
 
+	unlock_kernel();
+
 	return 0;
 }
 
@@ -1699,6 +1784,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
+	lock_kernel();
 	poll_wait(file, sk->sk_sleep, wait);
 	mask = 0;
 
@@ -1746,18 +1832,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
 	default:
 		break;
 	}
+	unlock_kernel();
 	return mask;
 }
 
+static unsigned int irda_datagram_poll(struct file *file, struct socket *sock,
+			   poll_table *wait)
+{
+	int err;
+
+	lock_kernel();
+	err = datagram_poll(file, sock, wait);
+	unlock_kernel();
+
+	return err;
+}
+
 /*
  * Function irda_ioctl (sock, cmd, arg)
  */
 static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
+	int err;
 
 	IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
 
+	lock_kernel();
+	err = -EINVAL;
 	switch (cmd) {
 	case TIOCOUTQ: {
 		long amount;
@@ -1765,9 +1867,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
 		if (amount < 0)
 			amount = 0;
-		if (put_user(amount, (unsigned int __user *)arg))
-			return -EFAULT;
-		return 0;
+		err = put_user(amount, (unsigned int __user *)arg);
+		break;
 	}
 
 	case TIOCINQ: {
@@ -1776,15 +1877,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		/* These two are safe on a single CPU system as only user tasks fiddle here */
 		if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
 			amount = skb->len;
-		if (put_user(amount, (unsigned int __user *)arg))
-			return -EFAULT;
-		return 0;
+		err = put_user(amount, (unsigned int __user *)arg);
+		break;
 	}
 
 	case SIOCGSTAMP:
 		if (sk != NULL)
-			return sock_get_timestamp(sk, (struct timeval __user *)arg);
-		return -EINVAL;
+			err = sock_get_timestamp(sk, (struct timeval __user *)arg);
+		break;
 
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
@@ -1796,14 +1896,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	case SIOCSIFNETMASK:
 	case SIOCGIFMETRIC:
 	case SIOCSIFMETRIC:
-		return -EINVAL;
+		break;
 	default:
 		IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
-		return -ENOIOCTLCMD;
+		err = -ENOIOCTLCMD;
 	}
+	unlock_kernel();
 
-	/*NOTREACHED*/
-	return 0;
+	return err;
 }
 
 #ifdef CONFIG_COMPAT
@@ -1825,7 +1925,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
  *    Set some options for the socket
  *
  */
-static int irda_setsockopt(struct socket *sock, int level, int optname,
+static int __irda_setsockopt(struct socket *sock, int level, int optname,
 			   char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
@@ -2083,6 +2183,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
 	return 0;
 }
 
+static int irda_setsockopt(struct socket *sock, int level, int optname,
+			   char __user *optval, unsigned int optlen)
+{
+	int err;
+
+	lock_kernel();
+	err = __irda_setsockopt(sock, level, optname, optval, optlen);
+	unlock_kernel();
+
+	return err;
+}
+
 /*
  * Function irda_extract_ias_value(ias_opt, ias_value)
  *
@@ -2135,7 +2247,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
 /*
  * Function irda_getsockopt (sock, level, optname, optval, optlen)
  */
-static int irda_getsockopt(struct socket *sock, int level, int optname,
+static int __irda_getsockopt(struct socket *sock, int level, int optname,
 			   char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
@@ -2463,13 +2575,25 @@ bed:
 	return 0;
 }
 
+static int irda_getsockopt(struct socket *sock, int level, int optname,
+			   char __user *optval, int __user *optlen)
+{
+	int err;
+
+	lock_kernel();
+	err = __irda_getsockopt(sock, level, optname, optval, optlen);
+	unlock_kernel();
+
+	return err;
+}
+
 static struct net_proto_family irda_family_ops = {
 	.family = PF_IRDA,
 	.create = irda_create,
 	.owner	= THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
+static const struct proto_ops irda_stream_ops = {
 	.family =	PF_IRDA,
 	.owner =	THIS_MODULE,
 	.release =	irda_release,
@@ -2493,7 +2617,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
 	.sendpage =	sock_no_sendpage,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
+static const struct proto_ops irda_seqpacket_ops = {
 	.family =	PF_IRDA,
 	.owner =	THIS_MODULE,
 	.release =	irda_release,
@@ -2502,7 +2626,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
 	.socketpair =	sock_no_socketpair,
 	.accept =	irda_accept,
 	.getname =	irda_getname,
-	.poll =		datagram_poll,
+	.poll =		irda_datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
@@ -2517,7 +2641,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
 	.sendpage =	sock_no_sendpage,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static const struct proto_ops irda_dgram_ops = {
 	.family =	PF_IRDA,
 	.owner =	THIS_MODULE,
 	.release =	irda_release,
@@ -2526,7 +2650,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
 	.socketpair =	sock_no_socketpair,
 	.accept =	irda_accept,
 	.getname =	irda_getname,
-	.poll =		datagram_poll,
+	.poll =		irda_datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
@@ -2542,7 +2666,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
 };
 
 #ifdef CONFIG_IRDA_ULTRA
-static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+static const struct proto_ops irda_ultra_ops = {
 	.family =	PF_IRDA,
 	.owner =	THIS_MODULE,
 	.release =	irda_release,
@@ -2551,7 +2675,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
 	.getname =	irda_getname,
-	.poll =		datagram_poll,
+	.poll =		irda_datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
@@ -2567,13 +2691,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
 };
 #endif /* CONFIG_IRDA_ULTRA */
 
-SOCKOPS_WRAP(irda_stream, PF_IRDA);
-SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
-SOCKOPS_WRAP(irda_dgram, PF_IRDA);
-#ifdef CONFIG_IRDA_ULTRA
-SOCKOPS_WRAP(irda_ultra, PF_IRDA);
-#endif /* CONFIG_IRDA_ULTRA */
-
 /*
  * Function irsock_init (pro)
  *
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Jon Loeliger @ 2009-11-05 14:01 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: David Miller, linuxppc-dev, netdev, Andy Fleming, Jason Wessel
In-Reply-To: <20091104225711.GA30844@oksana.dev.rtsoft.ru>

> When using KGDBoE, gianfar driver spits 'Interrupt problem' messages,
> which appears to be a legitimate warning, i.e. we may end up calling
> netif_receive_skb() or vlan_hwaccel_receive_skb() with IRQs disabled.
> 
> This patch reworks the RX path so that if netpoll is enabled (the
> only case when the driver don't know from what context the polling
> may be called), we check whether IRQs are disabled, and if so we
> fall back to safe variants of skb receiving functions.
> 
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> 
> I'm not sure if this is suitable for mainline since it doesn't
> have KGDBoE support. Jason, if the patch is OK, would you like
> to merge it into KGDB tree?

It's a legitimate problem with or without KGDBoE.  I see it
occasionally when conn_track is enabled as well, for example.

jdl

^ permalink raw reply

* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Jon Loeliger @ 2009-11-05 14:41 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, Jason Wessel, Andy Fleming, David Miller, netdev
In-Reply-To: <20091105142028.GB17171@oksana.dev.rtsoft.ru>

> 
> Hm, then I'd better remove the #ifdef CONFIG_NETPOLL.
> 
> Interestingly though, why conn_track does the polling with irqs
> disabled, could be a bug in the conn_track? Because pretty much
> drivers assume that polling is called with IRQs enabled.
> 
> If it's easily reproducible, could you replace the printk() with
> WARN_ON(1) and post the backtrace? Or I can try to reproduce the
> issue if you tell me how.
> 
> Thanks!

Yeah, I can reproduce it.  I'll try and get that for you.

jdl

^ permalink raw reply

* Re: [PATCH] netfilter: nf_nat_helper: tidy up adjust_tcp_sequence
From: Patrick McHardy @ 2009-11-05 14:53 UTC (permalink / raw)
  To: Hannes Eder; +Cc: netdev, netfilter-devel
In-Reply-To: <20090922155911.20008.96214.stgit@jazzy.zrh.corp.google.com>

Hannes Eder wrote:
> The variable 'other_way' gets initialized but is not read afterwards,
> so remove it.  Pass the right arguments to a pr_debug call.
> 
> While being at tidy up a bit and it fix this checkpatch warning:
>   WARNING: suspect code indent for conditional statements
> 
> Signed-off-by: Hannes Eder <heder@google.com>
> 

Applied with some minor changes (use enum ip_conntrack_dir instead
of int, use function name literally instead of "%s()" with __func__).

^ permalink raw reply

* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Andi Kleen @ 2009-11-05 14:54 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Andi Kleen, Octavian Purdila, Lucian Adrian Grijincu, netdev
In-Reply-To: <4AF2CCD9.7010507@gmail.com>

> I assume cache is cold or even on other cpu (worst case), dealing with
> 100.000+ sockets or so...

Other CPU cache hit is actually typically significantly 
faster than a DRAM access (unless you're talking about a very large NUMA 
system and a remote CPU far away)
> 
> If workload fits in one CPU cache/registers, we dont mind taking one
> or two cache lines per object, obviously.

It's more like part of your workload needs to fit.

For example if you use a tree and the higher levels fit into
the cache, having a few levels in the tree is (approximately) free.

That's why I'm not always fond of large hash tables. They pretty
much guarantee a lot of cache misses under high load, because
they have little locality.

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply

* Re: [PATCH] e1000: the power down when running ifdown command
From: Naohiro Ooiwa @ 2009-11-05 14:58 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: jeffrey.t.kirsher, jesse.brandeburg, peter.p.waskiewicz.jr,
	john.ronciak, davem, Andrew Morton, netdev, svaidy, e1000-devel
In-Reply-To: <20091104080846.5bf4d225@nehalam>

Stephen Hemminger wrote:
> On Wed, 04 Nov 2009 19:23:43 +0900
> Naohiro Ooiwa <nooiwa@miraclelinux.com> wrote:
> 
>> Naohiro Ooiwa wrote:
>>> Stephen Hemminger wrote:
>>>> On Sat, 31 Oct 2009 18:39:52 +0900
>>>> Naohiro Ooiwa <nooiwa@miraclelinux.com> wrote:
>>>>
>>>> Does this work with Wake On Lan? 
>>> Yes, it works WOL.
>> Sorry, I made a mistake.
>> The WOL doesn't work when my patch applied to kernel.
>> I wasn't myself.
>>
>> I consider the WOL and I will resent the patch.
>> Thank you for your point.
>>
>>
>> thanks,
>> Naohiro Ooiwa
> 
> 
> Good, thank you for checking. I like the idea of powering down the
> PHY. Some of the drivers have shutdown hooks to power PHY back on
> during shutdown to enable WOL.
> 

Thank you so much for your infomation.
Oh, The shutdown hooks is useful.


Thanks.
Naohiro Ooiwa

^ permalink raw reply

* Re: [net-next-2.6 PATCH RFC] TCPCT part 1d: generate Responder Cookie
From: Paul E. McKenney @ 2009-11-05 14:59 UTC (permalink / raw)
  To: William Allen Simpson
  Cc: Eric Dumazet, Linux Kernel Developers,
	Linux Kernel Network Developers
In-Reply-To: <4AF2C266.1010603@gmail.com>

On Thu, Nov 05, 2009 at 07:17:42AM -0500, William Allen Simpson wrote:
> Paul E. McKenney wrote:
>> On Tue, Nov 03, 2009 at 05:38:10PM -0500, William Allen Simpson wrote:
>>> Documentation/RCU/checklist.txt #7 says:
>>>
>>>   One exception to this rule: rcu_read_lock() and rcu_read_unlock()
>>>   may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
>>>   in cases where local bottom halves are already known to be
>>>   disabled, for example, in irq or softirq context.  Commenting
>>>   such cases is a must, of course!  And the jury is still out on
>>>   whether the increased speed is worth it.
>> I strongly suggest using the matching primitives unless you have a
>> really strong reason not to.
> Eric gave contrary advice.  But he also suggested (in an earlier message)
> clearing the secrets with a timer, which could be a separate context --
> although much later in time.
>
> As you suggest, I'll use the _bh suffix everywhere until every i is dotted
> and t is crossed.  Then, check for efficiency later after thorough
> analysis by experts such as yourself.
>
> This code will be hit on every SYN and SYNACK that has a cookie option.
> But it's just prior to a CPU intensive sha_transform -- in comparison,
> it's trivial.

Had Eric said that this code were performance-critical, where every
nanosecond mattered, that would certainly be good enough for me.
Eric has excellent knowledge of the networking code, certainly much
better than mine.  And 10Gb Ethernet is certainly a performance
challenge, and I don't expect 40Gb Ethernet to be any easier.

Of course, I would still argue that the use of rcu_read_lock() rather
than rcu_read_unlock() needs to be commented.  And if this sort of
substitution happens a lot, maybe we need a way for it to happen
automatically.

							Thanx, Paul

>>> +			rcu_assign_pointer(tcp_secret_generating,
>>> +					   tcp_secret_secondary);
>>> +			rcu_assign_pointer(tcp_secret_retiring,
>>> +					   tcp_secret_primary);
>>> +			spin_unlock_bh(&tcp_secret_locker);
>>> +			/* call_rcu() or synchronize_rcu() not needed. */
>> Would you be willing to say why?  Are you relying on a time delay for a
>> given item to pass through tcp_secret_secondary and tcp_secret_retiring
>> or some such?  If so, how do you know that this time delay will always
>> be long enough?
>> Or are you just shuffling the data structures around, without ever
>> freeing them?  If so, is it really OK for a given reader to keep a
>> reference to a given item through the full range of shuffling, especially
>> given that it might be accesssing this concurrently with the ->expires
>> assignments above?
>> Either way, could you please expand the comment to give at least some
>> hint to the poor guy reading your code?  ;-)
> Yes.  Just shuffling the pointers without ever freeing anything.  So,
> there's nothing for call_rcu() to do, and nothing else to synchronize
> (only the pointers).  This assumes that after _unlock_ any CPU cache
> with an old pointer->expires will hit the _lock_ code, and that will
> update *both* ->expires and the other array elements concurrently?
>
> One of the advantages of this scheme is the new secret is initialized
> while the old secret is still used, and the old secret can continue to
> be verified as old packets arrive.  (I originally designed this for
> Photuris [RFC-2522] circa 1995.)
>
> As described in the long header given, each array element goes through
> four (4) states.  This is handling the first state transition.  It will
> hit at least 2 more locks, pointer updates, and unlocks before reuse.
>
> Also, a great deal of time passes.  After being retired (and expired), it
> will be unused for approximately 5 minutes.
>
> All that's a bit long for a comment.
>
> +			/*
> +			 * The retiring data is never freed.  Instead, it is
> +			 * replaced after later pointer updates and a quiet
> +			 * time of approximately 5 minutes.  There is nothing
> +			 * for call_rcu() or synchronize_rcu() to handle.
> +			 */
>
> Clear enough?

^ permalink raw reply


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