@@ -138,7 +138,7 @@ dmu_zfetch_stream_remove(zfetch_t *zf, zstream_t *zs)
138
138
ASSERT (MUTEX_HELD (& zf -> zf_lock ));
139
139
list_remove (& zf -> zf_stream , zs );
140
140
zf -> zf_numstreams -- ;
141
- if (zfs_refcount_remove (& zs -> zs_blocks , NULL ) == 0 )
141
+ if (zfs_refcount_remove (& zs -> zs_refs , NULL ) == 0 )
142
142
dmu_zfetch_stream_fini (zs );
143
143
}
144
144
@@ -184,7 +184,7 @@ dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
184
184
/*
185
185
* Skip if still active. 1 -- zf_stream reference.
186
186
*/
187
- if (zfs_refcount_count (& zs -> zs_blocks ) != 1 )
187
+ if (zfs_refcount_count (& zs -> zs_refs ) != 1 )
188
188
continue ;
189
189
if (((now - zs -> zs_atime ) / NANOSEC ) >
190
190
zfetch_min_sec_reap )
@@ -217,9 +217,9 @@ dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
217
217
zs -> zs_fetch = zf ;
218
218
zs -> zs_missed = B_FALSE ;
219
219
zfs_refcount_create (& zs -> zs_callers );
220
- zfs_refcount_create (& zs -> zs_blocks );
220
+ zfs_refcount_create (& zs -> zs_refs );
221
221
/* One reference for zf_stream. */
222
- zfs_refcount_add (& zs -> zs_blocks , NULL );
222
+ zfs_refcount_add (& zs -> zs_refs , NULL );
223
223
zf -> zf_numstreams ++ ;
224
224
list_insert_head (& zf -> zf_stream , zs );
225
225
}
@@ -239,14 +239,18 @@ dmu_zfetch_stream_done(void *arg, boolean_t io_issued)
239
239
ZFETCHSTAT_SET (zfetchstat_max_completion_us , delta );
240
240
}
241
241
242
- if (zfs_refcount_remove (& zs -> zs_blocks , NULL ) == 0 )
242
+ if (zfs_refcount_remove (& zs -> zs_refs , NULL ) == 0 )
243
243
dmu_zfetch_stream_fini (zs );
244
244
}
245
245
246
246
/*
247
- * This is the predictive prefetch entry point. It associates dnode access
248
- * specified with blkid and nblks arguments with prefetch stream, predicts
249
- * further accesses based on that stats and initiates speculative prefetch.
247
+ * This is the predictive prefetch entry point. dmu_zfetch_prepare()
248
+ * associates dnode access specified with blkid and nblks arguments with
249
+ * prefetch stream, predicts further accesses based on that stats and returns
250
+ * the stream pointer on success. That pointer must later be passed to
251
+ * dmu_zfetch_run() to initiate the speculative prefetch for the stream and
252
+ * release it. dmu_zfetch() is a wrapper for simple cases when window between
253
+ * prediction and prefetch initiation is not needed.
250
254
* fetch_data argument specifies whether actual data blocks should be fetched:
251
255
* FALSE -- prefetch only indirect blocks for predicted data blocks;
252
256
* TRUE -- prefetch predicted data blocks plus following indirect blocks.
@@ -257,9 +261,9 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
257
261
{
258
262
zstream_t * zs ;
259
263
int64_t pf_start , ipf_start ;
260
- int64_t pf_ahead_blks , max_blks , maxblkid ;
264
+ int64_t pf_ahead_blks , max_blks ;
261
265
int max_dist_blks , pf_nblks , ipf_nblks ;
262
- uint64_t end_of_access_blkid ;
266
+ uint64_t end_of_access_blkid , maxblkid ;
263
267
end_of_access_blkid = blkid + nblks ;
264
268
spa_t * spa = zf -> zf_dnode -> dn_objset -> os_spa ;
265
269
@@ -289,7 +293,8 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
289
293
* A fast path for small files for which no prefetch will
290
294
* happen.
291
295
*/
292
- if ((maxblkid = zf -> zf_dnode -> dn_maxblkid ) < 2 ) {
296
+ maxblkid = zf -> zf_dnode -> dn_maxblkid ;
297
+ if (maxblkid < 2 ) {
293
298
if (!have_lock )
294
299
rw_exit (& zf -> zf_dnode -> dn_struct_rwlock );
295
300
return (NULL );
@@ -319,15 +324,19 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
319
324
if (end_of_access_blkid >= maxblkid ) {
320
325
if (zs != NULL )
321
326
dmu_zfetch_stream_remove (zf , zs );
322
- done :
323
327
mutex_exit (& zf -> zf_lock );
324
328
if (!have_lock )
325
329
rw_exit (& zf -> zf_dnode -> dn_struct_rwlock );
326
330
return (NULL );
327
331
}
328
332
329
- if (nblks == 0 )
330
- goto done ; /* Already prefetched this before. */
333
+ /* Exit if we already prefetched this block before. */
334
+ if (nblks == 0 ) {
335
+ mutex_exit (& zf -> zf_lock );
336
+ if (!have_lock )
337
+ rw_exit (& zf -> zf_dnode -> dn_struct_rwlock );
338
+ return (NULL );
339
+ }
331
340
332
341
if (zs == NULL ) {
333
342
/*
@@ -401,7 +410,7 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
401
410
402
411
zs -> zs_atime = gethrtime ();
403
412
/* Protect the stream from reclamation. 2 -- zf_stream + us. */
404
- if (zfs_refcount_add (& zs -> zs_blocks , NULL ) == 2 )
413
+ if (zfs_refcount_add (& zs -> zs_refs , NULL ) == 2 )
405
414
zs -> zs_start_time = zs -> zs_atime ;
406
415
/* Count concurrent callers. */
407
416
zfs_refcount_add (& zs -> zs_callers , NULL );
@@ -432,7 +441,7 @@ dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock)
432
441
*/
433
442
if (zfs_refcount_remove (& zs -> zs_callers , NULL ) != 0 ) {
434
443
/* Drop reference taken in dmu_zfetch_prepare(). */
435
- if (zfs_refcount_remove (& zs -> zs_blocks , NULL ) == 0 )
444
+ if (zfs_refcount_remove (& zs -> zs_refs , NULL ) == 0 )
436
445
dmu_zfetch_stream_fini (zs );
437
446
return ;
438
447
}
@@ -454,10 +463,10 @@ dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock)
454
463
issued = pf_end - pf_start + ipf_end - ipf_start ;
455
464
if (issued > 1 ) {
456
465
/* More references on top of taken in dmu_zfetch_prepare(). */
457
- zfs_refcount_add_many (& zs -> zs_blocks , issued - 1 , NULL );
466
+ zfs_refcount_add_many (& zs -> zs_refs , issued - 1 , NULL );
458
467
} else if (issued == 0 ) {
459
468
/* Some other thread has done our work, so drop the ref. */
460
- if (zfs_refcount_remove (& zs -> zs_blocks , NULL ) == 0 )
469
+ if (zfs_refcount_remove (& zs -> zs_refs , NULL ) == 0 )
461
470
dmu_zfetch_stream_fini (zs );
462
471
return ;
463
472
}
0 commit comments