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