* Move the supplied buffer to the indicated state. The hash lock * for the buffer must be held by the caller. */
| 2422 | * for the buffer must be held by the caller. |
| 2423 | */ |
| 2424 | static void |
| 2425 | arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr, |
| 2426 | kmutex_t *hash_lock) |
| 2427 | { |
| 2428 | arc_state_t *old_state; |
| 2429 | int64_t refcnt; |
| 2430 | uint32_t bufcnt; |
| 2431 | boolean_t update_old, update_new; |
| 2432 | arc_buf_contents_t buftype = arc_buf_type(hdr); |
| 2433 | |
| 2434 | /* |
| 2435 | * We almost always have an L1 hdr here, since we call arc_hdr_realloc() |
| 2436 | * in arc_read() when bringing a buffer out of the L2ARC. However, the |
| 2437 | * L1 hdr doesn't always exist when we change state to arc_anon before |
| 2438 | * destroying a header, in which case reallocating to add the L1 hdr is |
| 2439 | * pointless. |
| 2440 | */ |
| 2441 | if (HDR_HAS_L1HDR(hdr)) { |
| 2442 | old_state = hdr->b_l1hdr.b_state; |
| 2443 | refcnt = zfs_refcount_count(&hdr->b_l1hdr.b_refcnt); |
| 2444 | bufcnt = hdr->b_l1hdr.b_bufcnt; |
| 2445 | update_old = (bufcnt > 0 || hdr->b_l1hdr.b_pabd != NULL || |
| 2446 | HDR_HAS_RABD(hdr)); |
| 2447 | } else { |
| 2448 | old_state = arc_l2c_only; |
| 2449 | refcnt = 0; |
| 2450 | bufcnt = 0; |
| 2451 | update_old = B_FALSE; |
| 2452 | } |
| 2453 | update_new = update_old; |
| 2454 | |
| 2455 | ASSERT(MUTEX_HELD(hash_lock)); |
| 2456 | ASSERT3P(new_state, !=, old_state); |
| 2457 | ASSERT(!GHOST_STATE(new_state) || bufcnt == 0); |
| 2458 | ASSERT(old_state != arc_anon || bufcnt <= 1); |
| 2459 | |
| 2460 | /* |
| 2461 | * If this buffer is evictable, transfer it from the |
| 2462 | * old state list to the new state list. |
| 2463 | */ |
| 2464 | if (refcnt == 0) { |
| 2465 | if (old_state != arc_anon && old_state != arc_l2c_only) { |
| 2466 | ASSERT(HDR_HAS_L1HDR(hdr)); |
| 2467 | multilist_remove(old_state->arcs_list[buftype], hdr); |
| 2468 | |
| 2469 | if (GHOST_STATE(old_state)) { |
| 2470 | ASSERT0(bufcnt); |
| 2471 | ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL); |
| 2472 | update_old = B_TRUE; |
| 2473 | } |
| 2474 | arc_evictable_space_decrement(hdr, old_state); |
| 2475 | } |
| 2476 | if (new_state != arc_anon && new_state != arc_l2c_only) { |
| 2477 | /* |
| 2478 | * An L1 header always exists here, since if we're |
| 2479 | * moving to some L1-cached state (i.e. not l2c_only or |
| 2480 | * anonymous), we realloc the header to add an L1hdr |
| 2481 | * beforehand. |
no test coverage detected