* Allocate an entry in the cache. At the point we don't have the data, * we're just creating a placeholder so that multiple threads don't all * go off and read the same blocks. */
| 152 | * go off and read the same blocks. |
| 153 | */ |
| 154 | static vdev_cache_entry_t * |
| 155 | vdev_cache_allocate(zio_t *zio) |
| 156 | { |
| 157 | vdev_cache_t *vc = &zio->io_vd->vdev_cache; |
| 158 | uint64_t offset = P2ALIGN(zio->io_offset, VCBS); |
| 159 | vdev_cache_entry_t *ve; |
| 160 | |
| 161 | ASSERT(MUTEX_HELD(&vc->vc_lock)); |
| 162 | |
| 163 | if (zfs_vdev_cache_size == 0) |
| 164 | return (NULL); |
| 165 | |
| 166 | /* |
| 167 | * If adding a new entry would exceed the cache size, |
| 168 | * evict the oldest entry (LRU). |
| 169 | */ |
| 170 | if ((avl_numnodes(&vc->vc_lastused_tree) << zfs_vdev_cache_bshift) > |
| 171 | zfs_vdev_cache_size) { |
| 172 | ve = avl_first(&vc->vc_lastused_tree); |
| 173 | if (ve->ve_fill_io != NULL) |
| 174 | return (NULL); |
| 175 | ASSERT3U(ve->ve_hits, !=, 0); |
| 176 | vdev_cache_evict(vc, ve); |
| 177 | } |
| 178 | |
| 179 | ve = kmem_zalloc(sizeof (vdev_cache_entry_t), KM_SLEEP); |
| 180 | ve->ve_offset = offset; |
| 181 | ve->ve_lastused = ddi_get_lbolt(); |
| 182 | ve->ve_abd = abd_alloc_for_io(VCBS, B_TRUE); |
| 183 | |
| 184 | avl_add(&vc->vc_offset_tree, ve); |
| 185 | avl_add(&vc->vc_lastused_tree, ve); |
| 186 | |
| 187 | return (ve); |
| 188 | } |
| 189 | |
| 190 | static void |
| 191 | vdev_cache_hit(vdev_cache_t *vc, vdev_cache_entry_t *ve, zio_t *zio) |
no test coverage detected