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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/arc.c
          +++ new/usr/src/uts/common/fs/zfs/arc.c
↓ open down ↓ 2511 lines elided ↑ open up ↑
2512 2512   */
2513 2513  static void
2514 2514  arc_get_data_buf(arc_buf_t *buf)
2515 2515  {
2516 2516          arc_state_t             *state = buf->b_hdr->b_state;
2517 2517          uint64_t                size = buf->b_hdr->b_size;
2518 2518          arc_buf_contents_t      type = buf->b_hdr->b_type;
2519 2519  
2520 2520          arc_adapt(size, state);
2521 2521  
     2522 +top:
2522 2523          /*
2523 2524           * We have not yet reached cache maximum size,
2524 2525           * just allocate a new buffer.
2525 2526           */
2526 2527          if (!arc_evict_needed(type)) {
2527 2528                  if (type == ARC_BUFC_METADATA) {
2528      -                        buf->b_data = zio_buf_alloc(size);
2529      -                        arc_space_consume(size, ARC_SPACE_DATA);
     2529 +                        buf->b_data = zio_buf_alloc_canfail(size);
     2530 +                        if (buf->b_data != NULL) {
     2531 +                                arc_space_consume(size, ARC_SPACE_DATA);
     2532 +                                goto out;
     2533 +                        }
2530 2534                  } else {
2531 2535                          ASSERT(type == ARC_BUFC_DATA);
2532      -                        buf->b_data = zio_data_buf_alloc(size);
2533      -                        ARCSTAT_INCR(arcstat_data_size, size);
2534      -                        atomic_add_64(&arc_size, size);
     2536 +                        buf->b_data = zio_data_buf_alloc_canfail(size);
     2537 +                        if (buf->b_data != NULL) {
     2538 +                                ARCSTAT_INCR(arcstat_data_size, size);
     2539 +                                atomic_add_64(&arc_size, size);
     2540 +                                goto out;
     2541 +                        }
2535 2542                  }
2536      -                goto out;
     2543 +                /*
     2544 +                 * Memory allocation failed probably due to excessive
     2545 +                 * fragmentation, we need to evict regardless.
     2546 +                 */
2537 2547          }
2538 2548  
2539 2549          /*
2540 2550           * If we are prefetching from the mfu ghost list, this buffer
2541 2551           * will end up on the mru list; so steal space from there.
2542 2552           */
2543 2553          if (state == arc_mfu_ghost)
2544 2554                  state = buf->b_hdr->b_flags & ARC_PREFETCH ? arc_mru : arc_mfu;
2545 2555          else if (state == arc_mru_ghost)
2546 2556                  state = arc_mru;
↓ open down ↓ 2 lines elided ↑ open up ↑
2549 2559                  uint64_t mru_used = arc_anon->arcs_size + arc_mru->arcs_size;
2550 2560                  state = (arc_mfu->arcs_lsize[type] >= size &&
2551 2561                      arc_p > mru_used) ? arc_mfu : arc_mru;
2552 2562          } else {
2553 2563                  /* MFU cases */
2554 2564                  uint64_t mfu_space = arc_c - arc_p;
2555 2565                  state =  (arc_mru->arcs_lsize[type] >= size &&
2556 2566                      mfu_space > arc_mfu->arcs_size) ? arc_mru : arc_mfu;
2557 2567          }
2558 2568          if ((buf->b_data = arc_evict(state, NULL, size, TRUE, type)) == NULL) {
2559      -                if (type == ARC_BUFC_METADATA) {
2560      -                        buf->b_data = zio_buf_alloc(size);
2561      -                        arc_space_consume(size, ARC_SPACE_DATA);
2562      -                } else {
2563      -                        ASSERT(type == ARC_BUFC_DATA);
2564      -                        buf->b_data = zio_data_buf_alloc(size);
2565      -                        ARCSTAT_INCR(arcstat_data_size, size);
2566      -                        atomic_add_64(&arc_size, size);
2567      -                }
2568 2569                  ARCSTAT_BUMP(arcstat_recycle_miss);
     2570 +                goto top;
2569 2571          }
2570 2572          ASSERT(buf->b_data != NULL);
2571 2573  out:
2572 2574          /*
2573 2575           * Update the state size.  Note that ghost states have a
2574 2576           * "ghost size" and so don't need to be updated.
2575 2577           */
2576 2578          if (!GHOST_STATE(buf->b_hdr->b_state)) {
2577 2579                  arc_buf_hdr_t *hdr = buf->b_hdr;
2578 2580  
↓ open down ↓ 2645 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX