Re: mbuf starvation

1999-05-17 Thread Pierre Beyssac
On Wed, May 12, 1999 at 10:50:42AM -0700, Archie Cobbs wrote:
> > MCLGET(m, M_WAIT);
> > +   if (m == 0) {
> 
> I think this part of the patch is useless. MCLGET() does not set
> m to NULL when it fails, it simply doesn't set the M_EXT flag.
> ...unless things have changed recently.

No, they apparently haven't. You're absolutely right.
-- 
Pierre Beyssac  p...@enst.fr


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



Re: mbuf starvation

1999-05-17 Thread Pierre Beyssac
On Wed, May 12, 1999 at 01:34:05PM -0700, Matthew Dillon wrote:
> asleep() allows a subroutine deep in the call stack to specify an 
> asynchronous blocking condition and then return a temporary failure 
> up through the ranks.  At the top level, the scheduler sees and acts 
> upon the asynchronous blocking condition.  Higher level routines do not

So if I get it right, this would give something like the code below.
Is that the idea? What's missing in the asleep/await code to use
them in such a way?

soxxx()
{
for (;;) {
await(&mbuf_slp);
/* code */
error = xxx(&mbuf_slp);
if (error != ENOBUFS)
break;
}
}

m_retry()
{
/* find an mbuf... */
if (/* got an mbuf to return */)
return mbuf;
else {
asleep(&mbuf_slp);
return NULL;
}
}

m_free()
{
/* Free mbuf... */
wakeup(&mbuf_slp);
}

And, unless I'm missing something, we still need to properly check
for NULL return values from m_get and friends.
-- 
Pierre Beyssac  p...@enst.fr


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



Re: mbuf starvation

1999-05-12 Thread Matthew Dillon
:I think we need to think a bit more about the right semantics before
:making such a change.  M_WAIT is supposed to mean `I am in process
:context and don't mind sleeping in order to get an mbuf, but there is
:too much locking going on inside the network stack to be able to
:safely sleep without serious risk of deadlock.
:
:This is the sort of application which would be ideal for Matt's
:`asleep' interface.  Then, the code could back its way out of any
:locks and spls, safely wait for sufficient mbufs to be freed, and then
:retry.  Even then, it's still possible to deadlock if one process hogs
:the entire mbuf pool.  It may be necessary to incrementally penalize
:processes which do so.
:
:FWIW, the 4.3 code sleeps in a loop.
:
:-GAWollman

Doing something like this is exactly what was intented for asleep().
The code is not entirely complete, though.  Basically the idea is to
use asleep() in situations where the system might block but does not
normally block in order to avoid both deadlocks and unnecessary code
serialization ( due to holding a lock through a blocking situation ).
This becomes critically important in SMP models where most of the locks
you hold are spinlocks rather then scheduler locks.  

asleep() allows a subroutine deep in the call stack to specify an 
asynchronous blocking condition and then return a temporary failure 
up through the ranks.  At the top level, the scheduler sees and acts 
upon the asynchronous blocking condition.  Higher level routines do not
need to understand what condition is being blocked on, only that there 
is some condition being blocked on.   With the current model, higher
level routines have to assume that lower level routines may block which
complicates matters greatly.

-Matt
Matthew Dillon 


:--
:Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
:woll...@lcs.mit.edu  | O Siem / The fires of freedom 
:Opinions not those of| Dance in the burning flame
:MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick
:
:
:To Unsubscribe: send mail to majord...@freebsd.org
:with "unsubscribe freebsd-current" in the body of the message
:



To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



Re: mbuf starvation

1999-05-12 Thread Archie Cobbs
Pierre Beyssac writes:
>   if (resid >= MINCLSIZE) {
>   MCLGET(m, M_WAIT);
> + if (m == 0) {
> + error = ENOBUFS;
> + goto release;
> + }
>   if ((m->m_flags & M_EXT) == 0)
>   goto nopages;
>   mlen = MCLBYTES;

I think this part of the patch is useless. MCLGET() does not set
m to NULL when it fails, it simply doesn't set the M_EXT flag.
...unless things have changed recently.

-Archie

___
Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



mbuf starvation

1999-05-12 Thread Garrett Wollman
< said:

> Another big problem is that there's a check in m_retry and friends
> that panics when falling short of mbufs! I really believe this does
> more harm than good, because it prevents correct calling code
> (checking for NULL mbuf pointers) from exiting gracefully with
> ENOBUFS...

I think we need to think a bit more about the right semantics before
making such a change.  M_WAIT is supposed to mean `I am in process
context and don't mind sleeping in order to get an mbuf, but there is
too much locking going on inside the network stack to be able to
safely sleep without serious risk of deadlock.

This is the sort of application which would be ideal for Matt's
`asleep' interface.  Then, the code could back its way out of any
locks and spls, safely wait for sufficient mbufs to be freed, and then
retry.  Even then, it's still possible to deadlock if one process hogs
the entire mbuf pool.  It may be necessary to incrementally penalize
processes which do so.

FWIW, the 4.3 code sleeps in a loop.

-GAWollman

--
Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
woll...@lcs.mit.edu  | O Siem / The fires of freedom 
Opinions not those of| Dance in the burning flame
MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



Re: mbuf starvation

1999-05-12 Thread Pierre Beyssac
On Wed, May 12, 1999 at 05:43:27PM +0200, Stefan Bethke wrote:
> I've discussed this with Garett back in September.  The reason is quite
> simple: unless all cases of not checking for a NULL pointer returned are
> fixed (or instrumented with a panic), it is better to fail with a panic
> than with some obscure problem later on.

Yes, I would agree in the general case, but in that particular case
the reasonning is flawed: you panic every time, while there are
many cases that currently are handled gracefully by the caller. In
other words, you don't leave any choice to the caller. That's bad.

IHMO it's not even a good thing in general because mbuf starvations
can and _will_ happen as a normal condition, not because of bugs
but because of high resource use.

It can have its uses for debugging purposes, as a compilation
option.
-- 
Pierre Beyssac  p...@enst.fr


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



Re: mbuf starvation

1999-05-12 Thread Stefan Bethke


Pierre Beyssac  wrote:

> Another big problem is that there's a check in m_retry and friends
> that panics when falling short of mbufs! I really believe this does
> more harm than good, because it prevents correct calling code
> (checking for NULL mbuf pointers) from exiting gracefully with
> ENOBUFS...

I've discussed this with Garett back in September.  The reason is quite
simple: unless all cases of not checking for a NULL pointer returned are
fixed (or instrumented with a panic), it is better to fail with a panic
than with some obscure problem later on.


Stefan

--
Mühlendamm 12   |  Voice +49-40-256848, +49-177-3504009
D-22089 Hamburg |  e-mail: stefan.bet...@hanse.de
Germany |  s...@freebsd.org



To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message



mbuf starvation

1999-05-12 Thread Pierre Beyssac
I'm trying to plug some of the holes not checking for mbuf shortage.

In particular, there are the following unchecked calls to MGET and
friends in /sys/kern/uipc_socket.c:sosend() (see patches below).

Would anyone mind if I commit these? I won't be able to commit
these before next Sunday evening, so if anyone deems these to be
useful, he's welcome to commit before then.

Another big problem is that there's a check in m_retry and friends
that panics when falling short of mbufs! I really believe this does
more harm than good, because it prevents correct calling code
(checking for NULL mbuf pointers) from exiting gracefully with
ENOBUFS...

These could most certainly help with 3.2-RELEASE too. Same problem,
I won't be able to do anything more before Sunday.

--- uipc_socket.c.orig  Wed May  5 16:48:57 1999
+++ uipc_socket.c   Wed May 12 16:55:27 1999
@@ -497,15 +497,27 @@
} else do {
if (top == 0) {
MGETHDR(m, M_WAIT, MT_DATA);
+   if (m == 0) {
+   error = ENOBUFS;
+   goto release;
+   }
mlen = MHLEN;
m->m_pkthdr.len = 0;
m->m_pkthdr.rcvif = (struct ifnet *)0;
} else {
MGET(m, M_WAIT, MT_DATA);
+   if (m == 0) {
+   error = ENOBUFS;
+   goto release;
+   }
mlen = MLEN;
}
if (resid >= MINCLSIZE) {
MCLGET(m, M_WAIT);
+   if (m == 0) {
+   error = ENOBUFS;
+   goto release;
+   }
if ((m->m_flags & M_EXT) == 0)
goto nopages;
mlen = MCLBYTES;
@@ -617,6 +629,8 @@
flags = 0;
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
+   if (m == 0)
+   return (ENOBUFS);
error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
if (error)
goto bad;

--- uipc_mbuf.c.origFri Apr 30 12:33:50 1999
+++ uipc_mbuf.c Wed May 12 17:05:02 1999
@@ -263,10 +263,7 @@
if (m != NULL) {
mbstat.m_wait++;
} else {
-   if (i == M_DONTWAIT)
-   mbstat.m_drops++;
-   else
-   panic("Out of mbuf clusters");
+   mbstat.m_drops++;
}
return (m);
 }
@@ -291,10 +288,7 @@
if (m != NULL) {
mbstat.m_wait++;
} else {
-   if (i == M_DONTWAIT)
-   mbstat.m_drops++;
-   else
-   panic("Out of mbuf clusters");
+   mbstat.m_drops++;
}
return (m);
 }
-- 
Pierre Beyssac  p...@enst.fr


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message