* Issue prefetch reads for the given block on the given level. If the indirect * blocks above that block are not in memory, we will read them in * asynchronously. As a result, this call never blocks waiting for a read to * complete. Note that the prefetch might fail if the dataset is encrypted and * the encryption key is unmapped before the IO completes. */
| 3222 | * the encryption key is unmapped before the IO completes. |
| 3223 | */ |
| 3224 | int |
| 3225 | dbuf_prefetch_impl(dnode_t *dn, int64_t level, uint64_t blkid, |
| 3226 | zio_priority_t prio, arc_flags_t aflags, dbuf_prefetch_fn cb, |
| 3227 | void *arg) |
| 3228 | { |
| 3229 | blkptr_t bp; |
| 3230 | int epbs, nlevels, curlevel; |
| 3231 | uint64_t curblkid; |
| 3232 | |
| 3233 | ASSERT(blkid != DMU_BONUS_BLKID); |
| 3234 | ASSERT(RW_LOCK_HELD(&dn->dn_struct_rwlock)); |
| 3235 | |
| 3236 | if (blkid > dn->dn_maxblkid) |
| 3237 | goto no_issue; |
| 3238 | |
| 3239 | if (level == 0 && dnode_block_freed(dn, blkid)) |
| 3240 | goto no_issue; |
| 3241 | |
| 3242 | /* |
| 3243 | * This dnode hasn't been written to disk yet, so there's nothing to |
| 3244 | * prefetch. |
| 3245 | */ |
| 3246 | nlevels = dn->dn_phys->dn_nlevels; |
| 3247 | if (level >= nlevels || dn->dn_phys->dn_nblkptr == 0) |
| 3248 | goto no_issue; |
| 3249 | |
| 3250 | epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT; |
| 3251 | if (dn->dn_phys->dn_maxblkid < blkid << (epbs * level)) |
| 3252 | goto no_issue; |
| 3253 | |
| 3254 | dmu_buf_impl_t *db = dbuf_find(dn->dn_objset, dn->dn_object, |
| 3255 | level, blkid); |
| 3256 | if (db != NULL) { |
| 3257 | mutex_exit(&db->db_mtx); |
| 3258 | /* |
| 3259 | * This dbuf already exists. It is either CACHED, or |
| 3260 | * (we assume) about to be read or filled. |
| 3261 | */ |
| 3262 | goto no_issue; |
| 3263 | } |
| 3264 | |
| 3265 | /* |
| 3266 | * Find the closest ancestor (indirect block) of the target block |
| 3267 | * that is present in the cache. In this indirect block, we will |
| 3268 | * find the bp that is at curlevel, curblkid. |
| 3269 | */ |
| 3270 | curlevel = level; |
| 3271 | curblkid = blkid; |
| 3272 | while (curlevel < nlevels - 1) { |
| 3273 | int parent_level = curlevel + 1; |
| 3274 | uint64_t parent_blkid = curblkid >> epbs; |
| 3275 | dmu_buf_impl_t *db; |
| 3276 | |
| 3277 | if (dbuf_hold_impl(dn, parent_level, parent_blkid, |
| 3278 | FALSE, TRUE, FTAG, &db) == 0) { |
| 3279 | blkptr_t *bpp = db->db_buf->b_data; |
| 3280 | bp = bpp[P2PHASE(curblkid, 1 << epbs)]; |
| 3281 | dbuf_rele(db, FTAG); |
no test coverage detected