slab: trigger allocation failure for failed ctors

We were just returning NULL, which would have MEM_WAIT allocs return
NULL.  It'd usually panic immediately - this way we catch it a little
earlier in a common path.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/src/slab.c b/kern/src/slab.c
index eba20b5..be6b89a 100644
--- a/kern/src/slab.c
+++ b/kern/src/slab.c
@@ -594,21 +594,16 @@
 /* Alloc, bypassing the magazines and depot */
 static void *__kmem_alloc_from_slab(struct kmem_cache *cp, int flags)
 {
-	void *retval = NULL;
+	void *retval;
 
 	spin_lock_irqsave(&cp->cache_lock);
 	// look at partial list
 	struct kmem_slab *a_slab = TAILQ_FIRST(&cp->partial_slab_list);
 	//  if none, go to empty list and get an empty and make it partial
 	if (!a_slab) {
-		// TODO: think about non-sleeping flags
-		if (TAILQ_EMPTY(&cp->empty_slab_list) &&
-			!kmem_cache_grow(cp)) {
+		if (TAILQ_EMPTY(&cp->empty_slab_list) && !kmem_cache_grow(cp)) {
 			spin_unlock_irqsave(&cp->cache_lock);
-			if (flags & MEM_ERROR)
-				error(ENOMEM, ERROR_FIXME);
-			else
-				panic("[German Accent]: OOM for a small slab growth!!!");
+			goto out_oom;
 		}
 		// move to partial list
 		a_slab = TAILQ_FIRST(&cp->empty_slab_list);
@@ -643,10 +638,20 @@
 		if (cp->ctor(retval, cp->priv, flags)) {
 			warn("Ctor %p failed, probably a bug!");
 			__kmem_free_to_slab(cp, retval);
-			return NULL;
+			goto out_oom;
 		}
 	}
 	return retval;
+out_oom:
+	if (flags & MEM_ATOMIC)
+		return NULL;
+	/* Old code didn't set any MEM_ flag.  Typically '0' for MEM_ATOMIC. */
+	if (!(flags & MEM_FLAGS))
+		return NULL;
+	if (flags & MEM_ERROR)
+		error(ENOMEM, ERROR_FIXME);
+	else
+		panic("[German Accent]: OOM for a small slab growth!!!");
 }
 
 void *kmem_cache_alloc(struct kmem_cache *kc, int flags)