Print this page
arc_get_data_buf should be more aggressive in eviction when memory is unavailable

@@ -2517,26 +2517,36 @@
         uint64_t                size = buf->b_hdr->b_size;
         arc_buf_contents_t      type = buf->b_hdr->b_type;
 
         arc_adapt(size, state);
 
+top:
         /*
          * We have not yet reached cache maximum size,
          * just allocate a new buffer.
          */
         if (!arc_evict_needed(type)) {
                 if (type == ARC_BUFC_METADATA) {
-                        buf->b_data = zio_buf_alloc(size);
+                        buf->b_data = zio_buf_alloc_canfail(size);
+                        if (buf->b_data != NULL) {
                         arc_space_consume(size, ARC_SPACE_DATA);
+                                goto out;
+                        }
                 } else {
                         ASSERT(type == ARC_BUFC_DATA);
-                        buf->b_data = zio_data_buf_alloc(size);
+                        buf->b_data = zio_data_buf_alloc_canfail(size);
+                        if (buf->b_data != NULL) {
                         ARCSTAT_INCR(arcstat_data_size, size);
                         atomic_add_64(&arc_size, size);
-                }
                 goto out;
         }
+                }
+                /*
+                 * Memory allocation failed probably due to excessive
+                 * fragmentation, we need to evict regardless.
+                 */
+        }
 
         /*
          * If we are prefetching from the mfu ghost list, this buffer
          * will end up on the mru list; so steal space from there.
          */

@@ -2554,20 +2564,12 @@
                 uint64_t mfu_space = arc_c - arc_p;
                 state =  (arc_mru->arcs_lsize[type] >= size &&
                     mfu_space > arc_mfu->arcs_size) ? arc_mru : arc_mfu;
         }
         if ((buf->b_data = arc_evict(state, NULL, size, TRUE, type)) == NULL) {
-                if (type == ARC_BUFC_METADATA) {
-                        buf->b_data = zio_buf_alloc(size);
-                        arc_space_consume(size, ARC_SPACE_DATA);
-                } else {
-                        ASSERT(type == ARC_BUFC_DATA);
-                        buf->b_data = zio_data_buf_alloc(size);
-                        ARCSTAT_INCR(arcstat_data_size, size);
-                        atomic_add_64(&arc_size, size);
-                }
                 ARCSTAT_BUMP(arcstat_recycle_miss);
+                goto top;
         }
         ASSERT(buf->b_data != NULL);
 out:
         /*
          * Update the state size.  Note that ghost states have a