usr/src/uts/common/fs/zfs/vdev_cache.c
author ahrens
Fri, 10 Mar 2006 16:27:46 -0800
changeset 1596 2e2377ccbf85
parent 1544 938876158511
child 3059 7d69dbccfcbb
permissions -rw-r--r--
6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr 6396359 infinite loop due to dangling dbufs (hang on unmount)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 789
diff changeset
     5
 * Common Development and Distribution License (the "License").
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 789
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
/*
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 789
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
 * Virtual device read-ahead caching.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
 * This file implements a simple LRU read-ahead cache.  When the DMU reads
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
 * a given block, it will often want other, nearby blocks soon thereafter.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 * We take advantage of this by reading a larger disk region and caching
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
 * the result.  In the best case, this can turn 256 back-to-back 512-byte
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
 * reads into a single 128k read followed by 255 cache hits; this reduces
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
 * latency dramatically.  In the worst case, it can turn an isolated 512-byte
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
 * read into a 128k read, which doesn't affect latency all that much but is
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
 * terribly wasteful of bandwidth.  A more intelligent version of the cache
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
 * could keep track of access patterns and not do read-ahead unless it sees
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
 * at least two temporally close I/Os to the same region.  It could also
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
 * take advantage of semantic information about the I/O.  And it could use
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
 * something faster than an AVL tree; that was chosen solely for convenience.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
 * There are five cache operations: allocate, fill, read, write, evict.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
 * (1) Allocate.  This reserves a cache entry for the specified region.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
 *     We separate the allocate and fill operations so that multiple threads
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
 *     don't generate I/O for the same cache miss.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
 * (2) Fill.  When the I/O for a cache miss completes, the fill routine
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
 *     places the data in the previously allocated cache entry.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
 * (3) Read.  Read data from the cache.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
 * (4) Write.  Update cache contents after write completion.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
 * (5) Evict.  When allocating a new entry, we evict the oldest (LRU) entry
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
 *     if the total cache size exceeds vc_size.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
vdev_cache_offset_compare(const void *a1, const void *a2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
	const vdev_cache_entry_t *ve1 = a1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	const vdev_cache_entry_t *ve2 = a2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	if (ve1->ve_offset < ve2->ve_offset)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	if (ve1->ve_offset > ve2->ve_offset)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
		return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
vdev_cache_lastused_compare(const void *a1, const void *a2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	const vdev_cache_entry_t *ve1 = a1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
	const vdev_cache_entry_t *ve2 = a2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
	if (ve1->ve_lastused < ve2->ve_lastused)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	if (ve1->ve_lastused > ve2->ve_lastused)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
		return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
	 * Among equally old entries, sort by offset to ensure uniqueness.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
	return (vdev_cache_offset_compare(a1, a2));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
 * Evict the specified entry from the cache.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
vdev_cache_evict(vdev_cache_t *vc, vdev_cache_entry_t *ve)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
	ASSERT(MUTEX_HELD(&vc->vc_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
	ASSERT(ve->ve_fill_io == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
	ASSERT(ve->ve_data != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
	dprintf("evicting %p, off %llx, LRU %llu, age %lu, hits %u, stale %u\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
	    vc, ve->ve_offset, ve->ve_lastused, lbolt - ve->ve_lastused,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
	    ve->ve_hits, ve->ve_missed_update);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
	avl_remove(&vc->vc_lastused_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
	avl_remove(&vc->vc_offset_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
	zio_buf_free(ve->ve_data, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
	kmem_free(ve, sizeof (vdev_cache_entry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
 * Allocate an entry in the cache.  At the point we don't have the data,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
 * we're just creating a placeholder so that multiple threads don't all
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
 * go off and read the same blocks.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
static vdev_cache_entry_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
vdev_cache_allocate(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
	vdev_cache_t *vc = &zio->io_vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
	uint64_t offset = P2ALIGN(zio->io_offset, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
	vdev_cache_entry_t *ve;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
	ASSERT(MUTEX_HELD(&vc->vc_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
	if (vc->vc_size == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	 * If adding a new entry would exceed the cache size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
	 * evict the oldest entry (LRU).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
	if ((avl_numnodes(&vc->vc_lastused_tree) << vc->vc_bshift) >
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
	    vc->vc_size) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
		ve = avl_first(&vc->vc_lastused_tree);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
		if (ve->ve_fill_io != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
			dprintf("can't evict in %p, still filling\n", vc);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
		ASSERT(ve->ve_hits != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
		vdev_cache_evict(vc, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
	ve = kmem_zalloc(sizeof (vdev_cache_entry_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	ve->ve_offset = offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	ve->ve_lastused = lbolt;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
	ve->ve_data = zio_buf_alloc(vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
	avl_add(&vc->vc_offset_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
	avl_add(&vc->vc_lastused_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	return (ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
vdev_cache_hit(vdev_cache_t *vc, vdev_cache_entry_t *ve, zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
	uint64_t cache_phase = P2PHASE(zio->io_offset, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
	ASSERT(MUTEX_HELD(&vc->vc_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	ASSERT(ve->ve_fill_io == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	if (ve->ve_lastused != lbolt) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
		avl_remove(&vc->vc_lastused_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
		ve->ve_lastused = lbolt;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
		avl_add(&vc->vc_lastused_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	ve->ve_hits++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	bcopy(ve->ve_data + cache_phase, zio->io_data, zio->io_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
 * Fill a previously allocated cache entry with data.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
vdev_cache_fill(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	vdev_t *vd = zio->io_vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
	vdev_cache_t *vc = &vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	vdev_cache_entry_t *ve = zio->io_private;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	zio_t *dio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	ASSERT(zio->io_size == vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	 * Add data to the cache.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	mutex_enter(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
	ASSERT(ve->ve_fill_io == zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	ASSERT(ve->ve_offset == zio->io_offset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
	ASSERT(ve->ve_data == zio->io_data);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
	ve->ve_fill_io = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
	 * Even if this cache line was invalidated by a missed write update,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
	 * any reads that were queued up before the missed update are still
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
	 * valid, so we can satisfy them from this line before we evict it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
	for (dio = zio->io_delegate_list; dio; dio = dio->io_delegate_next)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
		vdev_cache_hit(vc, ve, dio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
	if (zio->io_error || ve->ve_missed_update)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
		vdev_cache_evict(vc, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
	mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	while ((dio = zio->io_delegate_list) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
		zio->io_delegate_list = dio->io_delegate_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
		dio->io_delegate_next = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
		dio->io_error = zio->io_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
		zio_next_stage(dio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
 * Read data from the cache.  Returns 0 on cache hit, errno on a miss.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
vdev_cache_read(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
	vdev_cache_t *vc = &zio->io_vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
	vdev_cache_entry_t *ve, ve_search;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
	uint64_t cache_offset = P2ALIGN(zio->io_offset, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
	uint64_t cache_phase = P2PHASE(zio->io_offset, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
	zio_t *fio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	ASSERT(zio->io_type == ZIO_TYPE_READ);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
	if (zio->io_flags & ZIO_FLAG_DONT_CACHE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
	if (zio->io_size > vc->vc_max)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
		return (EOVERFLOW);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
	 * If the I/O straddles two or more cache blocks, don't cache it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	if (P2CROSS(zio->io_offset, zio->io_offset + zio->io_size - 1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
	    vc->vc_blocksize))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
		return (EXDEV);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
	ASSERT(cache_phase + zio->io_size <= vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
	mutex_enter(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
	ve_search.ve_offset = cache_offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
	ve = avl_find(&vc->vc_offset_tree, &ve_search, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
	if (ve != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
		if (ve->ve_missed_update) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
			mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
			return (ESTALE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
		if ((fio = ve->ve_fill_io) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
			zio->io_delegate_next = fio->io_delegate_list;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
			fio->io_delegate_list = zio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
			zio_vdev_io_bypass(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
			mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
		vdev_cache_hit(vc, ve, zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
		zio_vdev_io_bypass(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
		mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
		zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	ve = vdev_cache_allocate(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
	if (ve == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
		mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
		return (ENOMEM);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	fio = zio_vdev_child_io(zio, NULL, zio->io_vd, cache_offset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	    ve->ve_data, vc->vc_blocksize, ZIO_TYPE_READ,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
	    ZIO_PRIORITY_CACHE_FILL,
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 789
diff changeset
   288
	    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_PROPAGATE |
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 789
diff changeset
   289
	    ZIO_FLAG_DONT_RETRY | ZIO_FLAG_NOBOOKMARK,
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	    vdev_cache_fill, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	ve->ve_fill_io = fio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
	fio->io_delegate_list = zio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
	zio_vdev_io_bypass(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
	mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
	zio_nowait(fio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
 * Update cache contents upon write completion.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
vdev_cache_write(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
	vdev_cache_t *vc = &zio->io_vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
	vdev_cache_entry_t *ve, ve_search;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
	uint64_t io_start = zio->io_offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
	uint64_t io_end = io_start + zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
	uint64_t min_offset = P2ALIGN(io_start, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
	uint64_t max_offset = P2ROUNDUP(io_end, vc->vc_blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
	ASSERT(zio->io_type == ZIO_TYPE_WRITE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	mutex_enter(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
	ve_search.ve_offset = min_offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
	ve = avl_find(&vc->vc_offset_tree, &ve_search, &where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
	if (ve == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
		ve = avl_nearest(&vc->vc_offset_tree, where, AVL_AFTER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
	while (ve != NULL && ve->ve_offset < max_offset) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
		uint64_t start = MAX(ve->ve_offset, io_start);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
		uint64_t end = MIN(ve->ve_offset + vc->vc_blocksize, io_end);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
		if (ve->ve_fill_io != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
			ve->ve_missed_update = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
			bcopy((char *)zio->io_data + start - io_start,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
			    ve->ve_data + start - ve->ve_offset, end - start);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
		ve = AVL_NEXT(&vc->vc_offset_tree, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
	mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
vdev_cache_init(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
	vdev_cache_t *vc = &vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	mutex_init(&vc->vc_lock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
	avl_create(&vc->vc_offset_tree, vdev_cache_offset_compare,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
	    sizeof (vdev_cache_entry_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
	    offsetof(struct vdev_cache_entry, ve_offset_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
	avl_create(&vc->vc_lastused_tree, vdev_cache_lastused_compare,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
	    sizeof (vdev_cache_entry_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
	    offsetof(struct vdev_cache_entry, ve_lastused_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
	vc->vc_blocksize = 1ULL << vc->vc_bshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
vdev_cache_fini(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
	vdev_cache_t *vc = &vd->vdev_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
	vdev_cache_entry_t *ve;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
	mutex_enter(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	while ((ve = avl_first(&vc->vc_offset_tree)) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
		vdev_cache_evict(vc, ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
	mutex_exit(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
	avl_destroy(&vc->vc_offset_tree);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
	avl_destroy(&vc->vc_lastused_tree);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
	mutex_destroy(&vc->vc_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
}