xref: /titanic_52/usr/src/psm/stand/bootblks/zfs/common/zfs.fth (revision 11b942e373071da9f760d7e6208bc79a7bbf7d3c)
1986fd29aSsetje\
2986fd29aSsetje\ CDDL HEADER START
3986fd29aSsetje\
4986fd29aSsetje\ The contents of this file are subject to the terms of the
5986fd29aSsetje\ Common Development and Distribution License (the "License").
6986fd29aSsetje\ You may not use this file except in compliance with the License.
7986fd29aSsetje\
8986fd29aSsetje\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9986fd29aSsetje\ or http://www.opensolaris.org/os/licensing.
10986fd29aSsetje\ See the License for the specific language governing permissions
11986fd29aSsetje\ and limitations under the License.
12986fd29aSsetje\
13986fd29aSsetje\ When distributing Covered Code, include this CDDL HEADER in each
14986fd29aSsetje\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15986fd29aSsetje\ If applicable, add the following below this CDDL HEADER, with the
16986fd29aSsetje\ fields enclosed by brackets "[]" replaced with your own identifying
17986fd29aSsetje\ information: Portions Copyright [yyyy] [name of copyright owner]
18986fd29aSsetje\
19986fd29aSsetje\ CDDL HEADER END
20986fd29aSsetje\
21986fd29aSsetje\
220a586ceaSMark Shellenbaum\ Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23c713350eSJohn Johnson\ Use is subject to license terms.
24c713350eSJohn Johnson\
258a9764c3SToomas Soome\ Copyright 2015 Toomas Soome <tsoome@me.com>
26986fd29aSsetje
27986fd29aSsetje
28986fd29aSsetjepurpose: ZFS file system support package
290a586ceaSMark Shellenbaumcopyright: Copyright 2010 Sun Microsystems, Inc. All Rights Reserved
30986fd29aSsetje
31986fd29aSsetje" /packages" get-package  push-package
32986fd29aSsetje
33986fd29aSsetjenew-device
34986fd29aSsetje   fs-pkg$  device-name  diag-cr?
35986fd29aSsetje
36986fd29aSsetje   0 instance value temp-space
37986fd29aSsetje
38986fd29aSsetje
39986fd29aSsetje   \ 64b ops
40986fd29aSsetje   \ fcode is still 32b on 64b sparc-v9, so
41986fd29aSsetje   \ we need to override some arithmetic ops
42986fd29aSsetje   \ stack ops and logical ops (dup, and, etc) are 64b
43986fd29aSsetje   : xcmp  ( x1 x2 -- -1|0|1 )
44986fd29aSsetje      xlsplit rot xlsplit        ( x2.lo x2.hi x1.lo x1.hi )
45e7cbe64fSgw25295      rot 2dup  u<  if           ( x2.lo x1.lo x1.hi x2.hi )
46986fd29aSsetje         2drop 2drop  -1         ( lt )
47e7cbe64fSgw25295      else  u>  if               ( x2.lo x1.lo )
48986fd29aSsetje         2drop  1                ( gt )
49e7cbe64fSgw25295      else  swap 2dup u<  if     ( x1.lo x2.lo )
50986fd29aSsetje         2drop  -1               ( lt )
51e7cbe64fSgw25295      else  u>  if               (  )
52986fd29aSsetje         1                       ( gt )
53986fd29aSsetje      else                       (  )
54986fd29aSsetje         0                       ( eq )
55986fd29aSsetje      then then then then        ( -1|0|1 )
56986fd29aSsetje   ;
57986fd29aSsetje   : x<   ( x1 x2 -- <? )   xcmp  -1 =  ;
58986fd29aSsetje   : x>   ( x1 x2 -- >? )   xcmp   1 =  ;
59986fd29aSsetje\  : x=   ( x1 x2 -- =? )   xcmp   0=   ;
60986fd29aSsetje   : x<>  ( x1 x2 -- <>? )  xcmp   0<>  ;
61986fd29aSsetje   : x0=  ( x -- 0=? )      xlsplit 0=  swap 0=  and  ;
62986fd29aSsetje
63986fd29aSsetje   /buf-len  instance buffer:  numbuf
64986fd29aSsetje
65986fd29aSsetje   : (xu.)  ( u -- u$ )
66986fd29aSsetje      numbuf /buf-len +  swap         ( adr u )
67986fd29aSsetje      begin
68986fd29aSsetje         d# 10 /mod  swap             ( adr u' rem )
69986fd29aSsetje         ascii 0  +                   ( adr u' c )
70986fd29aSsetje         rot 1-  tuck c!              ( u adr' )
71986fd29aSsetje         swap  dup 0=                 ( adr u done? )
72986fd29aSsetje      until  drop                     ( adr )
73986fd29aSsetje      dup  numbuf -  /buf-len swap -  ( adr len )
74986fd29aSsetje   ;
75986fd29aSsetje
76986fd29aSsetje   \ pool name
77986fd29aSsetje   /buf-len  instance buffer:  bootprop-buf
78986fd29aSsetje   : bootprop$  ( -- prop$ )  bootprop-buf cscount  ;
79986fd29aSsetje
80986fd29aSsetje   \ decompression
81986fd29aSsetje   \
82986fd29aSsetje   \ uts/common/os/compress.c has a definitive theory of operation comment
83986fd29aSsetje   \ on lzjb, but here's the reader's digest version:
84986fd29aSsetje   \
85986fd29aSsetje   \ repeated phrases are replaced by referenced to the original
86986fd29aSsetje   \ e.g.,
87986fd29aSsetje   \ y a d d a _ y a d d a _ y a d d a , _ b l a h _ b l a h _ b l a h
88986fd29aSsetje   \ becomes
89986fd29aSsetje   \ y a d d a _ 6 11 , _ b l a h 5 10
90986fd29aSsetje   \ where 6 11 means memmove(ptr, ptr - 6, 11)
91986fd29aSsetje   \
92986fd29aSsetje   \ data is separated from metadata with embedded copymap entries
93986fd29aSsetje   \ every 8 items  e.g.,
94986fd29aSsetje   \ 0x40 y a d d a _ 6 11 , 0x20 _ b l a h 5 10
95986fd29aSsetje   \ the copymap has a set bit for copy refercences
96986fd29aSsetje   \ and a clear bit for bytes to be copied directly
97986fd29aSsetje   \
98986fd29aSsetje   \ the reference marks are encoded with match-bits and match-min
99986fd29aSsetje   \ e.g.,
100986fd29aSsetje   \ byte[0] = ((mlen - MATCH_MIN) << (NBBY - MATCH_BITS) | (off >> NBBY)
101986fd29aSsetje   \ byte[1] = (uint8_t)off
102986fd29aSsetje   \
103986fd29aSsetje
104986fd29aSsetje   : pow2  ( n -- 2**n )  1 swap lshift  ;
105986fd29aSsetje
106986fd29aSsetje   \ assume MATCH_BITS=6 and MATCH_MIN=3
107986fd29aSsetje   6                       constant mbits
108986fd29aSsetje   3                       constant mmin
109986fd29aSsetje   8 mbits -               constant mshift
110986fd29aSsetje   d# 16 mbits -  pow2 1-  constant mmask
111986fd29aSsetje
112986fd29aSsetje   : decode-src  ( src -- mlen off )
113986fd29aSsetje      dup c@  swap  1+ c@              ( c[0] c[1] )
114986fd29aSsetje      over  mshift rshift  mmin +      ( c[0] c[1] mlen )
115986fd29aSsetje      -rot  swap bwjoin  mmask  and    ( mlen off )
116986fd29aSsetje   ;
117986fd29aSsetje
118986fd29aSsetje   \ equivalent of memmove(dst, dst - off, len)
119986fd29aSsetje   \ src points to a copy reference to be decoded
120986fd29aSsetje   : mcopy  ( dend dst src -- dend dst' )
121986fd29aSsetje      decode-src                         ( dend dst mlen off )
122986fd29aSsetje      2 pick  swap -  >r                 ( dent dst mlen  r: cpy )
123986fd29aSsetje      begin
124986fd29aSsetje         1-  dup 0>=                     ( dend dst mlen' any?  r: cpy )
125986fd29aSsetje         2over >  and                    ( dend dst mlen !done?  r : cpy )
126986fd29aSsetje      while                              ( dend dst mlen  r: cpy )
127986fd29aSsetje         swap  r> dup 1+ >r  c@          ( dend mlen dst c  r: cpy' )
128986fd29aSsetje         over c!  1+  swap               ( dend dst' mlen  r: cpy )
129986fd29aSsetje      repeat                             ( dend dst' mlen  r: cpy )
130986fd29aSsetje      r> 2drop                           ( dend dst )
131986fd29aSsetje   ;
132986fd29aSsetje
133986fd29aSsetje
134986fd29aSsetje   : lzjb ( src dst len -- )
135986fd29aSsetje      over +  swap                  ( src dend dst )
136986fd29aSsetje      rot >r                        ( dend dst  r: src )
137986fd29aSsetje
138986fd29aSsetje      \ setup mask so 1st while iteration fills map
139986fd29aSsetje      0  7 pow2  2swap              ( map mask dend dst  r: src )
140986fd29aSsetje
141986fd29aSsetje      begin  2dup >  while
142986fd29aSsetje         2swap  1 lshift            ( dend dst map mask'  r: src )
143986fd29aSsetje
144986fd29aSsetje         dup  8 pow2  =  if
145986fd29aSsetje            \ fetch next copymap
146986fd29aSsetje            2drop                   ( dend dst  r: src )
147986fd29aSsetje            r> dup 1+ >r  c@  1     ( dend dst map' mask'  r: src' )
148986fd29aSsetje         then                       ( dend dst map mask  r: src' )
149986fd29aSsetje
150986fd29aSsetje         \ if (map & mask) we hit a copy reference
151986fd29aSsetje         \ else just copy 1 byte
152986fd29aSsetje         2swap  2over and  if       ( map mask dend dst  r: src )
153986fd29aSsetje            r> dup 2+ >r            ( map mask dend dst src  r: src' )
154986fd29aSsetje            mcopy                   ( map mask dend dst'  r: src )
155986fd29aSsetje         else
156986fd29aSsetje            r> dup 1+ >r  c@        ( map mask dend dst c  r: src' )
157986fd29aSsetje            over c!  1+             ( map mask dend dst'  r: src )
158986fd29aSsetje         then
159986fd29aSsetje      repeat                        ( map mask dend dst  r: src )
160986fd29aSsetje      2drop 2drop  r> drop          (  )
161986fd29aSsetje   ;
162986fd29aSsetje
1638a9764c3SToomas Soome   \ decode lz4 buffer header, returns src addr and len
1648a9764c3SToomas Soome   : lz4_sbuf ( addr -- s_addr s_len )
1658a9764c3SToomas Soome      dup C@ 8 lshift swap 1+		( byte0 addr++ )
1668a9764c3SToomas Soome      dup C@				( byte0 addr byte1 )
1678a9764c3SToomas Soome      rot				( addr byte1 byte0 )
1688a9764c3SToomas Soome      or d# 16 lshift swap 1+		( d addr++ )
1698a9764c3SToomas Soome
1708a9764c3SToomas Soome      dup C@ 8 lshift			( d addr byte2 )
1718a9764c3SToomas Soome      swap 1+				( d byte2 addr++ )
1728a9764c3SToomas Soome      dup C@ swap 1+			( d byte2 byte3 addr++ )
1738a9764c3SToomas Soome      -rot				( d s_addr byte2 byte3 )
1748a9764c3SToomas Soome      or				( d s_addr d' )
1758a9764c3SToomas Soome      rot				( s_addr d' d )
1768a9764c3SToomas Soome      or				( s_addr s_len )
1778a9764c3SToomas Soome    ;
1788a9764c3SToomas Soome
1798a9764c3SToomas Soome    4           constant STEPSIZE
1808a9764c3SToomas Soome    8           constant COPYLENGTH
1818a9764c3SToomas Soome    5           constant LASTLITERALS
1828a9764c3SToomas Soome    4           constant ML_BITS
1838a9764c3SToomas Soome    d# 15       constant ML_MASK		\ (1<<ML_BITS)-1
1848a9764c3SToomas Soome    4           constant RUN_BITS		\ 8 - ML_BITS
1858a9764c3SToomas Soome    d# 15       constant RUN_MASK		\ (1<<RUN_BITS)-1
1868a9764c3SToomas Soome
1878a9764c3SToomas Soome    \ A32(d) = A32(s); d+=4; s+=4
1888a9764c3SToomas Soome    : lz4_copystep ( dest source -- dest' source')
1898a9764c3SToomas Soome      2dup swap 4 move
1908a9764c3SToomas Soome      swap 4 +
1918a9764c3SToomas Soome      swap 4 +		( dest+4 source+4 )
1928a9764c3SToomas Soome    ;
1938a9764c3SToomas Soome
1948a9764c3SToomas Soome    \ do { LZ4_COPYPACKET(s, d) } while (d < e);
1958a9764c3SToomas Soome    : lz4_copy ( e d s -- e d' s' )
1968a9764c3SToomas Soome      begin			( e d s )
1978a9764c3SToomas Soome        lz4_copystep
1988a9764c3SToomas Soome        lz4_copystep		( e d s )
1998a9764c3SToomas Soome        over			( e d s d )
2008a9764c3SToomas Soome        3 pick < 0=
2018a9764c3SToomas Soome      until
2028a9764c3SToomas Soome    ;
2038a9764c3SToomas Soome
2048a9764c3SToomas Soome    \ lz4 decompress translation from C code
2058a9764c3SToomas Soome    \ could use some factorisation
2068a9764c3SToomas Soome    : lz4 ( src dest len -- )
2078a9764c3SToomas Soome      swap dup >r swap		\ save original dest to return stack.
2088a9764c3SToomas Soome      rot			( dest len src )
2098a9764c3SToomas Soome      lz4_sbuf			( dest len s_buf s_len )
2108a9764c3SToomas Soome      over +			( dest len s_buf s_end )
2118a9764c3SToomas Soome      2swap				( s_buf s_end dest len )
2128a9764c3SToomas Soome      over +			( s_buf s_end dest dest_end )
2138a9764c3SToomas Soome      2swap				( dest dest_end s_buf s_end )
2148a9764c3SToomas Soome
2158a9764c3SToomas Soome      \ main loop
2168a9764c3SToomas Soome      begin 2dup < while
2178a9764c3SToomas Soome         swap dup C@		( dest dest_end s_end s_buf token )
2188a9764c3SToomas Soome         swap CHAR+ swap		( dest dest_end s_end s_buf++ token )
2198a9764c3SToomas Soome         dup ML_BITS rshift	( dest dest_end s_end s_buf token length )
2208a9764c3SToomas Soome         >r rot rot r>		( dest dest_end token s_end s_buf length )
2218a9764c3SToomas Soome         dup RUN_MASK = if
2228a9764c3SToomas Soome           d# 255 begin		( dest dest_end token s_end s_buf length s )
2238a9764c3SToomas Soome             swap		( dest dest_end token s_end s_buf s length )
2248a9764c3SToomas Soome             >r >r			( ... R: length s )
2258a9764c3SToomas Soome             2dup >			( dest dest_end token s_end s_buf flag )
2268a9764c3SToomas Soome             r@ d# 255 = and ( dest dest_end token s_end s_buf flag R: length s )
2278a9764c3SToomas Soome             r> swap r> swap ( dest dest_end token s_end s_buf s length flag )
2288a9764c3SToomas Soome             >r swap r>	 ( dest dest_end token s_end s_buf length s flag )
2298a9764c3SToomas Soome           while
2308a9764c3SToomas Soome             drop >r		( dest dest_end token s_end s_buf R: length )
2318a9764c3SToomas Soome             dup c@ swap CHAR+	( dest dest_end token s_end s s_buf++ )
2328a9764c3SToomas Soome	     swap			( dest dest_end token s_end s_buf s )
2338a9764c3SToomas Soome             dup			( dest dest_end token s_end s_buf s s )
2348a9764c3SToomas Soome             r> + swap		( dest dest_end token s_end s_buf length s )
2358a9764c3SToomas Soome           repeat
2368a9764c3SToomas Soome           drop			( dest dest_end token s_end s_buf length )
2378a9764c3SToomas Soome         then
2388a9764c3SToomas Soome
2398a9764c3SToomas Soome         -rot			( dest dest_end token length s_end s_buf )
2408a9764c3SToomas Soome         swap >r >r		( dest dest_end token length R: s_end s_buf )
2418a9764c3SToomas Soome         swap >r		( dest dest_end length R: s_end s_buf token )
2428a9764c3SToomas Soome         rot			( dest_end length dest )
2438a9764c3SToomas Soome         2dup +			( dest_end length dest cpy )
2448a9764c3SToomas Soome
2458a9764c3SToomas Soome         2dup > if ( dest > cpy )
2468a9764c3SToomas Soome            " lz4 overflow" die
2478a9764c3SToomas Soome         then
2488a9764c3SToomas Soome
2498a9764c3SToomas Soome         3 pick COPYLENGTH - over < ( dest_end length dest cpy flag )
2508a9764c3SToomas Soome         3 pick			( dest_end length dest cpy flag length )
2518a9764c3SToomas Soome         r>			( dest_end length dest cpy flag length token )
2528a9764c3SToomas Soome         r>	( dest_end length dest cpy flag length token s_buf R: s_end )
2538a9764c3SToomas Soome         rot	( dest_end length dest cpy flag token s_buf length )
2548a9764c3SToomas Soome         over +	( dest_end length dest cpy flag token s_buf length+s_buf )
2558a9764c3SToomas Soome         r@ COPYLENGTH - > ( dest_end length dest cpy flag token s_buf flag )
2568a9764c3SToomas Soome         swap >r ( dest_end length dest cpy flag token flag R: s_end s_buf )
2578a9764c3SToomas Soome         swap >r ( dest_end length dest cpy flag flag R: s_end s_buf token )
2588a9764c3SToomas Soome         or if		( dest_end length dest cpy R: s_end s_buf token )
2598a9764c3SToomas Soome
2608a9764c3SToomas Soome           3 pick over swap > if
2618a9764c3SToomas Soome             " lz4 write beyond buffer end" die	( write beyond the dest end )
2628a9764c3SToomas Soome           then			( dest_end length dest cpy )
2638a9764c3SToomas Soome
2648a9764c3SToomas Soome           2 pick			( dest_end length dest cpy length )
2658a9764c3SToomas Soome           r> r> swap	( dest_end length dest cpy length s_buf token R: s_end )
2668a9764c3SToomas Soome           r>		( dest_end length dest cpy length s_buf token s_end )
2678a9764c3SToomas Soome           swap >r >r	( dest_end length dest cpy length s_buf R: token s_end )
2688a9764c3SToomas Soome
2698a9764c3SToomas Soome           swap over +	( dest_end length dest cpy s_buf s_buf+length )
2708a9764c3SToomas Soome           r@ > if	( dest_end length dest cpy s_buf R: token s_end )
2718a9764c3SToomas Soome              " lz4 read beyond source" die	\ read beyond source buffer
2728a9764c3SToomas Soome           then
2738a9764c3SToomas Soome
2748a9764c3SToomas Soome           nip		( dest_end length dest s_buf R: token s_end )
2758a9764c3SToomas Soome           >r		( dest_end length dest R: token s_end s_buf )
2768a9764c3SToomas Soome           over r@		( dest_end length dest length s_buf )
2778a9764c3SToomas Soome           -rot move	( dest_end length )
2788a9764c3SToomas Soome
2798a9764c3SToomas Soome           r> + r> r> drop < if
2808a9764c3SToomas Soome             " lz4 format violation" die		\ LZ4 format violation
2818a9764c3SToomas Soome           then
2828a9764c3SToomas Soome
2838a9764c3SToomas Soome           r> drop		\ drop original dest
2848a9764c3SToomas Soome           drop
2858a9764c3SToomas Soome           exit			\ parsing done
2868a9764c3SToomas Soome         then
2878a9764c3SToomas Soome
2888a9764c3SToomas Soome         swap		( dest_end length cpy dest R: s_end s_buf token )
2898a9764c3SToomas Soome         r> r> swap >r		( dest_end length cpy dest s_buf R: s_end token )
2908a9764c3SToomas Soome
2918a9764c3SToomas Soome         lz4_copy		( dest_end length cpy dest s_buf)
2928a9764c3SToomas Soome
2938a9764c3SToomas Soome         -rot			( dest_end length s_buf cpy dest )
2948a9764c3SToomas Soome         over -			( dest_end length s_buf cpy dest-cpy )
2958a9764c3SToomas Soome         rot			( dest_end length cpy dest-cpy s_buf )
2968a9764c3SToomas Soome         swap -			( dest_end length cpy s_buf )
2978a9764c3SToomas Soome
2988a9764c3SToomas Soome         dup C@ swap		( dest_end length cpy b s_buf )
2998a9764c3SToomas Soome         dup 1+ C@ 8 lshift	( dest_end length cpy b s_buf w )
3008a9764c3SToomas Soome         rot or			( dest_end length cpy s_buf w )
3018a9764c3SToomas Soome         2 pick swap -		( dest_end length cpy s_buf ref )
3028a9764c3SToomas Soome         swap 2 +			( dest_end length cpy ref s_buf+2 )
3038a9764c3SToomas Soome			\ note: cpy is also dest, remember to save it
3048a9764c3SToomas Soome         -rot			( dest_end length s_buf cpy ref )
3058a9764c3SToomas Soome         dup			( dest_end length s_buf cpy ref ref )
3068a9764c3SToomas Soome
3078a9764c3SToomas Soome			\ now we need original dest
3088a9764c3SToomas Soome         r> r> swap r@		( dest_end length s_buf cpy ref ref s_end token dest )
3098a9764c3SToomas Soome         -rot swap >r >r
3108a9764c3SToomas Soome         < if
3118a9764c3SToomas Soome           " lz4 reference outside buffer" die	\ reference outside dest buffer
3128a9764c3SToomas Soome         then			( dest_end length s_buf op ref )
3138a9764c3SToomas Soome
3148a9764c3SToomas Soome         2swap			( dest_end op ref length s_buf )
3158a9764c3SToomas Soome         swap		( dest_end op ref s_buf length R: dest s_end token )
3168a9764c3SToomas Soome
3178a9764c3SToomas Soome         \ get matchlength
3188a9764c3SToomas Soome         drop r> ML_MASK and	( dest_end op ref s_buf length R: dest s_end )
3198a9764c3SToomas Soome         dup ML_MASK = if	( dest_end op ref s_buf length R: dest s_end )
3208a9764c3SToomas Soome           -1		\ flag to top
3218a9764c3SToomas Soome           begin
3228a9764c3SToomas Soome             rot			( dest_end op ref length flag s_buf )
3238a9764c3SToomas Soome	     dup r@ <		( dest_end op ref length flag s_buf flag )
3248a9764c3SToomas Soome             rot and		( dest_end op ref length s_buf flag )
3258a9764c3SToomas Soome           while
3268a9764c3SToomas Soome             dup c@		( dest_end op ref length s_buf s )
3278a9764c3SToomas Soome             swap 1+		( dest_end op ref length s s_buf++ )
3288a9764c3SToomas Soome             -rot		( dest_end op ref s_buf length s )
3298a9764c3SToomas Soome             swap over + swap	( dest_end op ref s_buf length+s s )
3308a9764c3SToomas Soome             d# 255 =
3318a9764c3SToomas Soome           repeat
3328a9764c3SToomas Soome           swap
3338a9764c3SToomas Soome         then			( dest_end op ref s_buf length R: dest s_end )
3348a9764c3SToomas Soome
3358a9764c3SToomas Soome         2swap			( dest_end s_buf length op ref )
3368a9764c3SToomas Soome
3378a9764c3SToomas Soome         \ copy repeated sequence
3388a9764c3SToomas Soome         2dup - STEPSIZE < if	( dest_end s_buf length op ref )
3398a9764c3SToomas Soome           \ 4 times *op++ = *ref++;
3408a9764c3SToomas Soome           dup c@ >r		( dest_end s_buf length op ref R: C )
3418a9764c3SToomas Soome           CHAR+ swap		( dest_end s_buf length ref++ op )
3428a9764c3SToomas Soome           dup r> swap c! CHAR+ swap    ( dest_end s_buf length op ref )
3438a9764c3SToomas Soome           dup c@ >r		( dest_end s_buf length op ref R: C )
3448a9764c3SToomas Soome           CHAR+ swap		( dest_end s_buf length ref++ op )
3458a9764c3SToomas Soome           dup r> swap c! CHAR+ swap    ( dest_end s_buf length op ref )
3468a9764c3SToomas Soome           dup c@ >r		( dest_end s_buf length op ref R: C )
3478a9764c3SToomas Soome           CHAR+ swap		( dest_end s_buf length ref++ op )
3488a9764c3SToomas Soome           dup r> swap c! CHAR+ swap    ( dest_end s_buf length op ref )
3498a9764c3SToomas Soome           dup c@ >r		( dest_end s_buf length op ref R: C )
3508a9764c3SToomas Soome           CHAR+ swap		( dest_end s_buf length ref++ op )
3518a9764c3SToomas Soome           dup r> swap c! CHAR+ swap    ( dest_end s_buf length op ref )
3528a9764c3SToomas Soome           2dup -			( dest_end s_buf length op ref op-ref )
3538a9764c3SToomas Soome           case
3548a9764c3SToomas Soome             1 of 3 endof
3558a9764c3SToomas Soome             2 of 2 endof
3568a9764c3SToomas Soome             3 of 3 endof
3578a9764c3SToomas Soome               0
3588a9764c3SToomas Soome           endcase
3598a9764c3SToomas Soome           -			\ ref -= dec
3608a9764c3SToomas Soome           2dup swap 4 move	( dest_end s_buf length op ref )
3618a9764c3SToomas Soome           swap STEPSIZE 4 - +
3628a9764c3SToomas Soome           swap			( dest_end s_buf length op ref )
3638a9764c3SToomas Soome        else
3648a9764c3SToomas Soome           lz4_copystep		( dest_end s_buf length op ref )
3658a9764c3SToomas Soome        then
3668a9764c3SToomas Soome        -rot			( dest_end s_buf ref length op )
3678a9764c3SToomas Soome        swap over		( dest_end s_buf ref op length op )
3688a9764c3SToomas Soome        + STEPSIZE 4 - -	( dest_end s_buf ref op cpy R: dest s_end )
3698a9764c3SToomas Soome
3708a9764c3SToomas Soome        \ if cpy > oend - COPYLENGTH
3718a9764c3SToomas Soome        4 pick COPYLENGTH -	( dest_end s_buf ref op cpy oend-COPYLENGTH )
3728a9764c3SToomas Soome        2dup > if		( dest_end s_buf ref op cpy oend-COPYLENGTH )
3738a9764c3SToomas Soome          swap			( dest_end s_buf ref op oend-COPYLENGTH cpy )
3748a9764c3SToomas Soome
3758a9764c3SToomas Soome          5 pick over < if
3768a9764c3SToomas Soome            " lz4 write outside buffer" die	\ write outside of dest buffer
3778a9764c3SToomas Soome          then			( dest_end s_buf ref op oend-COPYLENGTH cpy )
3788a9764c3SToomas Soome
3798a9764c3SToomas Soome          >r	( dest_end s_buf ref op oend-COPYLENGTH R: dest s_end cpy )
3808a9764c3SToomas Soome          -rot swap		( dest_end s_buf oend-COPYLENGTH op ref )
3818a9764c3SToomas Soome          lz4_copy		( dest_end s_buf oend-COPYLENGTH op ref )
3828a9764c3SToomas Soome          rot drop swap r>	( dest_end s_buf ref op cpy )
3838a9764c3SToomas Soome          begin
3848a9764c3SToomas Soome            2dup <
3858a9764c3SToomas Soome          while
3868a9764c3SToomas Soome            >r			( dest_end s_buf ref op R: cpy )
3878a9764c3SToomas Soome            over			( dest_end s_buf ref op ref )
3888a9764c3SToomas Soome            c@			( dest_end s_buf ref op C )
3898a9764c3SToomas Soome            over c!		( dest_end s_buf ref op )
3908a9764c3SToomas Soome            >r 1+ r> 1+ r>	( dest_end s_buf ref++ op++ cpy )
3918a9764c3SToomas Soome          repeat
3928a9764c3SToomas Soome
3938a9764c3SToomas Soome          nip			( dest_end s_buf ref op )
3948a9764c3SToomas Soome          dup 4 pick = if
3958a9764c3SToomas Soome            \ op == dest_end  we are done, cleanup
3968a9764c3SToomas Soome            r> r> 2drop 2drop 2drop
3978a9764c3SToomas Soome            exit
3988a9764c3SToomas Soome          then
3998a9764c3SToomas Soome				( dest_end s_buf ref op R: dest s_end )
4008a9764c3SToomas Soome          nip			( dest_end s_buf op )
4018a9764c3SToomas Soome        else
4028a9764c3SToomas Soome          drop			( dest_end s_buf ref op cpy R: dest s_end)
4038a9764c3SToomas Soome          -rot			( dest_end s_buf cpy ref op )
4048a9764c3SToomas Soome          swap			( dest_end s_buf cpy op ref )
4058a9764c3SToomas Soome          lz4_copy
4068a9764c3SToomas Soome          2drop			( dest_end s_buf op )
4078a9764c3SToomas Soome       then
4088a9764c3SToomas Soome
4098a9764c3SToomas Soome       -rot r>			( op dest_end s_buf s_end R: dest )
4108a9764c3SToomas Soome     repeat
4118a9764c3SToomas Soome
4128a9764c3SToomas Soome     r> drop
4138a9764c3SToomas Soome     2drop
4148a9764c3SToomas Soome     2drop
4158a9764c3SToomas Soome   ;
416986fd29aSsetje
417986fd29aSsetje   \
418986fd29aSsetje   \	ZFS block (SPA) routines
419986fd29aSsetje   \
420986fd29aSsetje
421c713350eSJohn Johnson   1           constant  def-comp#
422986fd29aSsetje   2           constant  no-comp#
423c713350eSJohn Johnson   3           constant  lzjb-comp#
4248a9764c3SToomas Soome   d# 15       constant  lz4-comp#
425c713350eSJohn Johnson
426986fd29aSsetje   h# 2.0000   constant  /max-bsize
427986fd29aSsetje   d# 512      constant  /disk-block
428986fd29aSsetje   d# 128      constant  /blkp
429986fd29aSsetje
430c713350eSJohn Johnson   alias  /gang-block  /disk-block
431c713350eSJohn Johnson
432c713350eSJohn Johnson   \ the ending checksum is larger than 1 byte, but that
433c713350eSJohn Johnson   \ doesn't affect the math here
434c713350eSJohn Johnson   /gang-block 1-
435c713350eSJohn Johnson   /blkp  /    constant  #blks/gang
436c713350eSJohn Johnson
437c713350eSJohn Johnson   : blk_offset    ( bp -- n )  h#  8 +  x@  -1 h# 7fff.ffff  lxjoin  and  ;
438986fd29aSsetje   : blk_gang      ( bp -- n )  h#  8 +  x@  xlsplit  nip  d# 31 rshift  ;
439*11b942e3SToomas Soome   : blk_etype     ( bp -- n )  h# 32 +  c@  ;
440*11b942e3SToomas Soome   : blk_comp      ( bp -- n )  h# 33 +  c@  h# 7f and ;
441*11b942e3SToomas Soome   : blk_embedded? ( bp -- flag )  h# 33 +  c@  h# 80 and h# 80 = ;
442986fd29aSsetje   : blk_psize     ( bp -- n )  h# 34 +  w@  ;
443986fd29aSsetje   : blk_lsize     ( bp -- n )  h# 36 +  w@  ;
444986fd29aSsetje   : blk_birth     ( bp -- n )  h# 50 +  x@  ;
445986fd29aSsetje
446*11b942e3SToomas Soome   : blke_psize    ( bp -- n )  h# 34 +  c@  1 rshift h# 7f and 1+ ;
447*11b942e3SToomas Soome   : blke_lsize    ( bp -- n )  h# 34 +  l@  h# 1ff.ffff and 1+ ;
448*11b942e3SToomas Soome
449986fd29aSsetje   0 instance value dev-ih
450986fd29aSsetje   0 instance value blk-space
451986fd29aSsetje   0 instance value gang-space
452986fd29aSsetje
453986fd29aSsetje   : foff>doff  ( fs-off -- disk-off )    /disk-block *  h# 40.0000 +  ;
454986fd29aSsetje   : fsz>dsz    ( fs-size -- disk-size )  1+  /disk-block *  ;
455986fd29aSsetje
456*11b942e3SToomas Soome   : bp-dsize  ( bp -- dsize )
457*11b942e3SToomas Soome      dup blk_embedded? if
458*11b942e3SToomas Soome         blke_psize
459*11b942e3SToomas Soome      else
460*11b942e3SToomas Soome         blk_psize fsz>dsz
461*11b942e3SToomas Soome      then
462*11b942e3SToomas Soome   ;
463*11b942e3SToomas Soome
464*11b942e3SToomas Soome   : bp-lsize  ( bp -- lsize )
465*11b942e3SToomas Soome      dup blk_embedded? if
466*11b942e3SToomas Soome         blke_lsize
467*11b942e3SToomas Soome      else
468*11b942e3SToomas Soome         blk_lsize fsz>dsz
469*11b942e3SToomas Soome      then
470*11b942e3SToomas Soome   ;
471986fd29aSsetje
472c713350eSJohn Johnson   : (read-dva)  ( adr len dva -- )
473986fd29aSsetje      blk_offset foff>doff  dev-ih  read-disk
474986fd29aSsetje   ;
475986fd29aSsetje
476c713350eSJohn Johnson   : gang-read  ( adr len bp gb-adr -- )    tokenizer[ reveal ]tokenizer
477986fd29aSsetje
478986fd29aSsetje      \ read gang block
479c713350eSJohn Johnson      tuck  /gang-block rot  (read-dva)   ( adr len gb-adr )
480986fd29aSsetje
481c713350eSJohn Johnson      \ loop through indirected bp's
482c713350eSJohn Johnson      dup  /blkp #blks/gang *             ( adr len gb-adr bp-list bp-list-len )
483c713350eSJohn Johnson      bounds  do                          ( adr len gb-adr )
484986fd29aSsetje         i blk_offset x0=  ?leave
485c713350eSJohn Johnson
486c713350eSJohn Johnson         \ calc subordinate read len
487c713350eSJohn Johnson         over  i bp-dsize  min            ( adr len gb-adr sub-len )
488c713350eSJohn Johnson         2swap swap                       ( gb-adr sub-len len adr )
489c713350eSJohn Johnson
490c713350eSJohn Johnson         \ nested gang block - recurse with new gang block area
491c713350eSJohn Johnson         i blk_gang  if
492c713350eSJohn Johnson            2swap                         ( len adr gb-adr sub-len )
493c713350eSJohn Johnson            3dup  swap  /gang-block +     ( len adr gb-adr sub-len adr sub-len gb-adr' )
494c713350eSJohn Johnson            i swap  gang-read             ( len adr gb-adr sub-len )
495c713350eSJohn Johnson            2swap                         ( gb-adr sub-len len adr )
496c713350eSJohn Johnson         else
497c713350eSJohn Johnson            3dup  nip  swap               ( gb-adr sub-len len adr adr sub-len )
498c713350eSJohn Johnson            i (read-dva)                  ( gb-adr sub-len len adr )
499c713350eSJohn Johnson         then                             ( gb-adr sub-len len adr )
500c713350eSJohn Johnson
501c713350eSJohn Johnson         \ adjust adr,len and check if done
502c713350eSJohn Johnson         -rot  over -                     ( gb-adr adr sub-len len' )
503c713350eSJohn Johnson         -rot  +  swap                    ( gb-adr adr' len' )
504c713350eSJohn Johnson         dup 0=  ?leave
505c713350eSJohn Johnson         rot                              ( adr' len' gb-adr )
506986fd29aSsetje      /blkp  +loop
507c713350eSJohn Johnson      3drop                               (  )
508c713350eSJohn Johnson   ;
509c713350eSJohn Johnson
510c713350eSJohn Johnson   : read-dva  ( adr len dva -- )
511c713350eSJohn Johnson      dup  blk_gang  if
512c713350eSJohn Johnson         gang-space  gang-read
513c713350eSJohn Johnson      else
514c713350eSJohn Johnson         (read-dva)
515c713350eSJohn Johnson      then
516986fd29aSsetje   ;
517986fd29aSsetje
518*11b942e3SToomas Soome   : read-embedded ( adr len bp -- )
519*11b942e3SToomas Soome      \ loop over buf len, w in comment is octet count
520*11b942e3SToomas Soome      \ note, we dont increment bp, but use index value of w
521*11b942e3SToomas Soome      \ so we can skip the non-payload octets
522*11b942e3SToomas Soome      swap 0 0                              ( adr bp len 0 0 )
523*11b942e3SToomas Soome      rot 0 do                              ( adr bp 0 0 )
524*11b942e3SToomas Soome         I 8 mod 0= if                      ( adr bp w x )
525*11b942e3SToomas Soome            drop                            ( adr bp w )
526*11b942e3SToomas Soome            2dup                            ( adr bp w bp w )
527*11b942e3SToomas Soome            xa+                             ( adr bp w bp+w*8 )
528*11b942e3SToomas Soome            x@ swap                         ( adr bp x w )
529*11b942e3SToomas Soome            1+ dup 6 = if 1+ else           \ skip 6th word
530*11b942e3SToomas Soome               dup h# a = if 1+ then        \ skip 10th word
531*11b942e3SToomas Soome            then                            ( adr bp x w )
532*11b942e3SToomas Soome            swap                            ( adr bp w x )
533*11b942e3SToomas Soome         then
534*11b942e3SToomas Soome         2swap                              ( w x adr bp )
535*11b942e3SToomas Soome         -rot                               ( w bp x adr )
536*11b942e3SToomas Soome         swap dup                           ( w bp adr x x )
537*11b942e3SToomas Soome         I 8 mod 4 < if
538*11b942e3SToomas Soome            xlsplit                         ( w bp adr x x.lo x.hi )
539*11b942e3SToomas Soome            drop                            ( w bp adr x x.lo )
540*11b942e3SToomas Soome         else
541*11b942e3SToomas Soome            xlsplit                         ( w bp adr x x.lo x.hi )
542*11b942e3SToomas Soome            nip                             ( w bp adr x x.hi )
543*11b942e3SToomas Soome         then
544*11b942e3SToomas Soome         I 4 mod 8 * rshift h# ff and       ( w bp adr x c )
545*11b942e3SToomas Soome         rot                                ( w bp x c adr )
546*11b942e3SToomas Soome         swap over                          ( w bp x adr c adr )
547*11b942e3SToomas Soome         I + c!                             ( w bp x adr )
548*11b942e3SToomas Soome
549*11b942e3SToomas Soome         \ now we need to fix the stack for next pass
550*11b942e3SToomas Soome         \ need to get ( adr bp w x )
551*11b942e3SToomas Soome         swap 2swap                         ( adr x w bp )
552*11b942e3SToomas Soome         -rot                               ( adr bp x w )
553*11b942e3SToomas Soome         swap                               ( adr bp w x )
554*11b942e3SToomas Soome      loop
555*11b942e3SToomas Soome      2drop 2drop
556*11b942e3SToomas Soome   ;
557*11b942e3SToomas Soome
558986fd29aSsetje   \ block read that check for holes, gangs, compression, etc
559986fd29aSsetje   : read-bp  ( adr len bp -- )
560986fd29aSsetje      \ sparse block?
5610d21b83cSToomas Soome      dup x@ x0=                         ( addr len bp flag0 )
5620d21b83cSToomas Soome      swap dup 8 + x@ x0=                ( addr len flag0 bp flag1 )
5630d21b83cSToomas Soome      rot                                ( addr len bp flag1 flag0 )
5640d21b83cSToomas Soome      and if
565986fd29aSsetje         drop  erase  exit               (  )
566986fd29aSsetje      then
567c713350eSJohn Johnson
568c713350eSJohn Johnson      \ no compression?
569c713350eSJohn Johnson      dup blk_comp  no-comp#  =  if
570c713350eSJohn Johnson         read-dva  exit                  (  )
571986fd29aSsetje      then
572c713350eSJohn Johnson
573*11b942e3SToomas Soome      \ read into blk-space. read is either from embedded area or disk
574*11b942e3SToomas Soome      dup blk_embedded? if
575*11b942e3SToomas Soome         dup blk-space  over bp-dsize    ( adr len bp bp blk-adr rd-len )
576*11b942e3SToomas Soome         rot  read-embedded              ( adr len bp )
577*11b942e3SToomas Soome      else
578*11b942e3SToomas Soome         dup blk-space  over bp-dsize    ( adr len bp bp blk-adr rd-len )
579*11b942e3SToomas Soome         rot  read-dva                   ( adr len bp )
5808a9764c3SToomas Soome      then
5818a9764c3SToomas Soome
582*11b942e3SToomas Soome      \ set up the stack for decompress
583*11b942e3SToomas Soome      blk_comp >r                        ( adr len R: alg )
584*11b942e3SToomas Soome      blk-space -rot r>                  ( blk-adr adr len alg )
585c713350eSJohn Johnson
586*11b942e3SToomas Soome      case
587*11b942e3SToomas Soome         lzjb-comp#  of lzjb endof
588*11b942e3SToomas Soome         lz4-comp#   of lz4  endof
589*11b942e3SToomas Soome         def-comp#   of lz4  endof       \ isn't this writer only?
590*11b942e3SToomas Soome         dup .h
591*11b942e3SToomas Soome         "  : unknown compression algorithm, only lzjb and lz4 are supported"
592*11b942e3SToomas Soome         die
593*11b942e3SToomas Soome      endcase                             (  )
594986fd29aSsetje   ;
595986fd29aSsetje
596986fd29aSsetje   \
597986fd29aSsetje   \    ZFS vdev routines
598986fd29aSsetje   \
599986fd29aSsetje
600986fd29aSsetje   h# 1.c000  constant /nvpairs
601986fd29aSsetje   h# 4000    constant nvpairs-off
602986fd29aSsetje
603986fd29aSsetje   \
604986fd29aSsetje   \ xdr packed nvlist
605986fd29aSsetje   \
606986fd29aSsetje   \  12B header
607986fd29aSsetje   \  array of xdr packed nvpairs
608986fd29aSsetje   \     4B encoded nvpair size
609986fd29aSsetje   \     4B decoded nvpair size
610986fd29aSsetje   \     4B name string size
611986fd29aSsetje   \     name string
612986fd29aSsetje   \     4B data type
613986fd29aSsetje   \     4B # of data elements
614986fd29aSsetje   \     data
615986fd29aSsetje   \  8B of 0
616986fd29aSsetje   \
617986fd29aSsetje   d# 12      constant /nvhead
618986fd29aSsetje
619986fd29aSsetje   : >nvsize  ( nv -- size )  l@  ;
620986fd29aSsetje   : >nvname  ( nv -- name$ )
621986fd29aSsetje      /l 2* +  dup /l +  swap l@
622986fd29aSsetje   ;
623986fd29aSsetje   : >nvdata  ( nv -- data )
624986fd29aSsetje      >nvname +  /l roundup
625986fd29aSsetje   ;
626e7cbe64fSgw25295
627e7cbe64fSgw25295   \ convert nvdata to 64b int or string
628e7cbe64fSgw25295   : nvdata>x  ( nvdata -- x )
629e7cbe64fSgw25295      /l 2* +                   ( ptr )
630e7cbe64fSgw25295      dup /l + l@  swap l@      ( x.lo x.hi )
631e7cbe64fSgw25295      lxjoin                    ( x )
632e7cbe64fSgw25295   ;
633986fd29aSsetje   alias nvdata>$ >nvname
634986fd29aSsetje
635986fd29aSsetje   : nv-lookup  ( nv name$ -- nvdata false  |  true )
636986fd29aSsetje      rot /nvhead +               ( name$ nvpair )
637986fd29aSsetje      begin  dup >nvsize  while
638986fd29aSsetje         dup >r  >nvname          ( name$ nvname$  r: nvpair )
639986fd29aSsetje         2over $=  if             ( name$  r: nvpair )
640986fd29aSsetje            2drop  r> >nvdata     ( nvdata )
641986fd29aSsetje            false exit            ( nvdata found )
642986fd29aSsetje         then                     ( name$  r: nvpair )
643986fd29aSsetje         r>  dup >nvsize  +       ( name$ nvpair' )
644986fd29aSsetje      repeat
645986fd29aSsetje      3drop  true                 ( not-found )
646986fd29aSsetje   ;
647986fd29aSsetje
648986fd29aSsetje   : scan-vdev  ( -- )
649986fd29aSsetje      temp-space /nvpairs nvpairs-off    ( adr len off )
650986fd29aSsetje      dev-ih  read-disk                  (  )
651e7cbe64fSgw25295      temp-space " txg"  nv-lookup  if
652e7cbe64fSgw25295         " no txg nvpair"  die
653e7cbe64fSgw25295      then  nvdata>x                     ( txg )
654e7cbe64fSgw25295      x0=  if
655e7cbe64fSgw25295         " detached mirror"  die
656e7cbe64fSgw25295      then                               (  )
657986fd29aSsetje      temp-space " name"  nv-lookup  if
658e7cbe64fSgw25295         " no name nvpair"  die
659986fd29aSsetje      then  nvdata>$                     ( pool$ )
660986fd29aSsetje      bootprop-buf swap  move            (  )
661986fd29aSsetje   ;
662986fd29aSsetje
663986fd29aSsetje
664986fd29aSsetje   \
665986fd29aSsetje   \	ZFS ueber-block routines
666986fd29aSsetje   \
667986fd29aSsetje
668986fd29aSsetje   d# 1024                  constant /uber-block
669986fd29aSsetje   d# 128                   constant #ub/label
670986fd29aSsetje   #ub/label /uber-block *  constant /ub-ring
671986fd29aSsetje   h# 2.0000                constant ubring-off
672986fd29aSsetje
673986fd29aSsetje   : ub_magic      ( ub -- n )          x@  ;
674986fd29aSsetje   : ub_txg        ( ub -- n )  h# 10 + x@  ;
675986fd29aSsetje   : ub_timestamp  ( ub -- n )  h# 20 + x@  ;
676986fd29aSsetje   : ub_rootbp     ( ub -- p )  h# 28 +     ;
677986fd29aSsetje
678986fd29aSsetje   0 instance value uber-block
679986fd29aSsetje
680986fd29aSsetje   : ub-cmp  ( ub1 ub2 -- best-ub )
681986fd29aSsetje
682986fd29aSsetje      \ ub1 wins if ub2 isn't valid
683986fd29aSsetje      dup  ub_magic h# 00bab10c  x<>  if
684986fd29aSsetje         drop  exit                  ( ub1 )
685986fd29aSsetje      then
686986fd29aSsetje
687986fd29aSsetje      \ if ub1 is 0, ub2 wins by default
688986fd29aSsetje      over 0=  if  nip  exit  then   ( ub2 )
689986fd29aSsetje
690986fd29aSsetje      \ 2 valid ubs, compare transaction groups
691986fd29aSsetje      over ub_txg  over ub_txg       ( ub1 ub2 txg1 txg2 )
692986fd29aSsetje      2dup x<  if
693986fd29aSsetje         2drop nip  exit             ( ub2 )
694986fd29aSsetje      then                           ( ub1 ub2 txg1 txg2 )
695986fd29aSsetje      x>  if  drop  exit  then       ( ub1 )
696986fd29aSsetje
697986fd29aSsetje      \ same txg, check timestamps
698986fd29aSsetje      over ub_timestamp  over ub_timestamp  x>  if
699986fd29aSsetje         nip                         ( ub2 )
700986fd29aSsetje      else
701986fd29aSsetje         drop                        ( ub1 )
702986fd29aSsetje      then
703986fd29aSsetje   ;
704986fd29aSsetje
705986fd29aSsetje   \ find best uber-block in ring, and copy it to uber-block
706986fd29aSsetje   : get-ub  ( -- )
707986fd29aSsetje      temp-space  /ub-ring ubring-off       ( adr len off )
708986fd29aSsetje      dev-ih  read-disk                     (  )
709986fd29aSsetje      0  temp-space /ub-ring                ( null-ub adr len )
710986fd29aSsetje      bounds  do                            ( ub )
711986fd29aSsetje         i ub-cmp                           ( best-ub )
712986fd29aSsetje      /uber-block +loop
713986fd29aSsetje
714986fd29aSsetje      \ make sure we found a valid ub
715e7cbe64fSgw25295      dup 0=  if  " no ub found" die  then
716986fd29aSsetje
717986fd29aSsetje      uber-block /uber-block  move          (  )
718986fd29aSsetje   ;
719986fd29aSsetje
720986fd29aSsetje
721986fd29aSsetje   \
722986fd29aSsetje   \	ZFS dnode (DMU) routines
723986fd29aSsetje   \
724986fd29aSsetje
7250a586ceaSMark Shellenbaum   d# 44  constant ot-sa#
7260a586ceaSMark Shellenbaum
727986fd29aSsetje   d# 512 constant /dnode
728986fd29aSsetje
729986fd29aSsetje   : dn_indblkshift   ( dn -- n )  h#   1 +  c@  ;
730986fd29aSsetje   : dn_nlevels       ( dn -- n )  h#   2 +  c@  ;
7310a586ceaSMark Shellenbaum   : dn_bonustype     ( dn -- n )  h#   4 +  c@  ;
732986fd29aSsetje   : dn_datablkszsec  ( dn -- n )  h#   8 +  w@  ;
7330a586ceaSMark Shellenbaum   : dn_bonuslen      ( dn -- n )  h#   a +  w@  ;
734986fd29aSsetje   : dn_blkptr        ( dn -- p )  h#  40 +      ;
735986fd29aSsetje   : dn_bonus         ( dn -- p )  h#  c0 +      ;
7360a586ceaSMark Shellenbaum   : dn_spill         ( dn -- p )  h# 180 +      ;
737986fd29aSsetje
738986fd29aSsetje   0 instance value dnode
739986fd29aSsetje
740986fd29aSsetje   \ indirect cache
741986fd29aSsetje   \
742986fd29aSsetje   \ ind-cache is a 1 block indirect block cache from dnode ic-dn
743986fd29aSsetje   \
744986fd29aSsetje   \ ic-bp and ic-bplim point into the ic-dn's block ptr array,
745986fd29aSsetje   \ either in dn_blkptr or in ind-cache   ic-bp is the ic-blk#'th
746986fd29aSsetje   \ block ptr, and ic-bplim is limit of the current bp array
747986fd29aSsetje   \
748986fd29aSsetje   \ the assumption is that reads will be sequential, so we can
749986fd29aSsetje   \ just increment ic-bp
750986fd29aSsetje   \
751986fd29aSsetje   0 instance value  ind-cache
752986fd29aSsetje   0 instance value  ic-dn
753986fd29aSsetje   0 instance value  ic-blk#
754986fd29aSsetje   0 instance value  ic-bp
755986fd29aSsetje   0 instance value  ic-bplim
756986fd29aSsetje
757986fd29aSsetje   : dn-bsize    ( dn -- bsize )    dn_datablkszsec /disk-block  *  ;
758986fd29aSsetje   : dn-indsize  ( dn -- indsize )  dn_indblkshift  pow2  ;
759986fd29aSsetje   : dn-indmask  ( dn -- mask )     dn-indsize 1-  ;
760986fd29aSsetje
761986fd29aSsetje   \ recursively climb the block tree from the leaf to the root
762986fd29aSsetje   : blk@lvl>bp  ( dn blk# lvl -- bp )   tokenizer[ reveal ]tokenizer
763986fd29aSsetje      >r  /blkp *  over dn_nlevels         ( dn bp-off #lvls  r: lvl )
764986fd29aSsetje
765986fd29aSsetje      \ at top, just add dn_blkptr
766986fd29aSsetje      r@  =  if                            ( dn bp-off  r: lvl )
767986fd29aSsetje         swap dn_blkptr  +                 ( bp  r: lvl )
768986fd29aSsetje         r> drop  exit                     ( bp )
769986fd29aSsetje      then                                 ( dn bp-off  r: lvl )
770986fd29aSsetje
771986fd29aSsetje      \ shift bp-off down and find parent indir blk
772986fd29aSsetje      2dup over  dn_indblkshift  rshift    ( dn bp-off dn blk#  r: lvl )
773986fd29aSsetje      r> 1+  blk@lvl>bp                    ( dn bp-off bp )
774986fd29aSsetje
775e7cbe64fSgw25295      \ read parent indir blk and index
776986fd29aSsetje      rot tuck dn-indsize                  ( bp-off dn bp len )
777986fd29aSsetje      ind-cache swap rot  read-bp          ( bp-off dn )
778986fd29aSsetje      dn-indmask  and                      ( bp-off' )
779986fd29aSsetje      ind-cache +                          ( bp )
780986fd29aSsetje   ;
781986fd29aSsetje
782986fd29aSsetje   \ return end of current bp array
783986fd29aSsetje   : bplim ( dn bp -- bp-lim )
784986fd29aSsetje      over dn_nlevels  1  =  if
785986fd29aSsetje          drop dn_blkptr              ( bp0 )
786986fd29aSsetje          3 /blkp *  +                ( bplim )
787986fd29aSsetje      else
788986fd29aSsetje          1+  swap dn-indsize         ( bp+1 indsz )
789986fd29aSsetje          roundup                     ( bplim )
790986fd29aSsetje      then
791986fd29aSsetje   ;
792986fd29aSsetje
793986fd29aSsetje   \ return the lblk#'th block ptr from dnode
794986fd29aSsetje   : lblk#>bp  ( dn blk# -- bp )
795986fd29aSsetje      2dup                               ( dn blk# dn blk# )
796986fd29aSsetje      ic-blk# <>  swap  ic-dn  <>  or    ( dn blk# cache-miss? )
797986fd29aSsetje      ic-bp  ic-bplim  =                 ( dn blk# cache-miss? cache-empty? )
798986fd29aSsetje      or  if                             ( dn blk# )
799986fd29aSsetje         2dup  1 blk@lvl>bp              ( dn blk# bp )
800986fd29aSsetje         dup         to ic-bp            ( dn blk# bp )
801986fd29aSsetje         swap        to ic-blk#          ( dn bp )
802986fd29aSsetje         2dup bplim  to ic-bplim         ( dn bp )
803986fd29aSsetje         over        to ic-dn
804986fd29aSsetje      then  2drop                        (  )
805986fd29aSsetje      ic-blk# 1+          to ic-blk#
806986fd29aSsetje      ic-bp dup  /blkp +  to ic-bp       ( bp )
807986fd29aSsetje   ;
808986fd29aSsetje
809986fd29aSsetje
810986fd29aSsetje   \
811986fd29aSsetje   \	ZFS attribute (ZAP) routines
812986fd29aSsetje   \
813986fd29aSsetje
814986fd29aSsetje   1        constant  fzap#
815986fd29aSsetje   3        constant  uzap#
816986fd29aSsetje
817986fd29aSsetje   d# 64    constant  /uzap
818986fd29aSsetje
819986fd29aSsetje   d# 24    constant  /lf-chunk
820986fd29aSsetje   d# 21    constant  /lf-arr
821986fd29aSsetje   h# ffff  constant  chain-end#
822986fd29aSsetje
823986fd29aSsetje   h# 100   constant /lf-buf
824986fd29aSsetje   /lf-buf  instance buffer: leaf-value
825986fd29aSsetje   /lf-buf  instance buffer: leaf-name
826986fd29aSsetje
827986fd29aSsetje   : +le              ( len off -- n )  +  w@  ;
828986fd29aSsetje   : le_next          ( le -- n )  h# 2 +le  ;
829986fd29aSsetje   : le_name_chunk    ( le -- n )  h# 4 +le  ;
830986fd29aSsetje   : le_name_length   ( le -- n )  h# 6 +le  ;
831986fd29aSsetje   : le_value_chunk   ( le -- n )  h# 8 +le  ;
832986fd29aSsetje   : le_value_length  ( le -- n )  h# a +le  ;
833986fd29aSsetje
834986fd29aSsetje   : la_array  ( la -- adr )  1+  ;
835986fd29aSsetje   : la_next   ( la -- n )    h# 16 +  w@  ;
836986fd29aSsetje
837986fd29aSsetje   0 instance value zap-space
838986fd29aSsetje
839986fd29aSsetje   \ setup leaf hash bounds
840986fd29aSsetje   : >leaf-hash  ( dn lh -- hash-adr /hash )
841986fd29aSsetje      /lf-chunk 2*  +                 ( dn hash-adr )
842986fd29aSsetje      \ size = (bsize / 32) * 2
843986fd29aSsetje      swap dn-bsize  4 rshift         ( hash-adr /hash )
844986fd29aSsetje   ;
845986fd29aSsetje   : >leaf-chunks  ( lf -- ch0 )  >leaf-hash +  ;
846986fd29aSsetje
847986fd29aSsetje   \ convert chunk # to leaf chunk
848986fd29aSsetje   : ch#>lc  ( dn ch# -- lc )
849986fd29aSsetje      /lf-chunk *                     ( dn lc-off )
850986fd29aSsetje      swap zap-space  >leaf-chunks    ( lc-off ch0 )
851986fd29aSsetje      +                               ( lc )
852986fd29aSsetje   ;
853986fd29aSsetje
854986fd29aSsetje   \ assemble chunk chain into single buffer
855986fd29aSsetje   : get-chunk-data  ( dn ch# adr -- )
856986fd29aSsetje      dup >r  /lf-buf  erase          ( dn ch#  r: adr )
857986fd29aSsetje      begin
858986fd29aSsetje         2dup  ch#>lc  nip            ( dn la  r: adr )
859986fd29aSsetje         dup la_array                 ( dn la la-arr  r: adr )
860986fd29aSsetje         r@  /lf-arr  move            ( dn la  r: adr )
861986fd29aSsetje         r>  /lf-arr +  >r            ( dn la  r: adr' )
862986fd29aSsetje         la_next  dup chain-end#  =   ( dn la-ch# end?  r: adr )
863986fd29aSsetje      until  r> 3drop                 (  )
864986fd29aSsetje   ;
865986fd29aSsetje
866986fd29aSsetje   \ get leaf entry's name
867986fd29aSsetje   : entry-name$  ( dn le -- name$ )
868986fd29aSsetje      2dup le_name_chunk              ( dn le dn la-ch# )
869986fd29aSsetje      leaf-name  get-chunk-data       ( dn le )
870b8b2ae86Sjgj      nip  le_name_length 1-          ( len )
871986fd29aSsetje      leaf-name swap                  ( name$ )
872986fd29aSsetje   ;
873986fd29aSsetje
874986fd29aSsetje   \ return entry value as int
875986fd29aSsetje   : entry-int-val  ( dn le -- n )
876986fd29aSsetje      le_value_chunk                  ( dn la-ch# )
877986fd29aSsetje      leaf-value  get-chunk-data      (  )
878986fd29aSsetje      leaf-value x@                   ( n )
879986fd29aSsetje   ;
880986fd29aSsetje
881986fd29aSsetje
882986fd29aSsetje[ifdef] strlookup
883986fd29aSsetje   \ get leaf entry's value as string
884986fd29aSsetje   : entry-val$  ( dn le -- val$ )
885986fd29aSsetje      2dup le_value_chunk             ( dn le dn la-ch# )
886986fd29aSsetje      leaf-value  get-chunk-data      ( dn le )
887986fd29aSsetje      nip le_value_length             ( len )
888986fd29aSsetje      leaf-value swap                 ( name$ )
889986fd29aSsetje   ;
890986fd29aSsetje[then]
891986fd29aSsetje
892986fd29aSsetje   \ apply xt to entry
893986fd29aSsetje   : entry-apply  ( xt dn le -- xt dn false  |  ??? true )
894986fd29aSsetje      over >r                    ( xt dn le  r: dn )
895986fd29aSsetje      rot  dup >r  execute  if   ( ???  r: xt dn )
896986fd29aSsetje         r> r>  2drop  true      ( ??? true )
897986fd29aSsetje      else                       (  )
898986fd29aSsetje         r> r>  false            ( xt dn false )
899986fd29aSsetje      then
900986fd29aSsetje   ;
901986fd29aSsetje
902986fd29aSsetje   \ apply xt to every entry in chain
903986fd29aSsetje   : chain-apply  ( xt dn ch# -- xt dn false  |  ??? true )
904986fd29aSsetje      begin
905986fd29aSsetje         2dup  ch#>lc  nip               ( xt dn le )
906986fd29aSsetje         dup >r  entry-apply  if         ( ???  r: le )
907986fd29aSsetje            r> drop  true  exit          ( ??? found )
908986fd29aSsetje         then                            ( xt dn  r: le )
909986fd29aSsetje         r> le_next                      ( xt dn ch# )
910986fd29aSsetje         dup chain-end#  =               ( xt dn ch# end? )
911986fd29aSsetje      until  drop                        ( xt dn )
912986fd29aSsetje      false                              ( xt dn false )
913986fd29aSsetje   ;
914986fd29aSsetje
915986fd29aSsetje   \ apply xt to every entry in leaf
916986fd29aSsetje   : leaf-apply  ( xt dn blk# -- xt dn false  |  ??? true )
917986fd29aSsetje
918986fd29aSsetje      \ read zap leaf into zap-space
919986fd29aSsetje      2dup lblk#>bp                       ( xt dn blk# bp )
920986fd29aSsetje      nip  over dn-bsize  zap-space       ( xt dn bp len adr )
921986fd29aSsetje      swap rot  read-bp                   ( xt dn )
922986fd29aSsetje
923986fd29aSsetje     \ call chunk-look for every valid chunk list
924986fd29aSsetje      dup zap-space  >leaf-hash           ( xt dn hash-adr /hash )
925986fd29aSsetje      bounds  do                          ( xt dn )
926986fd29aSsetje         i w@  dup chain-end#  <>  if     ( xt dn ch# )
927986fd29aSsetje            chain-apply  if               ( ??? )
928986fd29aSsetje               unloop  true  exit         ( ??? found )
929986fd29aSsetje            then                          ( xt dn )
930986fd29aSsetje         else  drop  then                 ( xt dn )
931986fd29aSsetje      /w  +loop
932986fd29aSsetje      false                               ( xt dn not-found )
933986fd29aSsetje   ;
934986fd29aSsetje
935986fd29aSsetje   \ apply xt to every entry in fzap
936986fd29aSsetje   : fzap-apply  ( xt dn fz -- ??? not-found? )
937986fd29aSsetje
938986fd29aSsetje      \ blk# 1 is always the 1st leaf
939986fd29aSsetje      >r  1 leaf-apply  if              ( ???  r: fz )
940b8b2ae86Sjgj         r> drop  true  exit            ( ??? found )
941986fd29aSsetje      then  r>                          ( xt dn fz )
942986fd29aSsetje
943986fd29aSsetje      \ call leaf-apply on every non-duplicate hash entry
944986fd29aSsetje      \ embedded hash is in 2nd half of fzap block
945986fd29aSsetje      over dn-bsize  tuck +             ( xt dn bsize hash-eadr )
946986fd29aSsetje      swap 2dup  2/  -                  ( xt dn hash-eadr bsize hash-adr )
947986fd29aSsetje      nip  do                           ( xt dn )
948986fd29aSsetje         i x@  dup 1  <>  if            ( xt dn blk# )
949986fd29aSsetje            leaf-apply  if              ( ??? )
950986fd29aSsetje               unloop  true  exit       ( ??? found )
951986fd29aSsetje            then                        ( xt dn )
952986fd29aSsetje         else  drop  then               ( xt dn )
953986fd29aSsetje      /x  +loop
954986fd29aSsetje      2drop  false                      ( not-found )
955986fd29aSsetje   ;
956986fd29aSsetje
957986fd29aSsetje   : mze_value  ( uz -- n )  x@  ;
958986fd29aSsetje   : mze_name   ( uz -- p )  h# e +  ;
959986fd29aSsetje
960986fd29aSsetje   : uzap-name$  ( uz -- name$ )  mze_name  cscount  ;
961986fd29aSsetje
962986fd29aSsetje   \ apply xt to each entry in micro-zap
963986fd29aSsetje   : uzap-apply ( xt uz len -- ??? not-found? )
964986fd29aSsetje      bounds  do                      ( xt )
965986fd29aSsetje         i swap  dup >r               ( uz xt  r: xt )
966986fd29aSsetje         execute  if                  ( ???  r: xt )
967986fd29aSsetje            r> drop                   ( ??? )
968986fd29aSsetje            unloop true  exit         ( ??? found )
969986fd29aSsetje         then  r>                     ( xt )
970986fd29aSsetje      /uzap  +loop
971986fd29aSsetje      drop  false                     ( not-found )
972986fd29aSsetje   ;
973986fd29aSsetje
974986fd29aSsetje   \ match by name
975986fd29aSsetje   : fz-nmlook  ( prop$ dn le -- prop$ false  |  prop$ dn le true )
976986fd29aSsetje      2dup entry-name$        ( prop$ dn le name$ )
977986fd29aSsetje      2rot 2swap              ( dn le prop$ name$ )
978986fd29aSsetje      2over  $=  if           ( dn le prop$ )
979986fd29aSsetje         2swap  true          ( prop$ dn le true )
980986fd29aSsetje      else                    ( dn le prop$ )
981986fd29aSsetje         2swap 2drop  false   ( prop$ false )
982986fd29aSsetje      then                    ( prop$ false  |  prop$ dn le true )
983986fd29aSsetje   ;
984986fd29aSsetje
985986fd29aSsetje   \ match by name
986986fd29aSsetje   : uz-nmlook  ( prop$ uz -- prop$ false  |  prop$ uz true )
987986fd29aSsetje      dup >r  uzap-name$      ( prop$ name$  r: uz )
988986fd29aSsetje      2over  $=  if           ( prop$  r: uz )
989986fd29aSsetje         r>  true             ( prop$ uz true )
990986fd29aSsetje      else                    ( prop$  r: uz )
991986fd29aSsetje         r> drop  false       ( prop$ false )
992986fd29aSsetje      then                    ( prop$ false  |  prop$ uz true )
993986fd29aSsetje   ;
994986fd29aSsetje
995986fd29aSsetje   : zap-type   ( zp -- n )     h#  7 + c@  ;
996986fd29aSsetje   : >uzap-ent  ( adr -- ent )  h# 40 +  ;
997986fd29aSsetje
998986fd29aSsetje   \ read zap block into temp-space
999986fd29aSsetje   : get-zap  ( dn -- zp )
1000986fd29aSsetje      dup  0 lblk#>bp    ( dn bp )
1001986fd29aSsetje      swap dn-bsize      ( bp len )
1002986fd29aSsetje      temp-space swap    ( bp adr len )
1003986fd29aSsetje      rot read-bp        (  )
1004986fd29aSsetje      temp-space         ( zp )
1005986fd29aSsetje   ;
1006986fd29aSsetje
1007986fd29aSsetje   \ find prop in zap dnode
1008986fd29aSsetje   : zap-lookup  ( dn prop$ -- [ n ] not-found? )
1009986fd29aSsetje      rot  dup get-zap                    ( prop$ dn zp )
1010986fd29aSsetje      dup zap-type  case
1011986fd29aSsetje         uzap#  of
1012986fd29aSsetje            >uzap-ent  swap dn-bsize      ( prop$ uz len )
1013986fd29aSsetje            ['] uz-nmlook  -rot           ( prop$ xt uz len )
1014986fd29aSsetje            uzap-apply  if                ( prop$ uz )
1015986fd29aSsetje               mze_value  -rot 2drop      ( n )
1016986fd29aSsetje               false                      ( n found )
1017986fd29aSsetje            else                          ( prop$ )
1018986fd29aSsetje               2drop  true                ( !found )
1019986fd29aSsetje            then                          ( [ n ] not-found? )
1020986fd29aSsetje         endof
1021986fd29aSsetje         fzap#  of
1022986fd29aSsetje            ['] fz-nmlook  -rot           ( prop$ xt dn fz )
1023986fd29aSsetje            fzap-apply  if                ( prop$ dn le )
1024986fd29aSsetje               entry-int-val              ( prop$ n )
1025986fd29aSsetje               -rot 2drop  false          ( n found )
1026986fd29aSsetje            else                          ( prop$ )
1027986fd29aSsetje               2drop  true                ( !found )
1028986fd29aSsetje            then                          ( [ n ] not-found? )
1029986fd29aSsetje         endof
1030986fd29aSsetje         3drop 2drop  true                ( !found )
1031986fd29aSsetje      endcase                             ( [ n ] not-found? )
1032986fd29aSsetje   ;
1033986fd29aSsetje
1034986fd29aSsetje[ifdef] strlookup
1035986fd29aSsetje   : zap-lookup-str  ( dn prop$ -- [ val$ ] not-found? )
1036986fd29aSsetje      rot  dup get-zap                    ( prop$ dn zp )
1037986fd29aSsetje      dup zap-type  fzap#  <>  if         ( prop$ dn zp )
1038986fd29aSsetje         2drop 2drop  true  exit          ( !found )
1039986fd29aSsetje      then                                ( prop$ dn zp )
1040986fd29aSsetje      ['] fz-nmlook -rot                  ( prop$ xt dn fz )
1041986fd29aSsetje      fzap-apply  if                      ( prop$ dn le )
1042986fd29aSsetje         entry-val$  2swap 2drop  false   ( val$ found )
1043986fd29aSsetje      else                                ( prop$ )
1044986fd29aSsetje         2drop  true                      ( !found )
1045986fd29aSsetje      then                                ( [ val$ ] not-found? )
1046986fd29aSsetje   ;
1047986fd29aSsetje[then]
1048986fd29aSsetje
1049986fd29aSsetje   : fz-print  ( dn le -- false )
1050986fd29aSsetje      entry-name$  type cr  false
1051986fd29aSsetje   ;
1052986fd29aSsetje
1053986fd29aSsetje   : uz-print  ( uz -- false )
1054986fd29aSsetje      uzap-name$  type cr  false
1055986fd29aSsetje   ;
1056986fd29aSsetje
1057986fd29aSsetje   : zap-print  ( dn -- )
1058986fd29aSsetje      dup get-zap                         ( dn zp )
1059986fd29aSsetje      dup zap-type  case
1060986fd29aSsetje         uzap#  of
1061986fd29aSsetje            >uzap-ent  swap dn-bsize      ( uz len )
1062986fd29aSsetje            ['] uz-print  -rot            ( xt uz len )
1063986fd29aSsetje            uzap-apply                    ( false )
1064986fd29aSsetje         endof
1065986fd29aSsetje         fzap#  of
1066986fd29aSsetje            ['] fz-print -rot             ( xt dn fz )
1067986fd29aSsetje            fzap-apply                    ( false )
1068986fd29aSsetje         endof
1069986fd29aSsetje         3drop  false                     ( false )
1070986fd29aSsetje      endcase                             ( false )
1071986fd29aSsetje      drop                                (  )
1072986fd29aSsetje   ;
1073986fd29aSsetje
1074986fd29aSsetje
1075986fd29aSsetje   \
1076986fd29aSsetje   \	ZFS object set (DSL) routines
1077986fd29aSsetje   \
1078986fd29aSsetje
1079986fd29aSsetje   1 constant pool-dir#
1080986fd29aSsetje
1081986fd29aSsetje   : dd_head_dataset_obj  ( dd -- n )  h#  8 +  x@  ;
1082986fd29aSsetje   : dd_child_dir_zapobj  ( dd -- n )  h# 20 +  x@  ;
1083e7cbe64fSgw25295
1084e7cbe64fSgw25295   : ds_snapnames_zapobj  ( ds -- n )  h# 20 +  x@  ;
1085986fd29aSsetje   : ds_bp                ( ds -- p )  h# 80 +      ;
1086986fd29aSsetje
1087986fd29aSsetje   0 instance value mos-dn
1088986fd29aSsetje   0 instance value obj-dir
1089986fd29aSsetje   0 instance value root-dsl
1090986fd29aSsetje   0 instance value fs-dn
1091986fd29aSsetje
1092986fd29aSsetje   \ dn-cache contains dc-dn's contents at dc-blk#
1093986fd29aSsetje   \ dc-dn will be either mos-dn or fs-dn
1094986fd29aSsetje   0 instance value dn-cache
1095986fd29aSsetje   0 instance value dc-dn
1096986fd29aSsetje   0 instance value dc-blk#
1097986fd29aSsetje
1098986fd29aSsetje   alias  >dsl-dir  dn_bonus
1099986fd29aSsetje   alias  >dsl-ds   dn_bonus
1100986fd29aSsetje
1101986fd29aSsetje   : #dn/blk  ( dn -- n )     dn-bsize /dnode  /  ;
1102986fd29aSsetje
1103986fd29aSsetje   \ read block into dn-cache
1104986fd29aSsetje   : get-dnblk  ( dn blk# -- )
1105986fd29aSsetje      lblk#>bp  dn-cache swap         ( adr bp )
1106986fd29aSsetje      dup bp-lsize swap  read-bp      (  )
1107986fd29aSsetje   ;
1108986fd29aSsetje
1109986fd29aSsetje   \ read obj# from objset dir dn into dnode
1110986fd29aSsetje   : get-dnode  ( dn obj# -- )
1111986fd29aSsetje
1112986fd29aSsetje      \ check dn-cache
1113986fd29aSsetje      2dup  swap #dn/blk  /mod       ( dn obj# off# blk# )
1114986fd29aSsetje      swap >r  nip                   ( dn blk#  r: off# )
1115986fd29aSsetje      2dup  dc-blk#  <>              ( dn blk# dn !blk-hit?  r: off# )
1116986fd29aSsetje      swap dc-dn  <>  or  if         ( dn blk#  r: off# )
1117986fd29aSsetje         \ cache miss, fill from dir
1118986fd29aSsetje         2dup  get-dnblk
1119986fd29aSsetje         over  to dc-dn
1120986fd29aSsetje         dup   to dc-blk#
1121986fd29aSsetje      then                           ( dn blk#  r: off# )
1122986fd29aSsetje
1123986fd29aSsetje      \ index and copy
1124986fd29aSsetje      2drop r>  /dnode *             ( off )
1125986fd29aSsetje      dn-cache +                     ( dn-adr )
1126986fd29aSsetje      dnode  /dnode  move            (  )
1127986fd29aSsetje   ;
1128986fd29aSsetje
1129986fd29aSsetje   \ read meta object set from uber-block
1130986fd29aSsetje   : get-mos  ( -- )
1131c0dbe950SToomas Soome      mos-dn uber-block ub_rootbp    ( adr bp )
1132c0dbe950SToomas Soome      dup bp-lsize swap read-bp
1133986fd29aSsetje   ;
1134986fd29aSsetje
1135986fd29aSsetje   : get-mos-dnode  ( obj# -- )
1136986fd29aSsetje      mos-dn swap  get-dnode
1137986fd29aSsetje   ;
1138986fd29aSsetje
1139986fd29aSsetje   \ get root dataset
1140986fd29aSsetje   : get-root-dsl  ( -- )
1141986fd29aSsetje
1142986fd29aSsetje      \ read MOS
1143986fd29aSsetje      get-mos
1144986fd29aSsetje
1145986fd29aSsetje      \ read object dir
1146986fd29aSsetje      pool-dir#  get-mos-dnode
1147986fd29aSsetje      dnode obj-dir  /dnode  move
1148986fd29aSsetje
1149986fd29aSsetje      \ read root dataset
1150986fd29aSsetje      obj-dir " root_dataset"  zap-lookup  if
1151e7cbe64fSgw25295         " no root_dataset"  die
1152986fd29aSsetje      then                                   ( obj# )
1153986fd29aSsetje      get-mos-dnode                          (  )
1154986fd29aSsetje      dnode root-dsl  /dnode  move
1155986fd29aSsetje   ;
1156986fd29aSsetje
1157e7cbe64fSgw25295   \ find snapshot of given dataset
1158e7cbe64fSgw25295   : snap-look  ( snap$ ds-obj# -- [ss-obj# ] not-found? )
1159e7cbe64fSgw25295      get-mos-dnode  dnode >dsl-ds         ( snap$ ds )
1160e7cbe64fSgw25295      ds_snapnames_zapobj  get-mos-dnode   ( snap$ )
1161e7cbe64fSgw25295      dnode -rot  zap-lookup               ( [ss-obj# ] not-found? )
1162e7cbe64fSgw25295   ;
1163e7cbe64fSgw25295
1164e7cbe64fSgw25295   \ dsl dir to dataset
1165e7cbe64fSgw25295   : dir>ds   ( dn -- obj# )  >dsl-dir dd_head_dataset_obj  ;
1166e7cbe64fSgw25295
1167986fd29aSsetje   \ look thru the dsl hierarchy for path
1168986fd29aSsetje   \ this looks almost exactly like a FS directory lookup
1169986fd29aSsetje   : dsl-lookup ( path$ -- [ ds-obj# ] not-found? )
1170986fd29aSsetje      root-dsl >r                                 ( path$  r: root-dn )
1171986fd29aSsetje      begin
1172986fd29aSsetje         ascii /  left-parse-string               ( path$ file$  r: dn )
1173986fd29aSsetje      dup  while
1174986fd29aSsetje
1175986fd29aSsetje         \ get child dir zap dnode
1176986fd29aSsetje         r>  >dsl-dir dd_child_dir_zapobj         ( path$ file$ obj# )
1177986fd29aSsetje         get-mos-dnode                            ( path$ file$ )
1178986fd29aSsetje
1179e7cbe64fSgw25295         \ check for snapshot names
1180e7cbe64fSgw25295         ascii @  left-parse-string               ( path$ snap$ file$ )
1181e7cbe64fSgw25295
1182986fd29aSsetje         \ search it
1183e7cbe64fSgw25295         dnode -rot zap-lookup  if                ( path$ snap$ )
1184986fd29aSsetje            \ not found
1185e7cbe64fSgw25295            2drop 2drop true  exit                ( not-found )
1186e7cbe64fSgw25295         then                                     ( path$ snap$ obj# )
1187e7cbe64fSgw25295         get-mos-dnode                            ( path$ snap$ )
1188e7cbe64fSgw25295
1189e7cbe64fSgw25295         \ lookup any snapshot name
1190e7cbe64fSgw25295         dup  if
1191e7cbe64fSgw25295            \ must be last path component
1192e7cbe64fSgw25295            2swap  nip  if                        ( snap$ )
1193986fd29aSsetje               2drop true  exit                   ( not-found )
1194e7cbe64fSgw25295            then
1195e7cbe64fSgw25295            dnode dir>ds  snap-look  if           (  )
1196e7cbe64fSgw25295               true  exit                         ( not-found )
1197e7cbe64fSgw25295            then                                  ( obj# )
1198e7cbe64fSgw25295            false  exit                           ( obj# found )
1199e7cbe64fSgw25295         else  2drop  then                        ( path$ )
1200e7cbe64fSgw25295
1201986fd29aSsetje         dnode >r                                 ( path$  r: dn )
1202986fd29aSsetje      repeat                                      ( path$ file$  r: dn)
1203986fd29aSsetje      2drop 2drop  r> drop                        (  )
1204986fd29aSsetje
1205986fd29aSsetje      \ found it, return dataset obj#
1206e7cbe64fSgw25295      dnode  dir>ds                               ( ds-obj# )
1207986fd29aSsetje      false                                       ( ds-obj# found )
1208986fd29aSsetje   ;
1209986fd29aSsetje
1210986fd29aSsetje   \ get objset from dataset
1211986fd29aSsetje   : get-objset  ( adr dn -- )
1212c0dbe950SToomas Soome      >dsl-ds ds_bp  dup bp-lsize swap  read-bp
1213986fd29aSsetje   ;
1214986fd29aSsetje
1215986fd29aSsetje
1216986fd29aSsetje   \
1217986fd29aSsetje   \	ZFS file-system (ZPL) routines
1218986fd29aSsetje   \
1219986fd29aSsetje
1220986fd29aSsetje   1       constant master-node#
12210a586ceaSMark Shellenbaum
12220a586ceaSMark Shellenbaum   0 instance value bootfs-obj#
12230a586ceaSMark Shellenbaum   0 instance value root-obj#
12240a586ceaSMark Shellenbaum   0 instance value current-obj#
12250a586ceaSMark Shellenbaum   0 instance value search-obj#
12260a586ceaSMark Shellenbaum
12270a586ceaSMark Shellenbaum   instance defer fsize         ( dn -- size )
12280a586ceaSMark Shellenbaum   instance defer mode          ( dn -- mode )
12290a586ceaSMark Shellenbaum   instance defer parent        ( dn -- obj# )
12300a586ceaSMark Shellenbaum   instance defer readlink      ( dst dn -- )
12310a586ceaSMark Shellenbaum
12320a586ceaSMark Shellenbaum   \
12330a586ceaSMark Shellenbaum   \ routines when bonus pool contains a znode
12340a586ceaSMark Shellenbaum   \
1235986fd29aSsetje   d# 264  constant /znode
1236986fd29aSsetje   d#  56  constant /zn-slink
1237986fd29aSsetje
1238986fd29aSsetje   : zp_mode    ( zn -- n )  h# 48 +  x@  ;
1239986fd29aSsetje   : zp_size    ( zn -- n )  h# 50 +  x@  ;
1240986fd29aSsetje   : zp_parent  ( zn -- n )  h# 58 +  x@  ;
1241986fd29aSsetje
1242986fd29aSsetje   alias  >znode  dn_bonus
1243986fd29aSsetje
12440a586ceaSMark Shellenbaum   : zn-fsize     ( dn -- n )  >znode zp_size    ;
12450a586ceaSMark Shellenbaum   : zn-mode      ( dn -- n )  >znode zp_mode    ;
12460a586ceaSMark Shellenbaum   : zn-parent    ( dn -- n )  >znode zp_parent  ;
12470a586ceaSMark Shellenbaum
12480a586ceaSMark Shellenbaum   \ copy symlink target to dst
12490a586ceaSMark Shellenbaum   : zn-readlink  ( dst dn -- )
12500a586ceaSMark Shellenbaum      dup zn-fsize  tuck /zn-slink  >  if ( dst size dn )
12510a586ceaSMark Shellenbaum         \ contents in 1st block
12520a586ceaSMark Shellenbaum         temp-space  over dn-bsize        ( dst size dn t-adr bsize )
12530a586ceaSMark Shellenbaum         rot  0 lblk#>bp  read-bp         ( dst size )
12540a586ceaSMark Shellenbaum         temp-space                       ( dst size src )
12550a586ceaSMark Shellenbaum      else                                ( dst size dn )
12560a586ceaSMark Shellenbaum         \ contents in dnode
12570a586ceaSMark Shellenbaum         >znode  /znode +                 ( dst size src )
12580a586ceaSMark Shellenbaum      then                                ( dst size src )
12590a586ceaSMark Shellenbaum      -rot  move                          (  )
12600a586ceaSMark Shellenbaum   ;
12610a586ceaSMark Shellenbaum
12620a586ceaSMark Shellenbaum   \
12630a586ceaSMark Shellenbaum   \ routines when bonus pool contains sa's
12640a586ceaSMark Shellenbaum   \
12650a586ceaSMark Shellenbaum
12660a586ceaSMark Shellenbaum   \ SA header size when link is in dn_bonus
12670a586ceaSMark Shellenbaum   d# 16  constant  /sahdr-link
12680a586ceaSMark Shellenbaum
12690a586ceaSMark Shellenbaum   : sa_props  ( sa -- n )   h# 4 +  w@  ;
12700a586ceaSMark Shellenbaum
12710a586ceaSMark Shellenbaum   : sa-hdrsz  ( sa -- sz )  sa_props h# 7  >>  ;
12720a586ceaSMark Shellenbaum
12730a586ceaSMark Shellenbaum   alias  >sa  dn_bonus
12740a586ceaSMark Shellenbaum
12750a586ceaSMark Shellenbaum   : >sadata    ( dn -- adr )  >sa dup  sa-hdrsz  +  ;
12760a586ceaSMark Shellenbaum   : sa-mode    ( dn -- n )    >sadata           x@  ;
12770a586ceaSMark Shellenbaum   : sa-fsize   ( dn -- n )    >sadata  h#  8 +  x@  ;
12780a586ceaSMark Shellenbaum   : sa-parent  ( dn -- n )    >sadata  h# 28 +  x@  ;
12790a586ceaSMark Shellenbaum
12800a586ceaSMark Shellenbaum   \ copy symlink target to dst
12810a586ceaSMark Shellenbaum   : sa-readlink  ( dst dn -- )
12820a586ceaSMark Shellenbaum      dup  >sa sa-hdrsz  /sahdr-link  <>  if
12830a586ceaSMark Shellenbaum         \ contents in 1st attr of dn_spill
12840a586ceaSMark Shellenbaum         temp-space  over dn_spill           ( dst dn t-adr bp )
12850a586ceaSMark Shellenbaum         dup bp-lsize  swap  read-bp         ( dst dn )
12860a586ceaSMark Shellenbaum         sa-fsize                            ( dst size )
12870a586ceaSMark Shellenbaum         temp-space dup sa-hdrsz  +          ( dst size src )
12880a586ceaSMark Shellenbaum      else                                   ( dst dn )
12890a586ceaSMark Shellenbaum         \ content in bonus buf
12900a586ceaSMark Shellenbaum         dup dn_bonus  over  dn_bonuslen  +  ( dst dn ebonus )
12910a586ceaSMark Shellenbaum         swap sa-fsize  tuck  -              ( dst size src )
12920a586ceaSMark Shellenbaum      then                                   ( dst size src )
12930a586ceaSMark Shellenbaum      -rot  move                             (  )
12940a586ceaSMark Shellenbaum   ;
12950a586ceaSMark Shellenbaum
12960a586ceaSMark Shellenbaum
12970a586ceaSMark Shellenbaum   \ setup attr routines for dn
12980a586ceaSMark Shellenbaum   : set-attr  ( dn -- )
12990a586ceaSMark Shellenbaum      dn_bonustype  ot-sa#  =  if
13000a586ceaSMark Shellenbaum         ['] sa-fsize     to  fsize
13010a586ceaSMark Shellenbaum         ['] sa-mode      to  mode
13020a586ceaSMark Shellenbaum         ['] sa-parent    to  parent
13030a586ceaSMark Shellenbaum         ['] sa-readlink  to  readlink
13040a586ceaSMark Shellenbaum      else
13050a586ceaSMark Shellenbaum         ['] zn-fsize     to  fsize
13060a586ceaSMark Shellenbaum         ['] zn-mode      to  mode
13070a586ceaSMark Shellenbaum         ['] zn-parent    to  parent
13080a586ceaSMark Shellenbaum         ['] zn-readlink  to  readlink
13090a586ceaSMark Shellenbaum      then
13100a586ceaSMark Shellenbaum   ;
13110a586ceaSMark Shellenbaum
13120a586ceaSMark Shellenbaum   : ftype     ( dn -- type )  mode   h# f000  and  ;
1313986fd29aSsetje   : dir?      ( dn -- flag )  ftype  h# 4000  =  ;
1314986fd29aSsetje   : symlink?  ( dn -- flag )  ftype  h# a000  =  ;
1315986fd29aSsetje
1316986fd29aSsetje   \ read obj# from fs objset
1317986fd29aSsetje   : get-fs-dnode  ( obj# -- )
1318986fd29aSsetje      dup to current-obj#
1319986fd29aSsetje      fs-dn swap  get-dnode    (  )
1320986fd29aSsetje   ;
1321986fd29aSsetje
1322986fd29aSsetje   \ get root-obj# from dataset
1323986fd29aSsetje   : get-rootobj#  ( ds-obj# -- fsroot-obj# )
1324986fd29aSsetje      dup to bootfs-obj#
1325986fd29aSsetje      get-mos-dnode                   (  )
1326986fd29aSsetje      fs-dn dnode  get-objset
1327986fd29aSsetje
1328986fd29aSsetje      \ get root obj# from master node
1329986fd29aSsetje      master-node#  get-fs-dnode
1330986fd29aSsetje      dnode  " ROOT"  zap-lookup  if
1331e7cbe64fSgw25295         " no ROOT"  die
1332986fd29aSsetje      then                             ( fsroot-obj# )
1333986fd29aSsetje   ;
1334986fd29aSsetje
1335986fd29aSsetje   : prop>rootobj#  ( -- )
1336986fd29aSsetje      obj-dir " pool_props" zap-lookup  if
1337e7cbe64fSgw25295         " no pool_props"  die
1338986fd29aSsetje      then                               ( prop-obj# )
1339986fd29aSsetje      get-mos-dnode                      (  )
1340986fd29aSsetje      dnode " bootfs" zap-lookup  if
1341e7cbe64fSgw25295         " no bootfs"  die
1342986fd29aSsetje      then                               ( ds-obj# )
1343986fd29aSsetje      get-rootobj#                       ( fsroot-obj# )
1344986fd29aSsetje   ;
1345986fd29aSsetje
1346986fd29aSsetje   : fs>rootobj#  ( fs$ -- root-obj# not-found? )
1347986fd29aSsetje
1348986fd29aSsetje      \ skip pool name
1349986fd29aSsetje      ascii /  left-parse-string  2drop
1350986fd29aSsetje
1351986fd29aSsetje      \ lookup fs in dsl
1352986fd29aSsetje      dsl-lookup  if                   (  )
1353986fd29aSsetje         true  exit                    ( not-found )
1354986fd29aSsetje      then                             ( ds-obj# )
1355986fd29aSsetje
1356986fd29aSsetje      get-rootobj#                     ( fsroot-obj# )
1357986fd29aSsetje      false                            ( fsroot-obj# found )
1358986fd29aSsetje   ;
1359986fd29aSsetje
1360986fd29aSsetje   \ lookup file is current directory
1361986fd29aSsetje   : dirlook  ( file$ dn -- not-found? )
1362986fd29aSsetje      \ . and .. are magic
1363986fd29aSsetje      -rot  2dup " ."  $=  if     ( dn file$ )
1364986fd29aSsetje         3drop  false  exit       ( found )
1365986fd29aSsetje      then
1366986fd29aSsetje
1367986fd29aSsetje      2dup " .."  $=  if
13680a586ceaSMark Shellenbaum         2drop  parent            ( obj# )
1369986fd29aSsetje      else                        ( dn file$ )
1370986fd29aSsetje         \ search dir
1371986fd29aSsetje         current-obj# to search-obj#
1372986fd29aSsetje         zap-lookup  if           (  )
1373986fd29aSsetje            true  exit            ( not-found )
1374986fd29aSsetje         then                     ( obj# )
1375986fd29aSsetje      then                        ( obj# )
13760a586ceaSMark Shellenbaum      get-fs-dnode
13770a586ceaSMark Shellenbaum      dnode  set-attr
13780a586ceaSMark Shellenbaum      false                       ( found )
1379986fd29aSsetje   ;
1380986fd29aSsetje
1381986fd29aSsetje   /buf-len  instance buffer: fpath-buf
13820a586ceaSMark Shellenbaum   /buf-len  instance buffer: tpath-buf
1383986fd29aSsetje
13840a586ceaSMark Shellenbaum   : tpath-buf$  ( -- path$ )  tpath-buf cscount  ;
1385986fd29aSsetje   : fpath-buf$  ( -- path$ )  fpath-buf cscount  ;
1386986fd29aSsetje
1387986fd29aSsetje   \ modify tail to account for symlink
1388986fd29aSsetje   : follow-symlink  ( tail$ -- tail$' )
13890a586ceaSMark Shellenbaum      \ read target
13900a586ceaSMark Shellenbaum      tpath-buf /buf-len  erase
13910a586ceaSMark Shellenbaum      tpath-buf dnode  readlink
1392986fd29aSsetje
13930a586ceaSMark Shellenbaum      \ append current path
1394986fd29aSsetje      ?dup  if                                  ( tail$ )
13950a586ceaSMark Shellenbaum	 " /" tpath-buf$  $append               ( tail$ )
13960a586ceaSMark Shellenbaum	 tpath-buf$  $append                    (  )
1397986fd29aSsetje      else  drop  then                          (  )
13980a586ceaSMark Shellenbaum
13990a586ceaSMark Shellenbaum      \ copy to fpath
14000a586ceaSMark Shellenbaum      fpath-buf  /buf-len  erase
14010a586ceaSMark Shellenbaum      tpath-buf$  fpath-buf  swap move
1402986fd29aSsetje      fpath-buf$                                ( path$ )
1403986fd29aSsetje
1404986fd29aSsetje      \ get directory that starts changed path
1405986fd29aSsetje      over c@  ascii /  =  if                   ( path$ )
1406986fd29aSsetje	 str++  root-obj#                       ( path$' obj# )
1407986fd29aSsetje      else                                      ( path$ )
1408986fd29aSsetje         search-obj#                            ( path$ obj# )
1409986fd29aSsetje      then                                      ( path$ obj# )
1410986fd29aSsetje      get-fs-dnode                              ( path$ )
14110a586ceaSMark Shellenbaum      dnode  set-attr
1412986fd29aSsetje   ;
1413986fd29aSsetje
1414986fd29aSsetje   \ open dnode at path
1415986fd29aSsetje   : lookup  ( path$ -- not-found? )
1416986fd29aSsetje
1417986fd29aSsetje      \ get directory that starts path
1418986fd29aSsetje      over c@  ascii /  =  if
1419986fd29aSsetje         str++  root-obj#                         ( path$' obj# )
1420986fd29aSsetje      else
1421986fd29aSsetje         current-obj#                             ( path$ obj# )
1422986fd29aSsetje      then                                        ( path$ obj# )
1423986fd29aSsetje      get-fs-dnode                                ( path$ )
14240a586ceaSMark Shellenbaum      dnode  set-attr
1425986fd29aSsetje
1426986fd29aSsetje      \ lookup each path component
1427986fd29aSsetje      begin                                       ( path$ )
1428986fd29aSsetje         ascii /  left-parse-string               ( path$ file$ )
1429986fd29aSsetje      dup  while
1430986fd29aSsetje         dnode dir?  0=  if
1431986fd29aSsetje            2drop true  exit                      ( not-found )
1432986fd29aSsetje         then                                     ( path$ file$ )
1433986fd29aSsetje         dnode dirlook  if                        ( path$ )
1434986fd29aSsetje            2drop true  exit                      ( not-found )
1435986fd29aSsetje         then                                     ( path$ )
1436986fd29aSsetje         dnode symlink?  if
1437986fd29aSsetje            follow-symlink                        ( path$' )
1438986fd29aSsetje         then                                     ( path$ )
1439986fd29aSsetje      repeat                                      ( path$ file$ )
1440986fd29aSsetje      2drop 2drop  false                          ( found )
1441986fd29aSsetje   ;
1442986fd29aSsetje
1443986fd29aSsetje   \
1444e7cbe64fSgw25295   \   ZFS volume (ZVOL) routines
1445e7cbe64fSgw25295   \
1446e7cbe64fSgw25295   1 constant  zvol-data#
1447e7cbe64fSgw25295   2 constant  zvol-prop#
1448e7cbe64fSgw25295
1449e7cbe64fSgw25295   0 instance value zv-dn
1450e7cbe64fSgw25295
1451e7cbe64fSgw25295   : get-zvol  ( zvol$ -- not-found? )
1452e7cbe64fSgw25295      dsl-lookup  if
1453e7cbe64fSgw25295         drop true  exit           ( failed )
1454e7cbe64fSgw25295      then                         ( ds-obj# )
1455e7cbe64fSgw25295
1456e7cbe64fSgw25295      \ get zvol objset
1457e7cbe64fSgw25295      get-mos-dnode                (  )
1458e7cbe64fSgw25295      zv-dn dnode  get-objset
1459e7cbe64fSgw25295      false                        ( succeeded )
1460e7cbe64fSgw25295   ;
1461e7cbe64fSgw25295
1462e7cbe64fSgw25295   \ get zvol data dnode
1463e7cbe64fSgw25295   : zvol-data  ( -- )
1464e7cbe64fSgw25295      zv-dn zvol-data#  get-dnode
1465e7cbe64fSgw25295   ;
1466e7cbe64fSgw25295
1467e7cbe64fSgw25295   : zvol-size  ( -- size )
1468e7cbe64fSgw25295       zv-dn zvol-prop#   get-dnode
1469e7cbe64fSgw25295       dnode " size"  zap-lookup  if
1470e7cbe64fSgw25295          " no zvol size"  die
1471e7cbe64fSgw25295       then                            ( size )
1472e7cbe64fSgw25295   ;
1473e7cbe64fSgw25295
1474e7cbe64fSgw25295
1475e7cbe64fSgw25295   \
1476986fd29aSsetje   \	ZFS installation routines
1477986fd29aSsetje   \
1478986fd29aSsetje
1479986fd29aSsetje   \ ZFS file interface
1480986fd29aSsetje   struct
1481986fd29aSsetje      /x     field >busy
1482986fd29aSsetje      /x     field >offset
1483e7cbe64fSgw25295      /x     field >fsize
1484986fd29aSsetje      /dnode field >dnode
1485986fd29aSsetje   constant /file-record
1486986fd29aSsetje
1487986fd29aSsetje   d# 10                  constant #opens
1488986fd29aSsetje   #opens /file-record *  constant /file-records
1489986fd29aSsetje
1490986fd29aSsetje   /file-records  instance buffer: file-records
1491986fd29aSsetje
1492986fd29aSsetje   -1 instance value current-fd
1493986fd29aSsetje
1494986fd29aSsetje   : fd>record     ( fd -- rec )  /file-record *  file-records +  ;
1495986fd29aSsetje   : file-offset@  ( -- off )     current-fd fd>record >offset  x@  ;
1496986fd29aSsetje   : file-offset!  ( off -- )     current-fd fd>record >offset  x!  ;
1497986fd29aSsetje   : file-dnode    ( -- dn )      current-fd fd>record >dnode  ;
1498e7cbe64fSgw25295   : file-size     ( -- size )    current-fd fd>record >fsize  x@  ;
1499986fd29aSsetje   : file-bsize    ( -- bsize )   file-dnode  dn-bsize  ;
1500986fd29aSsetje
1501986fd29aSsetje   \ find free fd slot
1502986fd29aSsetje   : get-slot  ( -- fd false | true )
1503986fd29aSsetje      #opens 0  do
1504986fd29aSsetje         i fd>record >busy x@  0=  if
1505986fd29aSsetje            i false  unloop exit
1506986fd29aSsetje         then
1507986fd29aSsetje      loop  true
1508986fd29aSsetje   ;
1509986fd29aSsetje
1510986fd29aSsetje   : free-slot  ( fd -- )
1511986fd29aSsetje      0 swap  fd>record >busy  x!
1512986fd29aSsetje   ;
1513986fd29aSsetje
1514986fd29aSsetje   \ init fd to offset 0 and copy dnode
1515e7cbe64fSgw25295   : init-fd  ( fsize fd -- )
1516e7cbe64fSgw25295      fd>record                ( fsize rec )
1517986fd29aSsetje      dup  >busy  1 swap  x!
1518986fd29aSsetje      dup  >dnode  dnode swap  /dnode  move
1519e7cbe64fSgw25295      dup  >fsize  rot swap  x!     ( rec )
1520e7cbe64fSgw25295      >offset  0 swap  x!      (  )
1521986fd29aSsetje   ;
1522986fd29aSsetje
1523986fd29aSsetje   \ make fd current
1524986fd29aSsetje   : set-fd  ( fd -- error? )
1525986fd29aSsetje      dup fd>record  >busy x@  0=  if   ( fd )
1526986fd29aSsetje         drop true  exit                ( failed )
1527986fd29aSsetje      then                              ( fd )
1528986fd29aSsetje      to current-fd  false              ( succeeded )
1529986fd29aSsetje   ;
1530986fd29aSsetje
1531986fd29aSsetje   \ read next fs block
1532986fd29aSsetje   : file-bread  ( adr -- )
1533986fd29aSsetje      file-bsize                      ( adr len )
1534986fd29aSsetje      file-offset@ over  /            ( adr len blk# )
1535986fd29aSsetje      file-dnode swap  lblk#>bp       ( adr len bp )
1536986fd29aSsetje      read-bp                         ( )
1537986fd29aSsetje   ;
1538986fd29aSsetje
1539986fd29aSsetje   \ advance file io stack by n
1540986fd29aSsetje   : fio+  ( # adr len n -- #+n adr+n len-n )
1541986fd29aSsetje      dup file-offset@ +  file-offset!
1542986fd29aSsetje      dup >r  -  -rot   ( len' # adr  r: n )
1543986fd29aSsetje      r@  +  -rot       ( adr' len' #  r: n )
1544986fd29aSsetje      r>  +  -rot       ( #' adr' len' )
1545986fd29aSsetje   ;
1546986fd29aSsetje
1547629270abSjgj
1548986fd29aSsetje   /max-bsize    5 *
1549986fd29aSsetje   /uber-block        +
1550e7cbe64fSgw25295   /dnode        6 *  +
1551c713350eSJohn Johnson   /disk-block   6 *  +    ( size )
1552629270abSjgj   \ ugh - sg proms can't free 512k allocations
1553629270abSjgj   \ that aren't a multiple of 512k in size
1554629270abSjgj   h# 8.0000  roundup      ( size' )
1555986fd29aSsetje   constant  alloc-size
1556986fd29aSsetje
1557629270abSjgj
1558986fd29aSsetje   : allocate-buffers  ( -- )
1559986fd29aSsetje      alloc-size h# a0.0000 vmem-alloc  dup 0=  if
1560e7cbe64fSgw25295         " no memory"  die
1561986fd29aSsetje      then                                ( adr )
1562986fd29aSsetje      dup to temp-space    /max-bsize  +  ( adr )
1563986fd29aSsetje      dup to dn-cache      /max-bsize  +  ( adr )
1564986fd29aSsetje      dup to blk-space     /max-bsize  +  ( adr )
1565986fd29aSsetje      dup to ind-cache     /max-bsize  +  ( adr )
1566986fd29aSsetje      dup to zap-space     /max-bsize  +  ( adr )
1567986fd29aSsetje      dup to uber-block    /uber-block +  ( adr )
1568986fd29aSsetje      dup to mos-dn        /dnode      +  ( adr )
1569986fd29aSsetje      dup to obj-dir       /dnode      +  ( adr )
1570986fd29aSsetje      dup to root-dsl      /dnode      +  ( adr )
1571986fd29aSsetje      dup to fs-dn         /dnode      +  ( adr )
1572e7cbe64fSgw25295      dup to zv-dn         /dnode      +  ( adr )
1573986fd29aSsetje      dup to dnode         /dnode      +  ( adr )
1574986fd29aSsetje          to gang-space                   (  )
1575986fd29aSsetje
1576986fd29aSsetje      \ zero instance buffers
1577986fd29aSsetje      file-records /file-records  erase
1578986fd29aSsetje      bootprop-buf /buf-len  erase
1579986fd29aSsetje   ;
1580986fd29aSsetje
1581986fd29aSsetje   : release-buffers  ( -- )
1582986fd29aSsetje      temp-space  alloc-size  mem-free
1583986fd29aSsetje   ;
1584986fd29aSsetje
1585986fd29aSsetje   external
1586986fd29aSsetje
1587986fd29aSsetje   : open ( -- okay? )
1588986fd29aSsetje      my-args dev-open  dup 0=  if
1589986fd29aSsetje         exit                       ( failed )
1590986fd29aSsetje      then  to dev-ih
1591986fd29aSsetje
1592986fd29aSsetje      allocate-buffers
1593986fd29aSsetje      scan-vdev
1594986fd29aSsetje      get-ub
1595986fd29aSsetje      get-root-dsl
1596986fd29aSsetje      true
1597986fd29aSsetje   ;
1598986fd29aSsetje
1599986fd29aSsetje   : open-fs  ( fs$ -- okay? )
1600986fd29aSsetje      fs>rootobj#  if        (  )
1601986fd29aSsetje         false               ( failed )
1602986fd29aSsetje      else                   ( obj# )
1603986fd29aSsetje         to root-obj#  true  ( succeeded )
1604986fd29aSsetje      then                   ( okay? )
1605986fd29aSsetje   ;
1606986fd29aSsetje
1607986fd29aSsetje   : close  ( -- )
1608986fd29aSsetje      dev-ih dev-close
1609986fd29aSsetje      0 to dev-ih
1610986fd29aSsetje      release-buffers
1611986fd29aSsetje   ;
1612986fd29aSsetje
1613986fd29aSsetje   : open-file  ( path$ -- fd true | false )
1614986fd29aSsetje
1615986fd29aSsetje      \ open default fs if no open-fs
1616986fd29aSsetje      root-obj# 0=  if
1617986fd29aSsetje         prop>rootobj#  to root-obj#
1618986fd29aSsetje      then
1619986fd29aSsetje
1620986fd29aSsetje      get-slot  if
1621986fd29aSsetje         2drop false  exit         ( failed )
1622986fd29aSsetje      then  -rot                   ( fd path$ )
1623986fd29aSsetje
1624986fd29aSsetje      lookup  if                   ( fd )
1625986fd29aSsetje         drop false  exit          ( failed )
1626986fd29aSsetje      then                         ( fd )
1627986fd29aSsetje
1628e7cbe64fSgw25295      dnode fsize  over init-fd
1629e7cbe64fSgw25295      true                         ( fd succeeded )
1630e7cbe64fSgw25295   ;
1631e7cbe64fSgw25295
1632e7cbe64fSgw25295   : open-volume ( vol$ -- okay? )
1633e7cbe64fSgw25295      get-slot  if
1634e7cbe64fSgw25295         2drop false  exit         ( failed )
1635e7cbe64fSgw25295      then  -rot                   ( fd vol$ )
1636e7cbe64fSgw25295
1637e7cbe64fSgw25295      get-zvol  if                 ( fd )
1638e7cbe64fSgw25295         drop false  exit          ( failed )
1639e7cbe64fSgw25295      then
1640e7cbe64fSgw25295
1641e7cbe64fSgw25295      zvol-size over               ( fd size fd )
1642e7cbe64fSgw25295      zvol-data init-fd            ( fd )
1643e7cbe64fSgw25295      true                         ( fd succeeded )
1644986fd29aSsetje   ;
1645986fd29aSsetje
1646986fd29aSsetje   : close-file  ( fd -- )
1647986fd29aSsetje      free-slot   (  )
1648986fd29aSsetje   ;
1649986fd29aSsetje
1650986fd29aSsetje   : size-file  ( fd -- size )
1651986fd29aSsetje      set-fd  if  0  else  file-size  then
1652986fd29aSsetje   ;
1653986fd29aSsetje
1654986fd29aSsetje   : seek-file  ( off fd -- off true | false )
1655986fd29aSsetje      set-fd  if                ( off )
1656986fd29aSsetje         drop false  exit       ( failed )
1657986fd29aSsetje      then                      ( off )
1658986fd29aSsetje
1659e7cbe64fSgw25295      dup file-size x>  if      ( off )
1660986fd29aSsetje         drop false  exit       ( failed )
1661986fd29aSsetje      then                      ( off )
1662986fd29aSsetje      dup  file-offset!  true   ( off succeeded )
1663986fd29aSsetje   ;
1664986fd29aSsetje
1665986fd29aSsetje   : read-file  ( adr len fd -- #read )
1666986fd29aSsetje      set-fd  if                   ( adr len )
1667986fd29aSsetje         2drop 0  exit             ( 0 )
1668986fd29aSsetje      then                         ( adr len )
1669986fd29aSsetje
1670986fd29aSsetje      \ adjust len if reading past eof
1671e7cbe64fSgw25295      dup  file-offset@ +  file-size  x>  if
1672986fd29aSsetje         dup  file-offset@ +  file-size -  -
1673986fd29aSsetje      then
1674986fd29aSsetje      dup 0=  if  nip exit  then
1675986fd29aSsetje
1676986fd29aSsetje      0 -rot                              ( #read adr len )
1677986fd29aSsetje
1678986fd29aSsetje      \ initial partial block
1679986fd29aSsetje      file-offset@ file-bsize  mod  ?dup  if  ( #read adr len off )
1680986fd29aSsetje         temp-space  file-bread
1681986fd29aSsetje         2dup  file-bsize  swap -  min    ( #read adr len off cpy-len )
1682986fd29aSsetje         2over drop -rot                  ( #read adr len adr off cpy-len )
1683986fd29aSsetje         >r  temp-space +  swap           ( #read adr len cpy-src adr  r: cpy-len )
1684986fd29aSsetje         r@  move  r> fio+                ( #read' adr' len' )
1685986fd29aSsetje      then                                ( #read adr len )
1686986fd29aSsetje
1687986fd29aSsetje      dup file-bsize /  0  ?do            ( #read adr len )
1688986fd29aSsetje         over  file-bread
1689986fd29aSsetje         file-bsize fio+                  ( #read' adr' len' )
1690986fd29aSsetje      loop                                ( #read adr len )
1691986fd29aSsetje
1692986fd29aSsetje      \ final partial block
1693986fd29aSsetje      dup  if                             ( #read adr len )
1694986fd29aSsetje         temp-space  file-bread
1695986fd29aSsetje         2dup temp-space -rot  move       ( #read adr len )
1696986fd29aSsetje         dup fio+                         ( #read' adr' 0 )
1697986fd29aSsetje      then  2drop                         ( #read )
1698986fd29aSsetje   ;
1699986fd29aSsetje
1700986fd29aSsetje   : cinfo-file  ( fd -- bsize fsize comp? )
1701986fd29aSsetje      set-fd  if
1702986fd29aSsetje         0 0 0
1703986fd29aSsetje      else
1704986fd29aSsetje         file-bsize  file-size             ( bsize fsize )
1705986fd29aSsetje         \ zfs does internal compression
1706986fd29aSsetje         0                                 ( bsize fsize comp? )
1707986fd29aSsetje      then
1708986fd29aSsetje   ;
1709986fd29aSsetje
1710986fd29aSsetje   \ read ramdisk fcode at rd-offset
1711986fd29aSsetje   : get-rd   ( adr len -- )
1712986fd29aSsetje      rd-offset dev-ih  read-disk
1713986fd29aSsetje   ;
1714986fd29aSsetje
1715986fd29aSsetje   : bootprop
1716986fd29aSsetje      " /"  bootprop$  $append
1717986fd29aSsetje      bootfs-obj# (xu.)  bootprop$  $append
1718986fd29aSsetje      bootprop$  encode-string  " zfs-bootfs"   ( propval propname )
1719986fd29aSsetje      true
1720986fd29aSsetje   ;
1721986fd29aSsetje
1722986fd29aSsetje
1723986fd29aSsetje   : chdir  ( dir$ -- )
1724986fd29aSsetje      current-obj# -rot            ( obj# dir$ )
1725986fd29aSsetje      lookup  if                   ( obj# )
1726986fd29aSsetje         to current-obj#           (  )
1727986fd29aSsetje         ." no such dir" cr  exit
1728986fd29aSsetje      then                         ( obj# )
1729986fd29aSsetje      dnode dir?  0=  if           ( obj# )
1730986fd29aSsetje         to current-obj#           (  )
1731986fd29aSsetje         ." not a dir" cr  exit
1732986fd29aSsetje      then  drop                   (  )
1733986fd29aSsetje   ;
1734986fd29aSsetje
1735986fd29aSsetje   : dir  ( -- )
1736986fd29aSsetje      current-obj# get-fs-dnode
1737986fd29aSsetje      dnode zap-print
1738986fd29aSsetje   ;
1739986fd29aSsetje
1740986fd29aSsetjefinish-device
1741986fd29aSsetjepop-package
1742