On Sat, Sep 03, 2022 at 03:39:00AM +0300, Vitaliy Makkoveev wrote:
> Since we are not the special case where we have no resource allocation
> in runtime, because all required resources are pre-allocated by design,

During packet processing we do not wait, but drop the packet.
Network semantics allows packet loss.

> the memory errors are absolutely normal

Yes.  But in system call you wait.  Then userland gets consistent
behavior.  System call must not fail due to temporary memory shortage.
System call fails if it is a persistent failure.  The persistent
failure is caused by bad behavior from the userland, like exceeding
some limit.  Temporary failure can happen anytime.

> and should be handled by userland.

Userland does not retry.  Kernel is buggy and does not do it either.

I have a diff that introduces random malloc failures.  You cannot
boot to multiuser as handling NULL is incomplete.  The kernel should
recover by waiting.  Only if this is not feasable, pass the error
to userland.  Then the userland has to do something smart.

In theory OpenBSD should run with the diff below.  But we would
have to fix a lot of bugs for that.  Currently these are races that
are not triggered.

The design of malloc(9) is that if some userland process needs
memory, but there is not enough in the system, it has to wait.  Some
other part of the kernel or userland will free it eventually.  Then
the request can succeed.

bluhm

Index: kern/kern_malloc.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.148
diff -u -p -r1.148 kern_malloc.c
--- kern/kern_malloc.c  14 Aug 2022 01:58:27 -0000      1.148
+++ kern/kern_malloc.c  3 Sep 2022 13:18:24 -0000
@@ -184,6 +184,15 @@ malloc(size_t size, int type, int flags)
        }
 #endif
 
+       if (!cold && (flags & (M_NOWAIT|M_CANFAIL))) {
+               static int failcount;
+
+               if (failcount == 0) 
+                       failcount = arc4random();
+               if ((failcount++ & 0xfff) == 0)
+                       return (NULL);
+       }
+
        if (size > 65535 * PAGE_SIZE) {
                if (flags & M_CANFAIL) {
 #ifndef SMALL_KERNEL
Index: kern/subr_pool.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/subr_pool.c,v
retrieving revision 1.236
diff -u -p -r1.236 subr_pool.c
--- kern/subr_pool.c    14 Aug 2022 01:58:28 -0000      1.236
+++ kern/subr_pool.c    3 Sep 2022 13:17:33 -0000
@@ -567,6 +567,15 @@ pool_get(struct pool *pp, int flags)
        if (pp->pr_flags & PR_RWLOCK)
                KASSERT(flags & PR_WAITOK);
 
+       if (!cold && (flags & (PR_NOWAIT|PR_LIMITFAIL))) {
+               static int failcount;
+
+               if (failcount == 0)
+                       failcount = arc4random();
+               if ((failcount++ & 0xfff) == 0)
+                       return (NULL);
+       }
+
 #ifdef MULTIPROCESSOR
        if (pp->pr_cache != NULL) {
                v = pool_cache_get(pp);

Reply via email to