]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
MFC r203504,r204067,r204073,r204101,r204804,r205079,r205080,r205132,r205133,
[FreeBSD/stable/8.git] / sys / cddl / contrib / opensolaris / uts / common / fs / zfs / dmu_zfetch.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #pragma ident   "%Z%%M% %I%     %E% SMI"
27
28 #include <sys/zfs_context.h>
29 #include <sys/dnode.h>
30 #include <sys/dmu_objset.h>
31 #include <sys/dmu_zfetch.h>
32 #include <sys/dmu.h>
33 #include <sys/dbuf.h>
34
35 /*
36  * I'm against tune-ables, but these should probably exist as tweakable globals
37  * until we can get this working the way we want it to.
38  */
39
40 int zfs_prefetch_disable = 0;
41
42 /* max # of streams per zfetch */
43 uint32_t        zfetch_max_streams = 8;
44 /* min time before stream reclaim */
45 uint32_t        zfetch_min_sec_reap = 2;
46 /* max number of blocks to fetch at a time */
47 uint32_t        zfetch_block_cap = 256;
48 /* number of bytes in a array_read at which we stop prefetching (1Mb) */
49 uint64_t        zfetch_array_rd_sz = 1024 * 1024;
50
51 SYSCTL_DECL(_vfs_zfs);
52 SYSCTL_INT(_vfs_zfs, OID_AUTO, prefetch_disable, CTLFLAG_RW,
53     &zfs_prefetch_disable, 0, "Disable prefetch");
54 SYSCTL_NODE(_vfs_zfs, OID_AUTO, zfetch, CTLFLAG_RW, 0, "ZFS ZFETCH");
55 TUNABLE_INT("vfs.zfs.zfetch.max_streams", &zfetch_max_streams);
56 SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_streams, CTLFLAG_RW,
57     &zfetch_max_streams, 0, "Max # of streams per zfetch");
58 TUNABLE_INT("vfs.zfs.zfetch.min_sec_reap", &zfetch_min_sec_reap);
59 SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, min_sec_reap, CTLFLAG_RDTUN,
60     &zfetch_min_sec_reap, 0, "Min time before stream reclaim");
61 TUNABLE_INT("vfs.zfs.zfetch.block_cap", &zfetch_block_cap);
62 SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, block_cap, CTLFLAG_RDTUN,
63     &zfetch_block_cap, 0, "Max number of blocks to fetch at a time");
64 TUNABLE_QUAD("vfs.zfs.zfetch.array_rd_sz", &zfetch_array_rd_sz);
65 SYSCTL_QUAD(_vfs_zfs_zfetch, OID_AUTO, array_rd_sz, CTLFLAG_RDTUN,
66     &zfetch_array_rd_sz, 0,
67     "Number of bytes in a array_read at which we stop prefetching");
68
69 /* forward decls for static routines */
70 static int              dmu_zfetch_colinear(zfetch_t *, zstream_t *);
71 static void             dmu_zfetch_dofetch(zfetch_t *, zstream_t *);
72 static uint64_t         dmu_zfetch_fetch(dnode_t *, uint64_t, uint64_t);
73 static uint64_t         dmu_zfetch_fetchsz(dnode_t *, uint64_t, uint64_t);
74 static int              dmu_zfetch_find(zfetch_t *, zstream_t *, int);
75 static int              dmu_zfetch_stream_insert(zfetch_t *, zstream_t *);
76 static zstream_t        *dmu_zfetch_stream_reclaim(zfetch_t *);
77 static void             dmu_zfetch_stream_remove(zfetch_t *, zstream_t *);
78 static int              dmu_zfetch_streams_equal(zstream_t *, zstream_t *);
79
80 /*
81  * Given a zfetch structure and a zstream structure, determine whether the
82  * blocks to be read are part of a co-linear pair of existing prefetch
83  * streams.  If a set is found, coalesce the streams, removing one, and
84  * configure the prefetch so it looks for a strided access pattern.
85  *
86  * In other words: if we find two sequential access streams that are
87  * the same length and distance N appart, and this read is N from the
88  * last stream, then we are probably in a strided access pattern.  So
89  * combine the two sequential streams into a single strided stream.
90  *
91  * If no co-linear streams are found, return NULL.
92  */
93 static int
94 dmu_zfetch_colinear(zfetch_t *zf, zstream_t *zh)
95 {
96         zstream_t       *z_walk;
97         zstream_t       *z_comp;
98
99         if (! rw_tryenter(&zf->zf_rwlock, RW_WRITER))
100                 return (0);
101
102         if (zh == NULL) {
103                 rw_exit(&zf->zf_rwlock);
104                 return (0);
105         }
106
107         for (z_walk = list_head(&zf->zf_stream); z_walk;
108             z_walk = list_next(&zf->zf_stream, z_walk)) {
109                 for (z_comp = list_next(&zf->zf_stream, z_walk); z_comp;
110                     z_comp = list_next(&zf->zf_stream, z_comp)) {
111                         int64_t         diff;
112
113                         if (z_walk->zst_len != z_walk->zst_stride ||
114                             z_comp->zst_len != z_comp->zst_stride) {
115                                 continue;
116                         }
117
118                         diff = z_comp->zst_offset - z_walk->zst_offset;
119                         if (z_comp->zst_offset + diff == zh->zst_offset) {
120                                 z_walk->zst_offset = zh->zst_offset;
121                                 z_walk->zst_direction = diff < 0 ? -1 : 1;
122                                 z_walk->zst_stride =
123                                     diff * z_walk->zst_direction;
124                                 z_walk->zst_ph_offset =
125                                     zh->zst_offset + z_walk->zst_stride;
126                                 dmu_zfetch_stream_remove(zf, z_comp);
127                                 mutex_destroy(&z_comp->zst_lock);
128                                 kmem_free(z_comp, sizeof (zstream_t));
129
130                                 dmu_zfetch_dofetch(zf, z_walk);
131
132                                 rw_exit(&zf->zf_rwlock);
133                                 return (1);
134                         }
135
136                         diff = z_walk->zst_offset - z_comp->zst_offset;
137                         if (z_walk->zst_offset + diff == zh->zst_offset) {
138                                 z_walk->zst_offset = zh->zst_offset;
139                                 z_walk->zst_direction = diff < 0 ? -1 : 1;
140                                 z_walk->zst_stride =
141                                     diff * z_walk->zst_direction;
142                                 z_walk->zst_ph_offset =
143                                     zh->zst_offset + z_walk->zst_stride;
144                                 dmu_zfetch_stream_remove(zf, z_comp);
145                                 mutex_destroy(&z_comp->zst_lock);
146                                 kmem_free(z_comp, sizeof (zstream_t));
147
148                                 dmu_zfetch_dofetch(zf, z_walk);
149
150                                 rw_exit(&zf->zf_rwlock);
151                                 return (1);
152                         }
153                 }
154         }
155
156         rw_exit(&zf->zf_rwlock);
157         return (0);
158 }
159
160 /*
161  * Given a zstream_t, determine the bounds of the prefetch.  Then call the
162  * routine that actually prefetches the individual blocks.
163  */
164 static void
165 dmu_zfetch_dofetch(zfetch_t *zf, zstream_t *zs)
166 {
167         uint64_t        prefetch_tail;
168         uint64_t        prefetch_limit;
169         uint64_t        prefetch_ofst;
170         uint64_t        prefetch_len;
171         uint64_t        blocks_fetched;
172
173         zs->zst_stride = MAX((int64_t)zs->zst_stride, zs->zst_len);
174         zs->zst_cap = MIN(zfetch_block_cap, 2 * zs->zst_cap);
175
176         prefetch_tail = MAX((int64_t)zs->zst_ph_offset,
177             (int64_t)(zs->zst_offset + zs->zst_stride));
178         /*
179          * XXX: use a faster division method?
180          */
181         prefetch_limit = zs->zst_offset + zs->zst_len +
182             (zs->zst_cap * zs->zst_stride) / zs->zst_len;
183
184         while (prefetch_tail < prefetch_limit) {
185                 prefetch_ofst = zs->zst_offset + zs->zst_direction *
186                     (prefetch_tail - zs->zst_offset);
187
188                 prefetch_len = zs->zst_len;
189
190                 /*
191                  * Don't prefetch beyond the end of the file, if working
192                  * backwards.
193                  */
194                 if ((zs->zst_direction == ZFETCH_BACKWARD) &&
195                     (prefetch_ofst > prefetch_tail)) {
196                         prefetch_len += prefetch_ofst;
197                         prefetch_ofst = 0;
198                 }
199
200                 /* don't prefetch more than we're supposed to */
201                 if (prefetch_len > zs->zst_len)
202                         break;
203
204                 blocks_fetched = dmu_zfetch_fetch(zf->zf_dnode,
205                     prefetch_ofst, zs->zst_len);
206
207                 prefetch_tail += zs->zst_stride;
208                 /* stop if we've run out of stuff to prefetch */
209                 if (blocks_fetched < zs->zst_len)
210                         break;
211         }
212         zs->zst_ph_offset = prefetch_tail;
213         zs->zst_last = LBOLT;
214 }
215
216 /*
217  * This takes a pointer to a zfetch structure and a dnode.  It performs the
218  * necessary setup for the zfetch structure, grokking data from the
219  * associated dnode.
220  */
221 void
222 dmu_zfetch_init(zfetch_t *zf, dnode_t *dno)
223 {
224         if (zf == NULL) {
225                 return;
226         }
227
228         zf->zf_dnode = dno;
229         zf->zf_stream_cnt = 0;
230         zf->zf_alloc_fail = 0;
231
232         list_create(&zf->zf_stream, sizeof (zstream_t),
233             offsetof(zstream_t, zst_node));
234
235         rw_init(&zf->zf_rwlock, NULL, RW_DEFAULT, NULL);
236 }
237
238 /*
239  * This function computes the actual size, in blocks, that can be prefetched,
240  * and fetches it.
241  */
242 static uint64_t
243 dmu_zfetch_fetch(dnode_t *dn, uint64_t blkid, uint64_t nblks)
244 {
245         uint64_t        fetchsz;
246         uint64_t        i;
247
248         fetchsz = dmu_zfetch_fetchsz(dn, blkid, nblks);
249
250         for (i = 0; i < fetchsz; i++) {
251                 dbuf_prefetch(dn, blkid + i);
252         }
253
254         return (fetchsz);
255 }
256
257 /*
258  * this function returns the number of blocks that would be prefetched, based
259  * upon the supplied dnode, blockid, and nblks.  This is used so that we can
260  * update streams in place, and then prefetch with their old value after the
261  * fact.  This way, we can delay the prefetch, but subsequent accesses to the
262  * stream won't result in the same data being prefetched multiple times.
263  */
264 static uint64_t
265 dmu_zfetch_fetchsz(dnode_t *dn, uint64_t blkid, uint64_t nblks)
266 {
267         uint64_t        fetchsz;
268
269         if (blkid > dn->dn_maxblkid) {
270                 return (0);
271         }
272
273         /* compute fetch size */
274         if (blkid + nblks + 1 > dn->dn_maxblkid) {
275                 fetchsz = (dn->dn_maxblkid - blkid) + 1;
276                 ASSERT(blkid + fetchsz - 1 <= dn->dn_maxblkid);
277         } else {
278                 fetchsz = nblks;
279         }
280
281
282         return (fetchsz);
283 }
284
285 /*
286  * given a zfetch and a zsearch structure, see if there is an associated zstream
287  * for this block read.  If so, it starts a prefetch for the stream it
288  * located and returns true, otherwise it returns false
289  */
290 static int
291 dmu_zfetch_find(zfetch_t *zf, zstream_t *zh, int prefetched)
292 {
293         zstream_t       *zs;
294         int64_t         diff;
295         int             reset = !prefetched;
296         int             rc = 0;
297
298         if (zh == NULL)
299                 return (0);
300
301         /*
302          * XXX: This locking strategy is a bit coarse; however, it's impact has
303          * yet to be tested.  If this turns out to be an issue, it can be
304          * modified in a number of different ways.
305          */
306
307         rw_enter(&zf->zf_rwlock, RW_READER);
308 top:
309
310         for (zs = list_head(&zf->zf_stream); zs;
311             zs = list_next(&zf->zf_stream, zs)) {
312
313                 /*
314                  * XXX - should this be an assert?
315                  */
316                 if (zs->zst_len == 0) {
317                         /* bogus stream */
318                         continue;
319                 }
320
321                 /*
322                  * We hit this case when we are in a strided prefetch stream:
323                  * we will read "len" blocks before "striding".
324                  */
325                 if (zh->zst_offset >= zs->zst_offset &&
326                     zh->zst_offset < zs->zst_offset + zs->zst_len) {
327                         /* already fetched */
328                         rc = 1;
329                         goto out;
330                 }
331
332                 /*
333                  * This is the forward sequential read case: we increment
334                  * len by one each time we hit here, so we will enter this
335                  * case on every read.
336                  */
337                 if (zh->zst_offset == zs->zst_offset + zs->zst_len) {
338
339                         reset = !prefetched && zs->zst_len > 1;
340
341                         if (mutex_tryenter(&zs->zst_lock) == 0) {
342                                 rc = 1;
343                                 goto out;
344                         }
345                         if (zh->zst_offset != zs->zst_offset + zs->zst_len) {
346                                 mutex_exit(&zs->zst_lock);
347                                 goto top;
348                         }
349                         zs->zst_len += zh->zst_len;
350                         diff = zs->zst_len - zfetch_block_cap;
351                         if (diff > 0) {
352                                 zs->zst_offset += diff;
353                                 zs->zst_len = zs->zst_len > diff ?
354                                     zs->zst_len - diff : 0;
355                         }
356                         zs->zst_direction = ZFETCH_FORWARD;
357
358                         break;
359
360                 /*
361                  * Same as above, but reading backwards through the file.
362                  */
363                 } else if (zh->zst_offset == zs->zst_offset - zh->zst_len) {
364                         /* backwards sequential access */
365
366                         reset = !prefetched && zs->zst_len > 1;
367
368                         if (mutex_tryenter(&zs->zst_lock) == 0) {
369                                 rc = 1;
370                                 goto out;
371                         }
372                         if (zh->zst_offset != zs->zst_offset - zh->zst_len) {
373                                 mutex_exit(&zs->zst_lock);
374                                 goto top;
375                         }
376
377                         zs->zst_offset = zs->zst_offset > zh->zst_len ?
378                             zs->zst_offset - zh->zst_len : 0;
379                         zs->zst_ph_offset = zs->zst_ph_offset > zh->zst_len ?
380                             zs->zst_ph_offset - zh->zst_len : 0;
381                         zs->zst_len += zh->zst_len;
382
383                         diff = zs->zst_len - zfetch_block_cap;
384                         if (diff > 0) {
385                                 zs->zst_ph_offset = zs->zst_ph_offset > diff ?
386                                     zs->zst_ph_offset - diff : 0;
387                                 zs->zst_len = zs->zst_len > diff ?
388                                     zs->zst_len - diff : zs->zst_len;
389                         }
390                         zs->zst_direction = ZFETCH_BACKWARD;
391
392                         break;
393
394                 } else if ((zh->zst_offset - zs->zst_offset - zs->zst_stride <
395                     zs->zst_len) && (zs->zst_len != zs->zst_stride)) {
396                         /* strided forward access */
397
398                         if (mutex_tryenter(&zs->zst_lock) == 0) {
399                                 rc = 1;
400                                 goto out;
401                         }
402                         if ((zh->zst_offset - zs->zst_offset - zs->zst_stride >=
403                             zs->zst_len) || (zs->zst_len == zs->zst_stride)) {
404                                 mutex_exit(&zs->zst_lock);
405                                 goto top;
406                         }
407
408                         zs->zst_offset += zs->zst_stride;
409                         zs->zst_direction = ZFETCH_FORWARD;
410
411                         break;
412
413                 } else if ((zh->zst_offset - zs->zst_offset + zs->zst_stride <
414                     zs->zst_len) && (zs->zst_len != zs->zst_stride)) {
415                         /* strided reverse access */
416
417                         if (mutex_tryenter(&zs->zst_lock) == 0) {
418                                 rc = 1;
419                                 goto out;
420                         }
421                         if ((zh->zst_offset - zs->zst_offset + zs->zst_stride >=
422                             zs->zst_len) || (zs->zst_len == zs->zst_stride)) {
423                                 mutex_exit(&zs->zst_lock);
424                                 goto top;
425                         }
426
427                         zs->zst_offset = zs->zst_offset > zs->zst_stride ?
428                             zs->zst_offset - zs->zst_stride : 0;
429                         zs->zst_ph_offset = (zs->zst_ph_offset >
430                             (2 * zs->zst_stride)) ?
431                             (zs->zst_ph_offset - (2 * zs->zst_stride)) : 0;
432                         zs->zst_direction = ZFETCH_BACKWARD;
433
434                         break;
435                 }
436         }
437
438         if (zs) {
439                 if (reset) {
440                         zstream_t *remove = zs;
441
442                         rc = 0;
443                         mutex_exit(&zs->zst_lock);
444                         rw_exit(&zf->zf_rwlock);
445                         rw_enter(&zf->zf_rwlock, RW_WRITER);
446                         /*
447                          * Relocate the stream, in case someone removes
448                          * it while we were acquiring the WRITER lock.
449                          */
450                         for (zs = list_head(&zf->zf_stream); zs;
451                             zs = list_next(&zf->zf_stream, zs)) {
452                                 if (zs == remove) {
453                                         dmu_zfetch_stream_remove(zf, zs);
454                                         mutex_destroy(&zs->zst_lock);
455                                         kmem_free(zs, sizeof (zstream_t));
456                                         break;
457                                 }
458                         }
459                 } else {
460                         rc = 1;
461                         dmu_zfetch_dofetch(zf, zs);
462                         mutex_exit(&zs->zst_lock);
463                 }
464         }
465 out:
466         rw_exit(&zf->zf_rwlock);
467         return (rc);
468 }
469
470 /*
471  * Clean-up state associated with a zfetch structure.  This frees allocated
472  * structure members, empties the zf_stream tree, and generally makes things
473  * nice.  This doesn't free the zfetch_t itself, that's left to the caller.
474  */
475 void
476 dmu_zfetch_rele(zfetch_t *zf)
477 {
478         zstream_t       *zs;
479         zstream_t       *zs_next;
480
481         ASSERT(!RW_LOCK_HELD(&zf->zf_rwlock));
482
483         for (zs = list_head(&zf->zf_stream); zs; zs = zs_next) {
484                 zs_next = list_next(&zf->zf_stream, zs);
485
486                 list_remove(&zf->zf_stream, zs);
487                 mutex_destroy(&zs->zst_lock);
488                 kmem_free(zs, sizeof (zstream_t));
489         }
490         list_destroy(&zf->zf_stream);
491         rw_destroy(&zf->zf_rwlock);
492
493         zf->zf_dnode = NULL;
494 }
495
496 /*
497  * Given a zfetch and zstream structure, insert the zstream structure into the
498  * AVL tree contained within the zfetch structure.  Peform the appropriate
499  * book-keeping.  It is possible that another thread has inserted a stream which
500  * matches one that we are about to insert, so we must be sure to check for this
501  * case.  If one is found, return failure, and let the caller cleanup the
502  * duplicates.
503  */
504 static int
505 dmu_zfetch_stream_insert(zfetch_t *zf, zstream_t *zs)
506 {
507         zstream_t       *zs_walk;
508         zstream_t       *zs_next;
509
510         ASSERT(RW_WRITE_HELD(&zf->zf_rwlock));
511
512         for (zs_walk = list_head(&zf->zf_stream); zs_walk; zs_walk = zs_next) {
513                 zs_next = list_next(&zf->zf_stream, zs_walk);
514
515                 if (dmu_zfetch_streams_equal(zs_walk, zs)) {
516                     return (0);
517                 }
518         }
519
520         list_insert_head(&zf->zf_stream, zs);
521         zf->zf_stream_cnt++;
522
523         return (1);
524 }
525
526
527 /*
528  * Walk the list of zstreams in the given zfetch, find an old one (by time), and
529  * reclaim it for use by the caller.
530  */
531 static zstream_t *
532 dmu_zfetch_stream_reclaim(zfetch_t *zf)
533 {
534         zstream_t       *zs;
535
536         if (! rw_tryenter(&zf->zf_rwlock, RW_WRITER))
537                 return (0);
538
539         for (zs = list_head(&zf->zf_stream); zs;
540             zs = list_next(&zf->zf_stream, zs)) {
541
542                 if (((LBOLT - zs->zst_last) / hz) > zfetch_min_sec_reap)
543                         break;
544         }
545
546         if (zs) {
547                 dmu_zfetch_stream_remove(zf, zs);
548                 mutex_destroy(&zs->zst_lock);
549                 bzero(zs, sizeof (zstream_t));
550         } else {
551                 zf->zf_alloc_fail++;
552         }
553         rw_exit(&zf->zf_rwlock);
554
555         return (zs);
556 }
557
558 /*
559  * Given a zfetch and zstream structure, remove the zstream structure from its
560  * container in the zfetch structure.  Perform the appropriate book-keeping.
561  */
562 static void
563 dmu_zfetch_stream_remove(zfetch_t *zf, zstream_t *zs)
564 {
565         ASSERT(RW_WRITE_HELD(&zf->zf_rwlock));
566
567         list_remove(&zf->zf_stream, zs);
568         zf->zf_stream_cnt--;
569 }
570
571 static int
572 dmu_zfetch_streams_equal(zstream_t *zs1, zstream_t *zs2)
573 {
574         if (zs1->zst_offset != zs2->zst_offset)
575                 return (0);
576
577         if (zs1->zst_len != zs2->zst_len)
578                 return (0);
579
580         if (zs1->zst_stride != zs2->zst_stride)
581                 return (0);
582
583         if (zs1->zst_ph_offset != zs2->zst_ph_offset)
584                 return (0);
585
586         if (zs1->zst_cap != zs2->zst_cap)
587                 return (0);
588
589         if (zs1->zst_direction != zs2->zst_direction)
590                 return (0);
591
592         return (1);
593 }
594
595 /*
596  * This is the prefetch entry point.  It calls all of the other dmu_zfetch
597  * routines to create, delete, find, or operate upon prefetch streams.
598  */
599 void
600 dmu_zfetch(zfetch_t *zf, uint64_t offset, uint64_t size, int prefetched)
601 {
602         zstream_t       zst;
603         zstream_t       *newstream;
604         int             fetched;
605         int             inserted;
606         unsigned int    blkshft;
607         uint64_t        blksz;
608
609         if (zfs_prefetch_disable)
610                 return;
611
612         /* files that aren't ln2 blocksz are only one block -- nothing to do */
613         if (!zf->zf_dnode->dn_datablkshift)
614                 return;
615
616         /* convert offset and size, into blockid and nblocks */
617         blkshft = zf->zf_dnode->dn_datablkshift;
618         blksz = (1 << blkshft);
619
620         bzero(&zst, sizeof (zstream_t));
621         zst.zst_offset = offset >> blkshft;
622         zst.zst_len = (P2ROUNDUP(offset + size, blksz) -
623             P2ALIGN(offset, blksz)) >> blkshft;
624
625         fetched = dmu_zfetch_find(zf, &zst, prefetched);
626         if (!fetched) {
627                 fetched = dmu_zfetch_colinear(zf, &zst);
628         }
629
630         if (!fetched) {
631                 newstream = dmu_zfetch_stream_reclaim(zf);
632
633                 /*
634                  * we still couldn't find a stream, drop the lock, and allocate
635                  * one if possible.  Otherwise, give up and go home.
636                  */
637                 if (newstream == NULL) {
638                         uint64_t        maxblocks;
639                         uint32_t        max_streams;
640                         uint32_t        cur_streams;
641
642                         cur_streams = zf->zf_stream_cnt;
643                         maxblocks = zf->zf_dnode->dn_maxblkid;
644
645                         max_streams = MIN(zfetch_max_streams,
646                             (maxblocks / zfetch_block_cap));
647                         if (max_streams == 0) {
648                                 max_streams++;
649                         }
650
651                         if (cur_streams >= max_streams) {
652                                 return;
653                         }
654
655                         newstream = kmem_zalloc(sizeof (zstream_t), KM_SLEEP);
656                 }
657
658                 newstream->zst_offset = zst.zst_offset;
659                 newstream->zst_len = zst.zst_len;
660                 newstream->zst_stride = zst.zst_len;
661                 newstream->zst_ph_offset = zst.zst_len + zst.zst_offset;
662                 newstream->zst_cap = zst.zst_len;
663                 newstream->zst_direction = ZFETCH_FORWARD;
664                 newstream->zst_last = LBOLT;
665
666                 mutex_init(&newstream->zst_lock, NULL, MUTEX_DEFAULT, NULL);
667
668                 rw_enter(&zf->zf_rwlock, RW_WRITER);
669                 inserted = dmu_zfetch_stream_insert(zf, newstream);
670                 rw_exit(&zf->zf_rwlock);
671
672                 if (!inserted) {
673                         mutex_destroy(&newstream->zst_lock);
674                         kmem_free(newstream, sizeof (zstream_t));
675                 }
676         }
677 }