]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.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_RDTUN,
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_RDTUN,
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                         mutex_enter(&zs->zst_lock);
342
343                         if (zh->zst_offset != zs->zst_offset + zs->zst_len) {
344                                 mutex_exit(&zs->zst_lock);
345                                 goto top;
346                         }
347                         zs->zst_len += zh->zst_len;
348                         diff = zs->zst_len - zfetch_block_cap;
349                         if (diff > 0) {
350                                 zs->zst_offset += diff;
351                                 zs->zst_len = zs->zst_len > diff ?
352                                     zs->zst_len - diff : 0;
353                         }
354                         zs->zst_direction = ZFETCH_FORWARD;
355
356                         break;
357
358                 /*
359                  * Same as above, but reading backwards through the file.
360                  */
361                 } else if (zh->zst_offset == zs->zst_offset - zh->zst_len) {
362                         /* backwards sequential access */
363
364                         reset = !prefetched && zs->zst_len > 1;
365
366                         mutex_enter(&zs->zst_lock);
367
368                         if (zh->zst_offset != zs->zst_offset - zh->zst_len) {
369                                 mutex_exit(&zs->zst_lock);
370                                 goto top;
371                         }
372
373                         zs->zst_offset = zs->zst_offset > zh->zst_len ?
374                             zs->zst_offset - zh->zst_len : 0;
375                         zs->zst_ph_offset = zs->zst_ph_offset > zh->zst_len ?
376                             zs->zst_ph_offset - zh->zst_len : 0;
377                         zs->zst_len += zh->zst_len;
378
379                         diff = zs->zst_len - zfetch_block_cap;
380                         if (diff > 0) {
381                                 zs->zst_ph_offset = zs->zst_ph_offset > diff ?
382                                     zs->zst_ph_offset - diff : 0;
383                                 zs->zst_len = zs->zst_len > diff ?
384                                     zs->zst_len - diff : zs->zst_len;
385                         }
386                         zs->zst_direction = ZFETCH_BACKWARD;
387
388                         break;
389
390                 } else if ((zh->zst_offset - zs->zst_offset - zs->zst_stride <
391                     zs->zst_len) && (zs->zst_len != zs->zst_stride)) {
392                         /* strided forward access */
393
394                         mutex_enter(&zs->zst_lock);
395
396                         if ((zh->zst_offset - zs->zst_offset - zs->zst_stride >=
397                             zs->zst_len) || (zs->zst_len == zs->zst_stride)) {
398                                 mutex_exit(&zs->zst_lock);
399                                 goto top;
400                         }
401
402                         zs->zst_offset += zs->zst_stride;
403                         zs->zst_direction = ZFETCH_FORWARD;
404
405                         break;
406
407                 } else if ((zh->zst_offset - zs->zst_offset + zs->zst_stride <
408                     zs->zst_len) && (zs->zst_len != zs->zst_stride)) {
409                         /* strided reverse access */
410
411                         mutex_enter(&zs->zst_lock);
412
413                         if ((zh->zst_offset - zs->zst_offset + zs->zst_stride >=
414                             zs->zst_len) || (zs->zst_len == zs->zst_stride)) {
415                                 mutex_exit(&zs->zst_lock);
416                                 goto top;
417                         }
418
419                         zs->zst_offset = zs->zst_offset > zs->zst_stride ?
420                             zs->zst_offset - zs->zst_stride : 0;
421                         zs->zst_ph_offset = (zs->zst_ph_offset >
422                             (2 * zs->zst_stride)) ?
423                             (zs->zst_ph_offset - (2 * zs->zst_stride)) : 0;
424                         zs->zst_direction = ZFETCH_BACKWARD;
425
426                         break;
427                 }
428         }
429
430         if (zs) {
431                 if (reset) {
432                         zstream_t *remove = zs;
433
434                         rc = 0;
435                         mutex_exit(&zs->zst_lock);
436                         rw_exit(&zf->zf_rwlock);
437                         rw_enter(&zf->zf_rwlock, RW_WRITER);
438                         /*
439                          * Relocate the stream, in case someone removes
440                          * it while we were acquiring the WRITER lock.
441                          */
442                         for (zs = list_head(&zf->zf_stream); zs;
443                             zs = list_next(&zf->zf_stream, zs)) {
444                                 if (zs == remove) {
445                                         dmu_zfetch_stream_remove(zf, zs);
446                                         mutex_destroy(&zs->zst_lock);
447                                         kmem_free(zs, sizeof (zstream_t));
448                                         break;
449                                 }
450                         }
451                 } else {
452                         rc = 1;
453                         dmu_zfetch_dofetch(zf, zs);
454                         mutex_exit(&zs->zst_lock);
455                 }
456         }
457 out:
458         rw_exit(&zf->zf_rwlock);
459         return (rc);
460 }
461
462 /*
463  * Clean-up state associated with a zfetch structure.  This frees allocated
464  * structure members, empties the zf_stream tree, and generally makes things
465  * nice.  This doesn't free the zfetch_t itself, that's left to the caller.
466  */
467 void
468 dmu_zfetch_rele(zfetch_t *zf)
469 {
470         zstream_t       *zs;
471         zstream_t       *zs_next;
472
473         ASSERT(!RW_LOCK_HELD(&zf->zf_rwlock));
474
475         for (zs = list_head(&zf->zf_stream); zs; zs = zs_next) {
476                 zs_next = list_next(&zf->zf_stream, zs);
477
478                 list_remove(&zf->zf_stream, zs);
479                 mutex_destroy(&zs->zst_lock);
480                 kmem_free(zs, sizeof (zstream_t));
481         }
482         list_destroy(&zf->zf_stream);
483         rw_destroy(&zf->zf_rwlock);
484
485         zf->zf_dnode = NULL;
486 }
487
488 /*
489  * Given a zfetch and zstream structure, insert the zstream structure into the
490  * AVL tree contained within the zfetch structure.  Peform the appropriate
491  * book-keeping.  It is possible that another thread has inserted a stream which
492  * matches one that we are about to insert, so we must be sure to check for this
493  * case.  If one is found, return failure, and let the caller cleanup the
494  * duplicates.
495  */
496 static int
497 dmu_zfetch_stream_insert(zfetch_t *zf, zstream_t *zs)
498 {
499         zstream_t       *zs_walk;
500         zstream_t       *zs_next;
501
502         ASSERT(RW_WRITE_HELD(&zf->zf_rwlock));
503
504         for (zs_walk = list_head(&zf->zf_stream); zs_walk; zs_walk = zs_next) {
505                 zs_next = list_next(&zf->zf_stream, zs_walk);
506
507                 if (dmu_zfetch_streams_equal(zs_walk, zs)) {
508                     return (0);
509                 }
510         }
511
512         list_insert_head(&zf->zf_stream, zs);
513         zf->zf_stream_cnt++;
514
515         return (1);
516 }
517
518
519 /*
520  * Walk the list of zstreams in the given zfetch, find an old one (by time), and
521  * reclaim it for use by the caller.
522  */
523 static zstream_t *
524 dmu_zfetch_stream_reclaim(zfetch_t *zf)
525 {
526         zstream_t       *zs;
527
528         if (! rw_tryenter(&zf->zf_rwlock, RW_WRITER))
529                 return (0);
530
531         for (zs = list_head(&zf->zf_stream); zs;
532             zs = list_next(&zf->zf_stream, zs)) {
533
534                 if (((LBOLT - zs->zst_last) / hz) > zfetch_min_sec_reap)
535                         break;
536         }
537
538         if (zs) {
539                 dmu_zfetch_stream_remove(zf, zs);
540                 mutex_destroy(&zs->zst_lock);
541                 bzero(zs, sizeof (zstream_t));
542         } else {
543                 zf->zf_alloc_fail++;
544         }
545         rw_exit(&zf->zf_rwlock);
546
547         return (zs);
548 }
549
550 /*
551  * Given a zfetch and zstream structure, remove the zstream structure from its
552  * container in the zfetch structure.  Perform the appropriate book-keeping.
553  */
554 static void
555 dmu_zfetch_stream_remove(zfetch_t *zf, zstream_t *zs)
556 {
557         ASSERT(RW_WRITE_HELD(&zf->zf_rwlock));
558
559         list_remove(&zf->zf_stream, zs);
560         zf->zf_stream_cnt--;
561 }
562
563 static int
564 dmu_zfetch_streams_equal(zstream_t *zs1, zstream_t *zs2)
565 {
566         if (zs1->zst_offset != zs2->zst_offset)
567                 return (0);
568
569         if (zs1->zst_len != zs2->zst_len)
570                 return (0);
571
572         if (zs1->zst_stride != zs2->zst_stride)
573                 return (0);
574
575         if (zs1->zst_ph_offset != zs2->zst_ph_offset)
576                 return (0);
577
578         if (zs1->zst_cap != zs2->zst_cap)
579                 return (0);
580
581         if (zs1->zst_direction != zs2->zst_direction)
582                 return (0);
583
584         return (1);
585 }
586
587 /*
588  * This is the prefetch entry point.  It calls all of the other dmu_zfetch
589  * routines to create, delete, find, or operate upon prefetch streams.
590  */
591 void
592 dmu_zfetch(zfetch_t *zf, uint64_t offset, uint64_t size, int prefetched)
593 {
594         zstream_t       zst;
595         zstream_t       *newstream;
596         int             fetched;
597         int             inserted;
598         unsigned int    blkshft;
599         uint64_t        blksz;
600
601         if (zfs_prefetch_disable)
602                 return;
603
604         /* files that aren't ln2 blocksz are only one block -- nothing to do */
605         if (!zf->zf_dnode->dn_datablkshift)
606                 return;
607
608         /* convert offset and size, into blockid and nblocks */
609         blkshft = zf->zf_dnode->dn_datablkshift;
610         blksz = (1 << blkshft);
611
612         bzero(&zst, sizeof (zstream_t));
613         zst.zst_offset = offset >> blkshft;
614         zst.zst_len = (P2ROUNDUP(offset + size, blksz) -
615             P2ALIGN(offset, blksz)) >> blkshft;
616
617         fetched = dmu_zfetch_find(zf, &zst, prefetched);
618         if (!fetched) {
619                 fetched = dmu_zfetch_colinear(zf, &zst);
620         }
621
622         if (!fetched) {
623                 newstream = dmu_zfetch_stream_reclaim(zf);
624
625                 /*
626                  * we still couldn't find a stream, drop the lock, and allocate
627                  * one if possible.  Otherwise, give up and go home.
628                  */
629                 if (newstream == NULL) {
630                         uint64_t        maxblocks;
631                         uint32_t        max_streams;
632                         uint32_t        cur_streams;
633
634                         cur_streams = zf->zf_stream_cnt;
635                         maxblocks = zf->zf_dnode->dn_maxblkid;
636
637                         max_streams = MIN(zfetch_max_streams,
638                             (maxblocks / zfetch_block_cap));
639                         if (max_streams == 0) {
640                                 max_streams++;
641                         }
642
643                         if (cur_streams >= max_streams) {
644                                 return;
645                         }
646
647                         newstream = kmem_zalloc(sizeof (zstream_t), KM_SLEEP);
648                 }
649
650                 newstream->zst_offset = zst.zst_offset;
651                 newstream->zst_len = zst.zst_len;
652                 newstream->zst_stride = zst.zst_len;
653                 newstream->zst_ph_offset = zst.zst_len + zst.zst_offset;
654                 newstream->zst_cap = zst.zst_len;
655                 newstream->zst_direction = ZFETCH_FORWARD;
656                 newstream->zst_last = LBOLT;
657
658                 mutex_init(&newstream->zst_lock, NULL, MUTEX_DEFAULT, NULL);
659
660                 rw_enter(&zf->zf_rwlock, RW_WRITER);
661                 inserted = dmu_zfetch_stream_insert(zf, newstream);
662                 rw_exit(&zf->zf_rwlock);
663
664                 if (!inserted) {
665                         mutex_destroy(&newstream->zst_lock);
666                         kmem_free(newstream, sizeof (zstream_t));
667                 }
668         }
669 }