15648Ssetje\ 25648Ssetje\ CDDL HEADER START 35648Ssetje\ 45648Ssetje\ The contents of this file are subject to the terms of the 55648Ssetje\ Common Development and Distribution License (the "License"). 65648Ssetje\ You may not use this file except in compliance with the License. 75648Ssetje\ 85648Ssetje\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95648Ssetje\ or http://www.opensolaris.org/os/licensing. 105648Ssetje\ See the License for the specific language governing permissions 115648Ssetje\ and limitations under the License. 125648Ssetje\ 135648Ssetje\ When distributing Covered Code, include this CDDL HEADER in each 145648Ssetje\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155648Ssetje\ If applicable, add the following below this CDDL HEADER, with the 165648Ssetje\ fields enclosed by brackets "[]" replaced with your own identifying 175648Ssetje\ information: Portions Copyright [yyyy] [name of copyright owner] 185648Ssetje\ 195648Ssetje\ CDDL HEADER END 205648Ssetje\ 215648Ssetje\ 22*11935SMark.Shellenbaum@Sun.COM\ Copyright 2010 Sun Microsystems, Inc. All rights reserved. 239941SJohn.Johnson@Sun.COM\ Use is subject to license terms. 249941SJohn.Johnson@Sun.COM\ 255648Ssetje 265648Ssetje 275648Ssetjepurpose: ZFS file system support package 28*11935SMark.Shellenbaum@Sun.COMcopyright: Copyright 2010 Sun Microsystems, Inc. All Rights Reserved 295648Ssetje 305648Ssetje" /packages" get-package push-package 315648Ssetje 325648Ssetjenew-device 335648Ssetje fs-pkg$ device-name diag-cr? 345648Ssetje 355648Ssetje 0 instance value temp-space 365648Ssetje 375648Ssetje 385648Ssetje \ 64b ops 395648Ssetje \ fcode is still 32b on 64b sparc-v9, so 405648Ssetje \ we need to override some arithmetic ops 415648Ssetje \ stack ops and logical ops (dup, and, etc) are 64b 425648Ssetje : xcmp ( x1 x2 -- -1|0|1 ) 435648Ssetje xlsplit rot xlsplit ( x2.lo x2.hi x1.lo x1.hi ) 446423Sgw25295 rot 2dup u< if ( x2.lo x1.lo x1.hi x2.hi ) 455648Ssetje 2drop 2drop -1 ( lt ) 466423Sgw25295 else u> if ( x2.lo x1.lo ) 475648Ssetje 2drop 1 ( gt ) 486423Sgw25295 else swap 2dup u< if ( x1.lo x2.lo ) 495648Ssetje 2drop -1 ( lt ) 506423Sgw25295 else u> if ( ) 515648Ssetje 1 ( gt ) 525648Ssetje else ( ) 535648Ssetje 0 ( eq ) 545648Ssetje then then then then ( -1|0|1 ) 555648Ssetje ; 565648Ssetje : x< ( x1 x2 -- <? ) xcmp -1 = ; 575648Ssetje : x> ( x1 x2 -- >? ) xcmp 1 = ; 585648Ssetje\ : x= ( x1 x2 -- =? ) xcmp 0= ; 595648Ssetje : x<> ( x1 x2 -- <>? ) xcmp 0<> ; 605648Ssetje : x0= ( x -- 0=? ) xlsplit 0= swap 0= and ; 615648Ssetje 625648Ssetje /buf-len instance buffer: numbuf 635648Ssetje 645648Ssetje : (xu.) ( u -- u$ ) 655648Ssetje numbuf /buf-len + swap ( adr u ) 665648Ssetje begin 675648Ssetje d# 10 /mod swap ( adr u' rem ) 685648Ssetje ascii 0 + ( adr u' c ) 695648Ssetje rot 1- tuck c! ( u adr' ) 705648Ssetje swap dup 0= ( adr u done? ) 715648Ssetje until drop ( adr ) 725648Ssetje dup numbuf - /buf-len swap - ( adr len ) 735648Ssetje ; 745648Ssetje 755648Ssetje \ pool name 765648Ssetje /buf-len instance buffer: bootprop-buf 775648Ssetje : bootprop$ ( -- prop$ ) bootprop-buf cscount ; 785648Ssetje 795648Ssetje \ decompression 805648Ssetje \ 815648Ssetje \ uts/common/os/compress.c has a definitive theory of operation comment 825648Ssetje \ on lzjb, but here's the reader's digest version: 835648Ssetje \ 845648Ssetje \ repeated phrases are replaced by referenced to the original 855648Ssetje \ e.g., 865648Ssetje \ 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 875648Ssetje \ becomes 885648Ssetje \ y a d d a _ 6 11 , _ b l a h 5 10 895648Ssetje \ where 6 11 means memmove(ptr, ptr - 6, 11) 905648Ssetje \ 915648Ssetje \ data is separated from metadata with embedded copymap entries 925648Ssetje \ every 8 items e.g., 935648Ssetje \ 0x40 y a d d a _ 6 11 , 0x20 _ b l a h 5 10 945648Ssetje \ the copymap has a set bit for copy refercences 955648Ssetje \ and a clear bit for bytes to be copied directly 965648Ssetje \ 975648Ssetje \ the reference marks are encoded with match-bits and match-min 985648Ssetje \ e.g., 995648Ssetje \ byte[0] = ((mlen - MATCH_MIN) << (NBBY - MATCH_BITS) | (off >> NBBY) 1005648Ssetje \ byte[1] = (uint8_t)off 1015648Ssetje \ 1025648Ssetje 1035648Ssetje : pow2 ( n -- 2**n ) 1 swap lshift ; 1045648Ssetje 1055648Ssetje \ assume MATCH_BITS=6 and MATCH_MIN=3 1065648Ssetje 6 constant mbits 1075648Ssetje 3 constant mmin 1085648Ssetje 8 mbits - constant mshift 1095648Ssetje d# 16 mbits - pow2 1- constant mmask 1105648Ssetje 1115648Ssetje : decode-src ( src -- mlen off ) 1125648Ssetje dup c@ swap 1+ c@ ( c[0] c[1] ) 1135648Ssetje over mshift rshift mmin + ( c[0] c[1] mlen ) 1145648Ssetje -rot swap bwjoin mmask and ( mlen off ) 1155648Ssetje ; 1165648Ssetje 1175648Ssetje \ equivalent of memmove(dst, dst - off, len) 1185648Ssetje \ src points to a copy reference to be decoded 1195648Ssetje : mcopy ( dend dst src -- dend dst' ) 1205648Ssetje decode-src ( dend dst mlen off ) 1215648Ssetje 2 pick swap - >r ( dent dst mlen r: cpy ) 1225648Ssetje begin 1235648Ssetje 1- dup 0>= ( dend dst mlen' any? r: cpy ) 1245648Ssetje 2over > and ( dend dst mlen !done? r : cpy ) 1255648Ssetje while ( dend dst mlen r: cpy ) 1265648Ssetje swap r> dup 1+ >r c@ ( dend mlen dst c r: cpy' ) 1275648Ssetje over c! 1+ swap ( dend dst' mlen r: cpy ) 1285648Ssetje repeat ( dend dst' mlen r: cpy ) 1295648Ssetje r> 2drop ( dend dst ) 1305648Ssetje ; 1315648Ssetje 1325648Ssetje 1335648Ssetje : lzjb ( src dst len -- ) 1345648Ssetje over + swap ( src dend dst ) 1355648Ssetje rot >r ( dend dst r: src ) 1365648Ssetje 1375648Ssetje \ setup mask so 1st while iteration fills map 1385648Ssetje 0 7 pow2 2swap ( map mask dend dst r: src ) 1395648Ssetje 1405648Ssetje begin 2dup > while 1415648Ssetje 2swap 1 lshift ( dend dst map mask' r: src ) 1425648Ssetje 1435648Ssetje dup 8 pow2 = if 1445648Ssetje \ fetch next copymap 1455648Ssetje 2drop ( dend dst r: src ) 1465648Ssetje r> dup 1+ >r c@ 1 ( dend dst map' mask' r: src' ) 1475648Ssetje then ( dend dst map mask r: src' ) 1485648Ssetje 1495648Ssetje \ if (map & mask) we hit a copy reference 1505648Ssetje \ else just copy 1 byte 1515648Ssetje 2swap 2over and if ( map mask dend dst r: src ) 1525648Ssetje r> dup 2+ >r ( map mask dend dst src r: src' ) 1535648Ssetje mcopy ( map mask dend dst' r: src ) 1545648Ssetje else 1555648Ssetje r> dup 1+ >r c@ ( map mask dend dst c r: src' ) 1565648Ssetje over c! 1+ ( map mask dend dst' r: src ) 1575648Ssetje then 1585648Ssetje repeat ( map mask dend dst r: src ) 1595648Ssetje 2drop 2drop r> drop ( ) 1605648Ssetje ; 1615648Ssetje 1625648Ssetje 1635648Ssetje \ 1645648Ssetje \ ZFS block (SPA) routines 1655648Ssetje \ 1665648Ssetje 1679941SJohn.Johnson@Sun.COM 1 constant def-comp# 1685648Ssetje 2 constant no-comp# 1699941SJohn.Johnson@Sun.COM 3 constant lzjb-comp# 1709941SJohn.Johnson@Sun.COM 1715648Ssetje h# 2.0000 constant /max-bsize 1725648Ssetje d# 512 constant /disk-block 1735648Ssetje d# 128 constant /blkp 1745648Ssetje 1759941SJohn.Johnson@Sun.COM alias /gang-block /disk-block 1769941SJohn.Johnson@Sun.COM 1779941SJohn.Johnson@Sun.COM \ the ending checksum is larger than 1 byte, but that 1789941SJohn.Johnson@Sun.COM \ doesn't affect the math here 1799941SJohn.Johnson@Sun.COM /gang-block 1- 1809941SJohn.Johnson@Sun.COM /blkp / constant #blks/gang 1819941SJohn.Johnson@Sun.COM 1829941SJohn.Johnson@Sun.COM : blk_offset ( bp -- n ) h# 8 + x@ -1 h# 7fff.ffff lxjoin and ; 1835648Ssetje : blk_gang ( bp -- n ) h# 8 + x@ xlsplit nip d# 31 rshift ; 1845648Ssetje : blk_comp ( bp -- n ) h# 33 + c@ ; 1855648Ssetje : blk_psize ( bp -- n ) h# 34 + w@ ; 1865648Ssetje : blk_lsize ( bp -- n ) h# 36 + w@ ; 1875648Ssetje : blk_birth ( bp -- n ) h# 50 + x@ ; 1885648Ssetje 1895648Ssetje 0 instance value dev-ih 1905648Ssetje 0 instance value blk-space 1915648Ssetje 0 instance value gang-space 1925648Ssetje 1935648Ssetje : foff>doff ( fs-off -- disk-off ) /disk-block * h# 40.0000 + ; 1945648Ssetje : fsz>dsz ( fs-size -- disk-size ) 1+ /disk-block * ; 1955648Ssetje 1965648Ssetje : bp-dsize ( bp -- dsize ) blk_psize fsz>dsz ; 1975648Ssetje : bp-lsize ( bp -- lsize ) blk_lsize fsz>dsz ; 1985648Ssetje 1999941SJohn.Johnson@Sun.COM : (read-dva) ( adr len dva -- ) 2005648Ssetje blk_offset foff>doff dev-ih read-disk 2015648Ssetje ; 2025648Ssetje 2039941SJohn.Johnson@Sun.COM : gang-read ( adr len bp gb-adr -- ) tokenizer[ reveal ]tokenizer 2045648Ssetje 2055648Ssetje \ read gang block 2069941SJohn.Johnson@Sun.COM tuck /gang-block rot (read-dva) ( adr len gb-adr ) 2079941SJohn.Johnson@Sun.COM 2089941SJohn.Johnson@Sun.COM \ loop through indirected bp's 2099941SJohn.Johnson@Sun.COM dup /blkp #blks/gang * ( adr len gb-adr bp-list bp-list-len ) 2109941SJohn.Johnson@Sun.COM bounds do ( adr len gb-adr ) 2119941SJohn.Johnson@Sun.COM i blk_offset x0= ?leave 2129941SJohn.Johnson@Sun.COM 2139941SJohn.Johnson@Sun.COM \ calc subordinate read len 2149941SJohn.Johnson@Sun.COM over i bp-dsize min ( adr len gb-adr sub-len ) 2159941SJohn.Johnson@Sun.COM 2swap swap ( gb-adr sub-len len adr ) 2165648Ssetje 2179941SJohn.Johnson@Sun.COM \ nested gang block - recurse with new gang block area 2189941SJohn.Johnson@Sun.COM i blk_gang if 2199941SJohn.Johnson@Sun.COM 2swap ( len adr gb-adr sub-len ) 2209941SJohn.Johnson@Sun.COM 3dup swap /gang-block + ( len adr gb-adr sub-len adr sub-len gb-adr' ) 2219941SJohn.Johnson@Sun.COM i swap gang-read ( len adr gb-adr sub-len ) 2229941SJohn.Johnson@Sun.COM 2swap ( gb-adr sub-len len adr ) 2239941SJohn.Johnson@Sun.COM else 2249941SJohn.Johnson@Sun.COM 3dup nip swap ( gb-adr sub-len len adr adr sub-len ) 2259941SJohn.Johnson@Sun.COM i (read-dva) ( gb-adr sub-len len adr ) 2269941SJohn.Johnson@Sun.COM then ( gb-adr sub-len len adr ) 2279941SJohn.Johnson@Sun.COM 2289941SJohn.Johnson@Sun.COM \ adjust adr,len and check if done 2299941SJohn.Johnson@Sun.COM -rot over - ( gb-adr adr sub-len len' ) 2309941SJohn.Johnson@Sun.COM -rot + swap ( gb-adr adr' len' ) 2319941SJohn.Johnson@Sun.COM dup 0= ?leave 2329941SJohn.Johnson@Sun.COM rot ( adr' len' gb-adr ) 2335648Ssetje /blkp +loop 2349941SJohn.Johnson@Sun.COM 3drop ( ) 2359941SJohn.Johnson@Sun.COM ; 2369941SJohn.Johnson@Sun.COM 2379941SJohn.Johnson@Sun.COM : read-dva ( adr len dva -- ) 2389941SJohn.Johnson@Sun.COM dup blk_gang if 2399941SJohn.Johnson@Sun.COM gang-space gang-read 2409941SJohn.Johnson@Sun.COM else 2419941SJohn.Johnson@Sun.COM (read-dva) 2429941SJohn.Johnson@Sun.COM then 2435648Ssetje ; 2445648Ssetje 2455648Ssetje \ block read that check for holes, gangs, compression, etc 2465648Ssetje : read-bp ( adr len bp -- ) 2475648Ssetje \ sparse block? 2485648Ssetje dup blk_birth x0= if 2499941SJohn.Johnson@Sun.COM drop erase exit ( ) 2505648Ssetje then 2519941SJohn.Johnson@Sun.COM 2529941SJohn.Johnson@Sun.COM \ no compression? 2539941SJohn.Johnson@Sun.COM dup blk_comp no-comp# = if 2549941SJohn.Johnson@Sun.COM read-dva exit ( ) 2555648Ssetje then 2569941SJohn.Johnson@Sun.COM 2579941SJohn.Johnson@Sun.COM \ only do lzjb 2589941SJohn.Johnson@Sun.COM dup blk_comp dup lzjb-comp# <> ( adr len bp comp lzjb? ) 2599941SJohn.Johnson@Sun.COM swap def-comp# <> and if ( adr len bp ) 2609941SJohn.Johnson@Sun.COM " only lzjb supported" die 2615648Ssetje then 2629941SJohn.Johnson@Sun.COM 2639941SJohn.Johnson@Sun.COM \ read into blk-space and de-compress 2649941SJohn.Johnson@Sun.COM blk-space over bp-dsize ( adr len bp blk-adr rd-len ) 2659941SJohn.Johnson@Sun.COM rot read-dva ( adr len ) 2669941SJohn.Johnson@Sun.COM blk-space -rot lzjb ( ) 2675648Ssetje ; 2685648Ssetje 2695648Ssetje \ 2705648Ssetje \ ZFS vdev routines 2715648Ssetje \ 2725648Ssetje 2735648Ssetje h# 1.c000 constant /nvpairs 2745648Ssetje h# 4000 constant nvpairs-off 2755648Ssetje 2765648Ssetje \ 2775648Ssetje \ xdr packed nvlist 2785648Ssetje \ 2795648Ssetje \ 12B header 2805648Ssetje \ array of xdr packed nvpairs 2815648Ssetje \ 4B encoded nvpair size 2825648Ssetje \ 4B decoded nvpair size 2835648Ssetje \ 4B name string size 2845648Ssetje \ name string 2855648Ssetje \ 4B data type 2865648Ssetje \ 4B # of data elements 2875648Ssetje \ data 2885648Ssetje \ 8B of 0 2895648Ssetje \ 2905648Ssetje d# 12 constant /nvhead 2915648Ssetje 2925648Ssetje : >nvsize ( nv -- size ) l@ ; 2935648Ssetje : >nvname ( nv -- name$ ) 2945648Ssetje /l 2* + dup /l + swap l@ 2955648Ssetje ; 2965648Ssetje : >nvdata ( nv -- data ) 2975648Ssetje >nvname + /l roundup 2985648Ssetje ; 2996423Sgw25295 3006423Sgw25295 \ convert nvdata to 64b int or string 3016423Sgw25295 : nvdata>x ( nvdata -- x ) 3026423Sgw25295 /l 2* + ( ptr ) 3036423Sgw25295 dup /l + l@ swap l@ ( x.lo x.hi ) 3046423Sgw25295 lxjoin ( x ) 3056423Sgw25295 ; 3065648Ssetje alias nvdata>$ >nvname 3075648Ssetje 3085648Ssetje : nv-lookup ( nv name$ -- nvdata false | true ) 3095648Ssetje rot /nvhead + ( name$ nvpair ) 3105648Ssetje begin dup >nvsize while 3115648Ssetje dup >r >nvname ( name$ nvname$ r: nvpair ) 3125648Ssetje 2over $= if ( name$ r: nvpair ) 3135648Ssetje 2drop r> >nvdata ( nvdata ) 3145648Ssetje false exit ( nvdata found ) 3155648Ssetje then ( name$ r: nvpair ) 3165648Ssetje r> dup >nvsize + ( name$ nvpair' ) 3175648Ssetje repeat 3185648Ssetje 3drop true ( not-found ) 3195648Ssetje ; 3205648Ssetje 3215648Ssetje : scan-vdev ( -- ) 3225648Ssetje temp-space /nvpairs nvpairs-off ( adr len off ) 3235648Ssetje dev-ih read-disk ( ) 3246423Sgw25295 temp-space " txg" nv-lookup if 3256423Sgw25295 " no txg nvpair" die 3266423Sgw25295 then nvdata>x ( txg ) 3276423Sgw25295 x0= if 3286423Sgw25295 " detached mirror" die 3296423Sgw25295 then ( ) 3305648Ssetje temp-space " name" nv-lookup if 3316423Sgw25295 " no name nvpair" die 3325648Ssetje then nvdata>$ ( pool$ ) 3335648Ssetje bootprop-buf swap move ( ) 3345648Ssetje ; 3355648Ssetje 3365648Ssetje 3375648Ssetje \ 3385648Ssetje \ ZFS ueber-block routines 3395648Ssetje \ 3405648Ssetje 3415648Ssetje d# 1024 constant /uber-block 3425648Ssetje d# 128 constant #ub/label 3435648Ssetje #ub/label /uber-block * constant /ub-ring 3445648Ssetje h# 2.0000 constant ubring-off 3455648Ssetje 3465648Ssetje : ub_magic ( ub -- n ) x@ ; 3475648Ssetje : ub_txg ( ub -- n ) h# 10 + x@ ; 3485648Ssetje : ub_timestamp ( ub -- n ) h# 20 + x@ ; 3495648Ssetje : ub_rootbp ( ub -- p ) h# 28 + ; 3505648Ssetje 3515648Ssetje 0 instance value uber-block 3525648Ssetje 3535648Ssetje : ub-cmp ( ub1 ub2 -- best-ub ) 3545648Ssetje 3555648Ssetje \ ub1 wins if ub2 isn't valid 3565648Ssetje dup ub_magic h# 00bab10c x<> if 3575648Ssetje drop exit ( ub1 ) 3585648Ssetje then 3595648Ssetje 3605648Ssetje \ if ub1 is 0, ub2 wins by default 3615648Ssetje over 0= if nip exit then ( ub2 ) 3625648Ssetje 3635648Ssetje \ 2 valid ubs, compare transaction groups 3645648Ssetje over ub_txg over ub_txg ( ub1 ub2 txg1 txg2 ) 3655648Ssetje 2dup x< if 3665648Ssetje 2drop nip exit ( ub2 ) 3675648Ssetje then ( ub1 ub2 txg1 txg2 ) 3685648Ssetje x> if drop exit then ( ub1 ) 3695648Ssetje 3705648Ssetje \ same txg, check timestamps 3715648Ssetje over ub_timestamp over ub_timestamp x> if 3725648Ssetje nip ( ub2 ) 3735648Ssetje else 3745648Ssetje drop ( ub1 ) 3755648Ssetje then 3765648Ssetje ; 3775648Ssetje 3785648Ssetje \ find best uber-block in ring, and copy it to uber-block 3795648Ssetje : get-ub ( -- ) 3805648Ssetje temp-space /ub-ring ubring-off ( adr len off ) 3815648Ssetje dev-ih read-disk ( ) 3825648Ssetje 0 temp-space /ub-ring ( null-ub adr len ) 3835648Ssetje bounds do ( ub ) 3845648Ssetje i ub-cmp ( best-ub ) 3855648Ssetje /uber-block +loop 3865648Ssetje 3875648Ssetje \ make sure we found a valid ub 3886423Sgw25295 dup 0= if " no ub found" die then 3895648Ssetje 3905648Ssetje uber-block /uber-block move ( ) 3915648Ssetje ; 3925648Ssetje 3935648Ssetje 3945648Ssetje \ 3955648Ssetje \ ZFS dnode (DMU) routines 3965648Ssetje \ 3975648Ssetje 398*11935SMark.Shellenbaum@Sun.COM d# 44 constant ot-sa# 399*11935SMark.Shellenbaum@Sun.COM 4005648Ssetje d# 512 constant /dnode 4015648Ssetje 402*11935SMark.Shellenbaum@Sun.COM : dn_indblkshift ( dn -- n ) h# 1 + c@ ; 403*11935SMark.Shellenbaum@Sun.COM : dn_nlevels ( dn -- n ) h# 2 + c@ ; 404*11935SMark.Shellenbaum@Sun.COM : dn_bonustype ( dn -- n ) h# 4 + c@ ; 405*11935SMark.Shellenbaum@Sun.COM : dn_datablkszsec ( dn -- n ) h# 8 + w@ ; 406*11935SMark.Shellenbaum@Sun.COM : dn_bonuslen ( dn -- n ) h# a + w@ ; 407*11935SMark.Shellenbaum@Sun.COM : dn_blkptr ( dn -- p ) h# 40 + ; 408*11935SMark.Shellenbaum@Sun.COM : dn_bonus ( dn -- p ) h# c0 + ; 409*11935SMark.Shellenbaum@Sun.COM : dn_spill ( dn -- p ) h# 180 + ; 4105648Ssetje 4115648Ssetje 0 instance value dnode 4125648Ssetje 4135648Ssetje \ indirect cache 4145648Ssetje \ 4155648Ssetje \ ind-cache is a 1 block indirect block cache from dnode ic-dn 4165648Ssetje \ 4175648Ssetje \ ic-bp and ic-bplim point into the ic-dn's block ptr array, 4185648Ssetje \ either in dn_blkptr or in ind-cache ic-bp is the ic-blk#'th 4195648Ssetje \ block ptr, and ic-bplim is limit of the current bp array 4205648Ssetje \ 4215648Ssetje \ the assumption is that reads will be sequential, so we can 4225648Ssetje \ just increment ic-bp 4235648Ssetje \ 4245648Ssetje 0 instance value ind-cache 4255648Ssetje 0 instance value ic-dn 4265648Ssetje 0 instance value ic-blk# 4275648Ssetje 0 instance value ic-bp 4285648Ssetje 0 instance value ic-bplim 4295648Ssetje 4305648Ssetje : dn-bsize ( dn -- bsize ) dn_datablkszsec /disk-block * ; 4315648Ssetje : dn-indsize ( dn -- indsize ) dn_indblkshift pow2 ; 4325648Ssetje : dn-indmask ( dn -- mask ) dn-indsize 1- ; 4335648Ssetje 4345648Ssetje \ recursively climb the block tree from the leaf to the root 4355648Ssetje : blk@lvl>bp ( dn blk# lvl -- bp ) tokenizer[ reveal ]tokenizer 4365648Ssetje >r /blkp * over dn_nlevels ( dn bp-off #lvls r: lvl ) 4375648Ssetje 4385648Ssetje \ at top, just add dn_blkptr 4395648Ssetje r@ = if ( dn bp-off r: lvl ) 4405648Ssetje swap dn_blkptr + ( bp r: lvl ) 4415648Ssetje r> drop exit ( bp ) 4425648Ssetje then ( dn bp-off r: lvl ) 4435648Ssetje 4445648Ssetje \ shift bp-off down and find parent indir blk 4455648Ssetje 2dup over dn_indblkshift rshift ( dn bp-off dn blk# r: lvl ) 4465648Ssetje r> 1+ blk@lvl>bp ( dn bp-off bp ) 4475648Ssetje 4486423Sgw25295 \ read parent indir blk and index 4495648Ssetje rot tuck dn-indsize ( bp-off dn bp len ) 4505648Ssetje ind-cache swap rot read-bp ( bp-off dn ) 4515648Ssetje dn-indmask and ( bp-off' ) 4525648Ssetje ind-cache + ( bp ) 4535648Ssetje ; 4545648Ssetje 4555648Ssetje \ return end of current bp array 4565648Ssetje : bplim ( dn bp -- bp-lim ) 4575648Ssetje over dn_nlevels 1 = if 4585648Ssetje drop dn_blkptr ( bp0 ) 4595648Ssetje 3 /blkp * + ( bplim ) 4605648Ssetje else 4615648Ssetje 1+ swap dn-indsize ( bp+1 indsz ) 4625648Ssetje roundup ( bplim ) 4635648Ssetje then 4645648Ssetje ; 4655648Ssetje 4665648Ssetje \ return the lblk#'th block ptr from dnode 4675648Ssetje : lblk#>bp ( dn blk# -- bp ) 4685648Ssetje 2dup ( dn blk# dn blk# ) 4695648Ssetje ic-blk# <> swap ic-dn <> or ( dn blk# cache-miss? ) 4705648Ssetje ic-bp ic-bplim = ( dn blk# cache-miss? cache-empty? ) 4715648Ssetje or if ( dn blk# ) 4725648Ssetje 2dup 1 blk@lvl>bp ( dn blk# bp ) 4735648Ssetje dup to ic-bp ( dn blk# bp ) 4745648Ssetje swap to ic-blk# ( dn bp ) 4755648Ssetje 2dup bplim to ic-bplim ( dn bp ) 4765648Ssetje over to ic-dn 4775648Ssetje then 2drop ( ) 4785648Ssetje ic-blk# 1+ to ic-blk# 4795648Ssetje ic-bp dup /blkp + to ic-bp ( bp ) 4805648Ssetje ; 4815648Ssetje 4825648Ssetje 4835648Ssetje \ 4845648Ssetje \ ZFS attribute (ZAP) routines 4855648Ssetje \ 4865648Ssetje 4875648Ssetje 1 constant fzap# 4885648Ssetje 3 constant uzap# 4895648Ssetje 4905648Ssetje d# 64 constant /uzap 4915648Ssetje 4925648Ssetje d# 24 constant /lf-chunk 4935648Ssetje d# 21 constant /lf-arr 4945648Ssetje h# ffff constant chain-end# 4955648Ssetje 4965648Ssetje h# 100 constant /lf-buf 4975648Ssetje /lf-buf instance buffer: leaf-value 4985648Ssetje /lf-buf instance buffer: leaf-name 4995648Ssetje 5005648Ssetje : +le ( len off -- n ) + w@ ; 5015648Ssetje : le_next ( le -- n ) h# 2 +le ; 5025648Ssetje : le_name_chunk ( le -- n ) h# 4 +le ; 5035648Ssetje : le_name_length ( le -- n ) h# 6 +le ; 5045648Ssetje : le_value_chunk ( le -- n ) h# 8 +le ; 5055648Ssetje : le_value_length ( le -- n ) h# a +le ; 5065648Ssetje 5075648Ssetje : la_array ( la -- adr ) 1+ ; 5085648Ssetje : la_next ( la -- n ) h# 16 + w@ ; 5095648Ssetje 5105648Ssetje 0 instance value zap-space 5115648Ssetje 5125648Ssetje \ setup leaf hash bounds 5135648Ssetje : >leaf-hash ( dn lh -- hash-adr /hash ) 5145648Ssetje /lf-chunk 2* + ( dn hash-adr ) 5155648Ssetje \ size = (bsize / 32) * 2 5165648Ssetje swap dn-bsize 4 rshift ( hash-adr /hash ) 5175648Ssetje ; 5185648Ssetje : >leaf-chunks ( lf -- ch0 ) >leaf-hash + ; 5195648Ssetje 5205648Ssetje \ convert chunk # to leaf chunk 5215648Ssetje : ch#>lc ( dn ch# -- lc ) 5225648Ssetje /lf-chunk * ( dn lc-off ) 5235648Ssetje swap zap-space >leaf-chunks ( lc-off ch0 ) 5245648Ssetje + ( lc ) 5255648Ssetje ; 5265648Ssetje 5275648Ssetje \ assemble chunk chain into single buffer 5285648Ssetje : get-chunk-data ( dn ch# adr -- ) 5295648Ssetje dup >r /lf-buf erase ( dn ch# r: adr ) 5305648Ssetje begin 5315648Ssetje 2dup ch#>lc nip ( dn la r: adr ) 5325648Ssetje dup la_array ( dn la la-arr r: adr ) 5335648Ssetje r@ /lf-arr move ( dn la r: adr ) 5345648Ssetje r> /lf-arr + >r ( dn la r: adr' ) 5355648Ssetje la_next dup chain-end# = ( dn la-ch# end? r: adr ) 5365648Ssetje until r> 3drop ( ) 5375648Ssetje ; 5385648Ssetje 5395648Ssetje \ get leaf entry's name 5405648Ssetje : entry-name$ ( dn le -- name$ ) 5415648Ssetje 2dup le_name_chunk ( dn le dn la-ch# ) 5425648Ssetje leaf-name get-chunk-data ( dn le ) 5436490Sjgj nip le_name_length 1- ( len ) 5445648Ssetje leaf-name swap ( name$ ) 5455648Ssetje ; 5465648Ssetje 5475648Ssetje \ return entry value as int 5485648Ssetje : entry-int-val ( dn le -- n ) 5495648Ssetje le_value_chunk ( dn la-ch# ) 5505648Ssetje leaf-value get-chunk-data ( ) 5515648Ssetje leaf-value x@ ( n ) 5525648Ssetje ; 5535648Ssetje 5545648Ssetje 5555648Ssetje[ifdef] strlookup 5565648Ssetje \ get leaf entry's value as string 5575648Ssetje : entry-val$ ( dn le -- val$ ) 5585648Ssetje 2dup le_value_chunk ( dn le dn la-ch# ) 5595648Ssetje leaf-value get-chunk-data ( dn le ) 5605648Ssetje nip le_value_length ( len ) 5615648Ssetje leaf-value swap ( name$ ) 5625648Ssetje ; 5635648Ssetje[then] 5645648Ssetje 5655648Ssetje \ apply xt to entry 5665648Ssetje : entry-apply ( xt dn le -- xt dn false | ??? true ) 5675648Ssetje over >r ( xt dn le r: dn ) 5685648Ssetje rot dup >r execute if ( ??? r: xt dn ) 5695648Ssetje r> r> 2drop true ( ??? true ) 5705648Ssetje else ( ) 5715648Ssetje r> r> false ( xt dn false ) 5725648Ssetje then 5735648Ssetje ; 5745648Ssetje 5755648Ssetje \ apply xt to every entry in chain 5765648Ssetje : chain-apply ( xt dn ch# -- xt dn false | ??? true ) 5775648Ssetje begin 5785648Ssetje 2dup ch#>lc nip ( xt dn le ) 5795648Ssetje dup >r entry-apply if ( ??? r: le ) 5805648Ssetje r> drop true exit ( ??? found ) 5815648Ssetje then ( xt dn r: le ) 5825648Ssetje r> le_next ( xt dn ch# ) 5835648Ssetje dup chain-end# = ( xt dn ch# end? ) 5845648Ssetje until drop ( xt dn ) 5855648Ssetje false ( xt dn false ) 5865648Ssetje ; 5875648Ssetje 5885648Ssetje \ apply xt to every entry in leaf 5895648Ssetje : leaf-apply ( xt dn blk# -- xt dn false | ??? true ) 5905648Ssetje 5915648Ssetje \ read zap leaf into zap-space 5925648Ssetje 2dup lblk#>bp ( xt dn blk# bp ) 5935648Ssetje nip over dn-bsize zap-space ( xt dn bp len adr ) 5945648Ssetje swap rot read-bp ( xt dn ) 5955648Ssetje 5965648Ssetje \ call chunk-look for every valid chunk list 5975648Ssetje dup zap-space >leaf-hash ( xt dn hash-adr /hash ) 5985648Ssetje bounds do ( xt dn ) 5995648Ssetje i w@ dup chain-end# <> if ( xt dn ch# ) 6005648Ssetje chain-apply if ( ??? ) 6015648Ssetje unloop true exit ( ??? found ) 6025648Ssetje then ( xt dn ) 6035648Ssetje else drop then ( xt dn ) 6045648Ssetje /w +loop 6055648Ssetje false ( xt dn not-found ) 6065648Ssetje ; 6075648Ssetje 6085648Ssetje \ apply xt to every entry in fzap 6095648Ssetje : fzap-apply ( xt dn fz -- ??? not-found? ) 6105648Ssetje 6115648Ssetje \ blk# 1 is always the 1st leaf 6125648Ssetje >r 1 leaf-apply if ( ??? r: fz ) 6136490Sjgj r> drop true exit ( ??? found ) 6145648Ssetje then r> ( xt dn fz ) 6155648Ssetje 6165648Ssetje \ call leaf-apply on every non-duplicate hash entry 6175648Ssetje \ embedded hash is in 2nd half of fzap block 6185648Ssetje over dn-bsize tuck + ( xt dn bsize hash-eadr ) 6195648Ssetje swap 2dup 2/ - ( xt dn hash-eadr bsize hash-adr ) 6205648Ssetje nip do ( xt dn ) 6215648Ssetje i x@ dup 1 <> if ( xt dn blk# ) 6225648Ssetje leaf-apply if ( ??? ) 6235648Ssetje unloop true exit ( ??? found ) 6245648Ssetje then ( xt dn ) 6255648Ssetje else drop then ( xt dn ) 6265648Ssetje /x +loop 6275648Ssetje 2drop false ( not-found ) 6285648Ssetje ; 6295648Ssetje 6305648Ssetje : mze_value ( uz -- n ) x@ ; 6315648Ssetje : mze_name ( uz -- p ) h# e + ; 6325648Ssetje 6335648Ssetje : uzap-name$ ( uz -- name$ ) mze_name cscount ; 6345648Ssetje 6355648Ssetje \ apply xt to each entry in micro-zap 6365648Ssetje : uzap-apply ( xt uz len -- ??? not-found? ) 6375648Ssetje bounds do ( xt ) 6385648Ssetje i swap dup >r ( uz xt r: xt ) 6395648Ssetje execute if ( ??? r: xt ) 6405648Ssetje r> drop ( ??? ) 6415648Ssetje unloop true exit ( ??? found ) 6425648Ssetje then r> ( xt ) 6435648Ssetje /uzap +loop 6445648Ssetje drop false ( not-found ) 6455648Ssetje ; 6465648Ssetje 6475648Ssetje \ match by name 6485648Ssetje : fz-nmlook ( prop$ dn le -- prop$ false | prop$ dn le true ) 6495648Ssetje 2dup entry-name$ ( prop$ dn le name$ ) 6505648Ssetje 2rot 2swap ( dn le prop$ name$ ) 6515648Ssetje 2over $= if ( dn le prop$ ) 6525648Ssetje 2swap true ( prop$ dn le true ) 6535648Ssetje else ( dn le prop$ ) 6545648Ssetje 2swap 2drop false ( prop$ false ) 6555648Ssetje then ( prop$ false | prop$ dn le true ) 6565648Ssetje ; 6575648Ssetje 6585648Ssetje \ match by name 6595648Ssetje : uz-nmlook ( prop$ uz -- prop$ false | prop$ uz true ) 6605648Ssetje dup >r uzap-name$ ( prop$ name$ r: uz ) 6615648Ssetje 2over $= if ( prop$ r: uz ) 6625648Ssetje r> true ( prop$ uz true ) 6635648Ssetje else ( prop$ r: uz ) 6645648Ssetje r> drop false ( prop$ false ) 6655648Ssetje then ( prop$ false | prop$ uz true ) 6665648Ssetje ; 6675648Ssetje 6685648Ssetje : zap-type ( zp -- n ) h# 7 + c@ ; 6695648Ssetje : >uzap-ent ( adr -- ent ) h# 40 + ; 6705648Ssetje 6715648Ssetje \ read zap block into temp-space 6725648Ssetje : get-zap ( dn -- zp ) 6735648Ssetje dup 0 lblk#>bp ( dn bp ) 6745648Ssetje swap dn-bsize ( bp len ) 6755648Ssetje temp-space swap ( bp adr len ) 6765648Ssetje rot read-bp ( ) 6775648Ssetje temp-space ( zp ) 6785648Ssetje ; 6795648Ssetje 6805648Ssetje \ find prop in zap dnode 6815648Ssetje : zap-lookup ( dn prop$ -- [ n ] not-found? ) 6825648Ssetje rot dup get-zap ( prop$ dn zp ) 6835648Ssetje dup zap-type case 6845648Ssetje uzap# of 6855648Ssetje >uzap-ent swap dn-bsize ( prop$ uz len ) 6865648Ssetje ['] uz-nmlook -rot ( prop$ xt uz len ) 6875648Ssetje uzap-apply if ( prop$ uz ) 6885648Ssetje mze_value -rot 2drop ( n ) 6895648Ssetje false ( n found ) 6905648Ssetje else ( prop$ ) 6915648Ssetje 2drop true ( !found ) 6925648Ssetje then ( [ n ] not-found? ) 6935648Ssetje endof 6945648Ssetje fzap# of 6955648Ssetje ['] fz-nmlook -rot ( prop$ xt dn fz ) 6965648Ssetje fzap-apply if ( prop$ dn le ) 6975648Ssetje entry-int-val ( prop$ n ) 6985648Ssetje -rot 2drop false ( n found ) 6995648Ssetje else ( prop$ ) 7005648Ssetje 2drop true ( !found ) 7015648Ssetje then ( [ n ] not-found? ) 7025648Ssetje endof 7035648Ssetje 3drop 2drop true ( !found ) 7045648Ssetje endcase ( [ n ] not-found? ) 7055648Ssetje ; 7065648Ssetje 7075648Ssetje[ifdef] strlookup 7085648Ssetje : zap-lookup-str ( dn prop$ -- [ val$ ] not-found? ) 7095648Ssetje rot dup get-zap ( prop$ dn zp ) 7105648Ssetje dup zap-type fzap# <> if ( prop$ dn zp ) 7115648Ssetje 2drop 2drop true exit ( !found ) 7125648Ssetje then ( prop$ dn zp ) 7135648Ssetje ['] fz-nmlook -rot ( prop$ xt dn fz ) 7145648Ssetje fzap-apply if ( prop$ dn le ) 7155648Ssetje entry-val$ 2swap 2drop false ( val$ found ) 7165648Ssetje else ( prop$ ) 7175648Ssetje 2drop true ( !found ) 7185648Ssetje then ( [ val$ ] not-found? ) 7195648Ssetje ; 7205648Ssetje[then] 7215648Ssetje 7225648Ssetje : fz-print ( dn le -- false ) 7235648Ssetje entry-name$ type cr false 7245648Ssetje ; 7255648Ssetje 7265648Ssetje : uz-print ( uz -- false ) 7275648Ssetje uzap-name$ type cr false 7285648Ssetje ; 7295648Ssetje 7305648Ssetje : zap-print ( dn -- ) 7315648Ssetje dup get-zap ( dn zp ) 7325648Ssetje dup zap-type case 7335648Ssetje uzap# of 7345648Ssetje >uzap-ent swap dn-bsize ( uz len ) 7355648Ssetje ['] uz-print -rot ( xt uz len ) 7365648Ssetje uzap-apply ( false ) 7375648Ssetje endof 7385648Ssetje fzap# of 7395648Ssetje ['] fz-print -rot ( xt dn fz ) 7405648Ssetje fzap-apply ( false ) 7415648Ssetje endof 7425648Ssetje 3drop false ( false ) 7435648Ssetje endcase ( false ) 7445648Ssetje drop ( ) 7455648Ssetje ; 7465648Ssetje 7475648Ssetje 7485648Ssetje \ 7495648Ssetje \ ZFS object set (DSL) routines 7505648Ssetje \ 7515648Ssetje 7525648Ssetje 1 constant pool-dir# 7535648Ssetje 7545648Ssetje : dd_head_dataset_obj ( dd -- n ) h# 8 + x@ ; 7555648Ssetje : dd_child_dir_zapobj ( dd -- n ) h# 20 + x@ ; 7566423Sgw25295 7576423Sgw25295 : ds_snapnames_zapobj ( ds -- n ) h# 20 + x@ ; 7585648Ssetje : ds_bp ( ds -- p ) h# 80 + ; 7595648Ssetje 7605648Ssetje 0 instance value mos-dn 7615648Ssetje 0 instance value obj-dir 7625648Ssetje 0 instance value root-dsl 7635648Ssetje 0 instance value fs-dn 7645648Ssetje 7655648Ssetje \ dn-cache contains dc-dn's contents at dc-blk# 7665648Ssetje \ dc-dn will be either mos-dn or fs-dn 7675648Ssetje 0 instance value dn-cache 7685648Ssetje 0 instance value dc-dn 7695648Ssetje 0 instance value dc-blk# 7705648Ssetje 7715648Ssetje alias >dsl-dir dn_bonus 7725648Ssetje alias >dsl-ds dn_bonus 7735648Ssetje 7746423Sgw25295 : #dn/blk ( dn -- n ) dn-bsize /dnode / ; 7755648Ssetje 7765648Ssetje \ read block into dn-cache 7775648Ssetje : get-dnblk ( dn blk# -- ) 7785648Ssetje lblk#>bp dn-cache swap ( adr bp ) 7795648Ssetje dup bp-lsize swap read-bp ( ) 7805648Ssetje ; 7815648Ssetje 7825648Ssetje \ read obj# from objset dir dn into dnode 7835648Ssetje : get-dnode ( dn obj# -- ) 7845648Ssetje 7855648Ssetje \ check dn-cache 7865648Ssetje 2dup swap #dn/blk /mod ( dn obj# off# blk# ) 7875648Ssetje swap >r nip ( dn blk# r: off# ) 7885648Ssetje 2dup dc-blk# <> ( dn blk# dn !blk-hit? r: off# ) 7895648Ssetje swap dc-dn <> or if ( dn blk# r: off# ) 7905648Ssetje \ cache miss, fill from dir 7915648Ssetje 2dup get-dnblk 7925648Ssetje over to dc-dn 7935648Ssetje dup to dc-blk# 7945648Ssetje then ( dn blk# r: off# ) 7955648Ssetje 7965648Ssetje \ index and copy 7975648Ssetje 2drop r> /dnode * ( off ) 7985648Ssetje dn-cache + ( dn-adr ) 7995648Ssetje dnode /dnode move ( ) 8005648Ssetje ; 8015648Ssetje 8025648Ssetje \ read meta object set from uber-block 8035648Ssetje : get-mos ( -- ) 8045648Ssetje mos-dn /dnode ( adr len ) 8055648Ssetje uber-block ub_rootbp read-bp 8065648Ssetje ; 8075648Ssetje 8085648Ssetje : get-mos-dnode ( obj# -- ) 8095648Ssetje mos-dn swap get-dnode 8105648Ssetje ; 8115648Ssetje 8125648Ssetje \ get root dataset 8135648Ssetje : get-root-dsl ( -- ) 8145648Ssetje 8155648Ssetje \ read MOS 8165648Ssetje get-mos 8175648Ssetje 8185648Ssetje \ read object dir 8195648Ssetje pool-dir# get-mos-dnode 8205648Ssetje dnode obj-dir /dnode move 8215648Ssetje 8225648Ssetje \ read root dataset 8235648Ssetje obj-dir " root_dataset" zap-lookup if 8246423Sgw25295 " no root_dataset" die 8255648Ssetje then ( obj# ) 8265648Ssetje get-mos-dnode ( ) 8275648Ssetje dnode root-dsl /dnode move 8285648Ssetje ; 8295648Ssetje 8306423Sgw25295 \ find snapshot of given dataset 8316423Sgw25295 : snap-look ( snap$ ds-obj# -- [ss-obj# ] not-found? ) 8326423Sgw25295 get-mos-dnode dnode >dsl-ds ( snap$ ds ) 8336423Sgw25295 ds_snapnames_zapobj get-mos-dnode ( snap$ ) 8346423Sgw25295 dnode -rot zap-lookup ( [ss-obj# ] not-found? ) 8356423Sgw25295 ; 8366423Sgw25295 8376423Sgw25295 \ dsl dir to dataset 8386423Sgw25295 : dir>ds ( dn -- obj# ) >dsl-dir dd_head_dataset_obj ; 8396423Sgw25295 8405648Ssetje \ look thru the dsl hierarchy for path 8415648Ssetje \ this looks almost exactly like a FS directory lookup 8425648Ssetje : dsl-lookup ( path$ -- [ ds-obj# ] not-found? ) 8435648Ssetje root-dsl >r ( path$ r: root-dn ) 8445648Ssetje begin 8455648Ssetje ascii / left-parse-string ( path$ file$ r: dn ) 8465648Ssetje dup while 8475648Ssetje 8485648Ssetje \ get child dir zap dnode 8495648Ssetje r> >dsl-dir dd_child_dir_zapobj ( path$ file$ obj# ) 8505648Ssetje get-mos-dnode ( path$ file$ ) 8515648Ssetje 8526423Sgw25295 \ check for snapshot names 8536423Sgw25295 ascii @ left-parse-string ( path$ snap$ file$ ) 8546423Sgw25295 8555648Ssetje \ search it 8566423Sgw25295 dnode -rot zap-lookup if ( path$ snap$ ) 8575648Ssetje \ not found 8586423Sgw25295 2drop 2drop true exit ( not-found ) 8596423Sgw25295 then ( path$ snap$ obj# ) 8606423Sgw25295 get-mos-dnode ( path$ snap$ ) 8616423Sgw25295 8626423Sgw25295 \ lookup any snapshot name 8636423Sgw25295 dup if 8646423Sgw25295 \ must be last path component 8656423Sgw25295 2swap nip if ( snap$ ) 8666423Sgw25295 2drop true exit ( not-found ) 8676423Sgw25295 then 8686423Sgw25295 dnode dir>ds snap-look if ( ) 8696423Sgw25295 true exit ( not-found ) 8706423Sgw25295 then ( obj# ) 8716423Sgw25295 false exit ( obj# found ) 8726423Sgw25295 else 2drop then ( path$ ) 8736423Sgw25295 8745648Ssetje dnode >r ( path$ r: dn ) 8755648Ssetje repeat ( path$ file$ r: dn) 8765648Ssetje 2drop 2drop r> drop ( ) 8775648Ssetje 8785648Ssetje \ found it, return dataset obj# 8796423Sgw25295 dnode dir>ds ( ds-obj# ) 8805648Ssetje false ( ds-obj# found ) 8815648Ssetje ; 8825648Ssetje 8835648Ssetje \ get objset from dataset 8845648Ssetje : get-objset ( adr dn -- ) 8855648Ssetje >dsl-ds ds_bp /dnode swap read-bp 8865648Ssetje ; 8875648Ssetje 8885648Ssetje 8895648Ssetje \ 8905648Ssetje \ ZFS file-system (ZPL) routines 8915648Ssetje \ 8925648Ssetje 8935648Ssetje 1 constant master-node# 894*11935SMark.Shellenbaum@Sun.COM 895*11935SMark.Shellenbaum@Sun.COM 0 instance value bootfs-obj# 896*11935SMark.Shellenbaum@Sun.COM 0 instance value root-obj# 897*11935SMark.Shellenbaum@Sun.COM 0 instance value current-obj# 898*11935SMark.Shellenbaum@Sun.COM 0 instance value search-obj# 899*11935SMark.Shellenbaum@Sun.COM 900*11935SMark.Shellenbaum@Sun.COM instance defer fsize ( dn -- size ) 901*11935SMark.Shellenbaum@Sun.COM instance defer mode ( dn -- mode ) 902*11935SMark.Shellenbaum@Sun.COM instance defer parent ( dn -- obj# ) 903*11935SMark.Shellenbaum@Sun.COM instance defer readlink ( dst dn -- ) 904*11935SMark.Shellenbaum@Sun.COM 905*11935SMark.Shellenbaum@Sun.COM \ 906*11935SMark.Shellenbaum@Sun.COM \ routines when bonus pool contains a znode 907*11935SMark.Shellenbaum@Sun.COM \ 9085648Ssetje d# 264 constant /znode 9095648Ssetje d# 56 constant /zn-slink 9105648Ssetje 9115648Ssetje : zp_mode ( zn -- n ) h# 48 + x@ ; 9125648Ssetje : zp_size ( zn -- n ) h# 50 + x@ ; 9135648Ssetje : zp_parent ( zn -- n ) h# 58 + x@ ; 9145648Ssetje 9155648Ssetje alias >znode dn_bonus 9165648Ssetje 917*11935SMark.Shellenbaum@Sun.COM : zn-fsize ( dn -- n ) >znode zp_size ; 918*11935SMark.Shellenbaum@Sun.COM : zn-mode ( dn -- n ) >znode zp_mode ; 919*11935SMark.Shellenbaum@Sun.COM : zn-parent ( dn -- n ) >znode zp_parent ; 920*11935SMark.Shellenbaum@Sun.COM 921*11935SMark.Shellenbaum@Sun.COM \ copy symlink target to dst 922*11935SMark.Shellenbaum@Sun.COM : zn-readlink ( dst dn -- ) 923*11935SMark.Shellenbaum@Sun.COM dup zn-fsize tuck /zn-slink > if ( dst size dn ) 924*11935SMark.Shellenbaum@Sun.COM \ contents in 1st block 925*11935SMark.Shellenbaum@Sun.COM temp-space over dn-bsize ( dst size dn t-adr bsize ) 926*11935SMark.Shellenbaum@Sun.COM rot 0 lblk#>bp read-bp ( dst size ) 927*11935SMark.Shellenbaum@Sun.COM temp-space ( dst size src ) 928*11935SMark.Shellenbaum@Sun.COM else ( dst size dn ) 929*11935SMark.Shellenbaum@Sun.COM \ contents in dnode 930*11935SMark.Shellenbaum@Sun.COM >znode /znode + ( dst size src ) 931*11935SMark.Shellenbaum@Sun.COM then ( dst size src ) 932*11935SMark.Shellenbaum@Sun.COM -rot move ( ) 933*11935SMark.Shellenbaum@Sun.COM ; 934*11935SMark.Shellenbaum@Sun.COM 935*11935SMark.Shellenbaum@Sun.COM \ 936*11935SMark.Shellenbaum@Sun.COM \ routines when bonus pool contains sa's 937*11935SMark.Shellenbaum@Sun.COM \ 938*11935SMark.Shellenbaum@Sun.COM 939*11935SMark.Shellenbaum@Sun.COM \ SA header size when link is in dn_bonus 940*11935SMark.Shellenbaum@Sun.COM d# 16 constant /sahdr-link 941*11935SMark.Shellenbaum@Sun.COM 942*11935SMark.Shellenbaum@Sun.COM : sa_props ( sa -- n ) h# 4 + w@ ; 943*11935SMark.Shellenbaum@Sun.COM 944*11935SMark.Shellenbaum@Sun.COM : sa-hdrsz ( sa -- sz ) sa_props h# 7 >> ; 945*11935SMark.Shellenbaum@Sun.COM 946*11935SMark.Shellenbaum@Sun.COM alias >sa dn_bonus 947*11935SMark.Shellenbaum@Sun.COM 948*11935SMark.Shellenbaum@Sun.COM : >sadata ( dn -- adr ) >sa dup sa-hdrsz + ; 949*11935SMark.Shellenbaum@Sun.COM : sa-mode ( dn -- n ) >sadata x@ ; 950*11935SMark.Shellenbaum@Sun.COM : sa-fsize ( dn -- n ) >sadata h# 8 + x@ ; 951*11935SMark.Shellenbaum@Sun.COM : sa-parent ( dn -- n ) >sadata h# 28 + x@ ; 952*11935SMark.Shellenbaum@Sun.COM 953*11935SMark.Shellenbaum@Sun.COM \ copy symlink target to dst 954*11935SMark.Shellenbaum@Sun.COM : sa-readlink ( dst dn -- ) 955*11935SMark.Shellenbaum@Sun.COM dup >sa sa-hdrsz /sahdr-link <> if 956*11935SMark.Shellenbaum@Sun.COM \ contents in 1st attr of dn_spill 957*11935SMark.Shellenbaum@Sun.COM temp-space over dn_spill ( dst dn t-adr bp ) 958*11935SMark.Shellenbaum@Sun.COM dup bp-lsize swap read-bp ( dst dn ) 959*11935SMark.Shellenbaum@Sun.COM sa-fsize ( dst size ) 960*11935SMark.Shellenbaum@Sun.COM temp-space dup sa-hdrsz + ( dst size src ) 961*11935SMark.Shellenbaum@Sun.COM else ( dst dn ) 962*11935SMark.Shellenbaum@Sun.COM \ content in bonus buf 963*11935SMark.Shellenbaum@Sun.COM dup dn_bonus over dn_bonuslen + ( dst dn ebonus ) 964*11935SMark.Shellenbaum@Sun.COM swap sa-fsize tuck - ( dst size src ) 965*11935SMark.Shellenbaum@Sun.COM then ( dst size src ) 966*11935SMark.Shellenbaum@Sun.COM -rot move ( ) 967*11935SMark.Shellenbaum@Sun.COM ; 968*11935SMark.Shellenbaum@Sun.COM 969*11935SMark.Shellenbaum@Sun.COM 970*11935SMark.Shellenbaum@Sun.COM \ setup attr routines for dn 971*11935SMark.Shellenbaum@Sun.COM : set-attr ( dn -- ) 972*11935SMark.Shellenbaum@Sun.COM dn_bonustype ot-sa# = if 973*11935SMark.Shellenbaum@Sun.COM ['] sa-fsize to fsize 974*11935SMark.Shellenbaum@Sun.COM ['] sa-mode to mode 975*11935SMark.Shellenbaum@Sun.COM ['] sa-parent to parent 976*11935SMark.Shellenbaum@Sun.COM ['] sa-readlink to readlink 977*11935SMark.Shellenbaum@Sun.COM else 978*11935SMark.Shellenbaum@Sun.COM ['] zn-fsize to fsize 979*11935SMark.Shellenbaum@Sun.COM ['] zn-mode to mode 980*11935SMark.Shellenbaum@Sun.COM ['] zn-parent to parent 981*11935SMark.Shellenbaum@Sun.COM ['] zn-readlink to readlink 982*11935SMark.Shellenbaum@Sun.COM then 983*11935SMark.Shellenbaum@Sun.COM ; 984*11935SMark.Shellenbaum@Sun.COM 985*11935SMark.Shellenbaum@Sun.COM : ftype ( dn -- type ) mode h# f000 and ; 9865648Ssetje : dir? ( dn -- flag ) ftype h# 4000 = ; 9875648Ssetje : symlink? ( dn -- flag ) ftype h# a000 = ; 9885648Ssetje 9895648Ssetje \ read obj# from fs objset 9905648Ssetje : get-fs-dnode ( obj# -- ) 9915648Ssetje dup to current-obj# 9925648Ssetje fs-dn swap get-dnode ( ) 9935648Ssetje ; 9945648Ssetje 9955648Ssetje \ get root-obj# from dataset 9965648Ssetje : get-rootobj# ( ds-obj# -- fsroot-obj# ) 9975648Ssetje dup to bootfs-obj# 9985648Ssetje get-mos-dnode ( ) 9995648Ssetje fs-dn dnode get-objset 10005648Ssetje 10015648Ssetje \ get root obj# from master node 10025648Ssetje master-node# get-fs-dnode 10035648Ssetje dnode " ROOT" zap-lookup if 10046423Sgw25295 " no ROOT" die 10055648Ssetje then ( fsroot-obj# ) 10065648Ssetje ; 10075648Ssetje 10085648Ssetje : prop>rootobj# ( -- ) 10095648Ssetje obj-dir " pool_props" zap-lookup if 10106423Sgw25295 " no pool_props" die 10115648Ssetje then ( prop-obj# ) 10125648Ssetje get-mos-dnode ( ) 10135648Ssetje dnode " bootfs" zap-lookup if 10146423Sgw25295 " no bootfs" die 10155648Ssetje then ( ds-obj# ) 10165648Ssetje get-rootobj# ( fsroot-obj# ) 10175648Ssetje ; 10185648Ssetje 10195648Ssetje : fs>rootobj# ( fs$ -- root-obj# not-found? ) 10205648Ssetje 10215648Ssetje \ skip pool name 10225648Ssetje ascii / left-parse-string 2drop 10235648Ssetje 10245648Ssetje \ lookup fs in dsl 10255648Ssetje dsl-lookup if ( ) 10265648Ssetje true exit ( not-found ) 10275648Ssetje then ( ds-obj# ) 10285648Ssetje 10295648Ssetje get-rootobj# ( fsroot-obj# ) 10305648Ssetje false ( fsroot-obj# found ) 10315648Ssetje ; 10325648Ssetje 10335648Ssetje \ lookup file is current directory 10345648Ssetje : dirlook ( file$ dn -- not-found? ) 10355648Ssetje \ . and .. are magic 10365648Ssetje -rot 2dup " ." $= if ( dn file$ ) 10375648Ssetje 3drop false exit ( found ) 10385648Ssetje then 10395648Ssetje 10405648Ssetje 2dup " .." $= if 1041*11935SMark.Shellenbaum@Sun.COM 2drop parent ( obj# ) 10425648Ssetje else ( dn file$ ) 10435648Ssetje \ search dir 10445648Ssetje current-obj# to search-obj# 10455648Ssetje zap-lookup if ( ) 10465648Ssetje true exit ( not-found ) 10475648Ssetje then ( obj# ) 10485648Ssetje then ( obj# ) 1049*11935SMark.Shellenbaum@Sun.COM get-fs-dnode 1050*11935SMark.Shellenbaum@Sun.COM dnode set-attr 1051*11935SMark.Shellenbaum@Sun.COM false ( found ) 10525648Ssetje ; 10535648Ssetje 10545648Ssetje /buf-len instance buffer: fpath-buf 1055*11935SMark.Shellenbaum@Sun.COM /buf-len instance buffer: tpath-buf 10565648Ssetje 1057*11935SMark.Shellenbaum@Sun.COM : tpath-buf$ ( -- path$ ) tpath-buf cscount ; 1058*11935SMark.Shellenbaum@Sun.COM : fpath-buf$ ( -- path$ ) fpath-buf cscount ; 10595648Ssetje 10605648Ssetje \ modify tail to account for symlink 10615648Ssetje : follow-symlink ( tail$ -- tail$' ) 1062*11935SMark.Shellenbaum@Sun.COM \ read target 1063*11935SMark.Shellenbaum@Sun.COM tpath-buf /buf-len erase 1064*11935SMark.Shellenbaum@Sun.COM tpath-buf dnode readlink 10655648Ssetje 1066*11935SMark.Shellenbaum@Sun.COM \ append current path 10675648Ssetje ?dup if ( tail$ ) 1068*11935SMark.Shellenbaum@Sun.COM " /" tpath-buf$ $append ( tail$ ) 1069*11935SMark.Shellenbaum@Sun.COM tpath-buf$ $append ( ) 10705648Ssetje else drop then ( ) 1071*11935SMark.Shellenbaum@Sun.COM 1072*11935SMark.Shellenbaum@Sun.COM \ copy to fpath 1073*11935SMark.Shellenbaum@Sun.COM fpath-buf /buf-len erase 1074*11935SMark.Shellenbaum@Sun.COM tpath-buf$ fpath-buf swap move 10755648Ssetje fpath-buf$ ( path$ ) 10765648Ssetje 10775648Ssetje \ get directory that starts changed path 10785648Ssetje over c@ ascii / = if ( path$ ) 10795648Ssetje str++ root-obj# ( path$' obj# ) 10805648Ssetje else ( path$ ) 10815648Ssetje search-obj# ( path$ obj# ) 10825648Ssetje then ( path$ obj# ) 10835648Ssetje get-fs-dnode ( path$ ) 1084*11935SMark.Shellenbaum@Sun.COM dnode set-attr 10855648Ssetje ; 10865648Ssetje 10875648Ssetje \ open dnode at path 10885648Ssetje : lookup ( path$ -- not-found? ) 10895648Ssetje 10905648Ssetje \ get directory that starts path 10915648Ssetje over c@ ascii / = if 10925648Ssetje str++ root-obj# ( path$' obj# ) 10935648Ssetje else 10945648Ssetje current-obj# ( path$ obj# ) 10955648Ssetje then ( path$ obj# ) 10965648Ssetje get-fs-dnode ( path$ ) 1097*11935SMark.Shellenbaum@Sun.COM dnode set-attr 10985648Ssetje 10995648Ssetje \ lookup each path component 11005648Ssetje begin ( path$ ) 11015648Ssetje ascii / left-parse-string ( path$ file$ ) 11025648Ssetje dup while 11035648Ssetje dnode dir? 0= if 11045648Ssetje 2drop true exit ( not-found ) 11055648Ssetje then ( path$ file$ ) 11065648Ssetje dnode dirlook if ( path$ ) 11075648Ssetje 2drop true exit ( not-found ) 11085648Ssetje then ( path$ ) 11095648Ssetje dnode symlink? if 11105648Ssetje follow-symlink ( path$' ) 11115648Ssetje then ( path$ ) 11125648Ssetje repeat ( path$ file$ ) 11135648Ssetje 2drop 2drop false ( found ) 11145648Ssetje ; 11155648Ssetje 11165648Ssetje \ 11176423Sgw25295 \ ZFS volume (ZVOL) routines 11186423Sgw25295 \ 11196423Sgw25295 1 constant zvol-data# 11206423Sgw25295 2 constant zvol-prop# 11216423Sgw25295 11226423Sgw25295 0 instance value zv-dn 11236423Sgw25295 11246423Sgw25295 : get-zvol ( zvol$ -- not-found? ) 11256423Sgw25295 dsl-lookup if 11266423Sgw25295 drop true exit ( failed ) 11276423Sgw25295 then ( ds-obj# ) 11286423Sgw25295 11296423Sgw25295 \ get zvol objset 11306423Sgw25295 get-mos-dnode ( ) 11316423Sgw25295 zv-dn dnode get-objset 11326423Sgw25295 false ( succeeded ) 11336423Sgw25295 ; 11346423Sgw25295 11356423Sgw25295 \ get zvol data dnode 11366423Sgw25295 : zvol-data ( -- ) 11376423Sgw25295 zv-dn zvol-data# get-dnode 11386423Sgw25295 ; 11396423Sgw25295 11406423Sgw25295 : zvol-size ( -- size ) 11416423Sgw25295 zv-dn zvol-prop# get-dnode 11426423Sgw25295 dnode " size" zap-lookup if 11436423Sgw25295 " no zvol size" die 11446423Sgw25295 then ( size ) 11456423Sgw25295 ; 11466423Sgw25295 11476423Sgw25295 11486423Sgw25295 \ 11495648Ssetje \ ZFS installation routines 11505648Ssetje \ 11515648Ssetje 11525648Ssetje \ ZFS file interface 11535648Ssetje struct 11545648Ssetje /x field >busy 11555648Ssetje /x field >offset 11566423Sgw25295 /x field >fsize 11575648Ssetje /dnode field >dnode 11585648Ssetje constant /file-record 11595648Ssetje 11605648Ssetje d# 10 constant #opens 11615648Ssetje #opens /file-record * constant /file-records 11625648Ssetje 11635648Ssetje /file-records instance buffer: file-records 11645648Ssetje 11655648Ssetje -1 instance value current-fd 11665648Ssetje 11675648Ssetje : fd>record ( fd -- rec ) /file-record * file-records + ; 11685648Ssetje : file-offset@ ( -- off ) current-fd fd>record >offset x@ ; 11695648Ssetje : file-offset! ( off -- ) current-fd fd>record >offset x! ; 11705648Ssetje : file-dnode ( -- dn ) current-fd fd>record >dnode ; 11716423Sgw25295 : file-size ( -- size ) current-fd fd>record >fsize x@ ; 11725648Ssetje : file-bsize ( -- bsize ) file-dnode dn-bsize ; 11735648Ssetje 11745648Ssetje \ find free fd slot 11755648Ssetje : get-slot ( -- fd false | true ) 11765648Ssetje #opens 0 do 11775648Ssetje i fd>record >busy x@ 0= if 11785648Ssetje i false unloop exit 11795648Ssetje then 11805648Ssetje loop true 11815648Ssetje ; 11825648Ssetje 11835648Ssetje : free-slot ( fd -- ) 11845648Ssetje 0 swap fd>record >busy x! 11855648Ssetje ; 11865648Ssetje 11875648Ssetje \ init fd to offset 0 and copy dnode 11886423Sgw25295 : init-fd ( fsize fd -- ) 11896423Sgw25295 fd>record ( fsize rec ) 11905648Ssetje dup >busy 1 swap x! 11915648Ssetje dup >dnode dnode swap /dnode move 11926423Sgw25295 dup >fsize rot swap x! ( rec ) 11936423Sgw25295 >offset 0 swap x! ( ) 11945648Ssetje ; 11955648Ssetje 11965648Ssetje \ make fd current 11975648Ssetje : set-fd ( fd -- error? ) 11985648Ssetje dup fd>record >busy x@ 0= if ( fd ) 11995648Ssetje drop true exit ( failed ) 12005648Ssetje then ( fd ) 12015648Ssetje to current-fd false ( succeeded ) 12025648Ssetje ; 12035648Ssetje 12045648Ssetje \ read next fs block 12055648Ssetje : file-bread ( adr -- ) 12065648Ssetje file-bsize ( adr len ) 12075648Ssetje file-offset@ over / ( adr len blk# ) 12085648Ssetje file-dnode swap lblk#>bp ( adr len bp ) 12095648Ssetje read-bp ( ) 12105648Ssetje ; 12115648Ssetje 12125648Ssetje \ advance file io stack by n 12135648Ssetje : fio+ ( # adr len n -- #+n adr+n len-n ) 12145648Ssetje dup file-offset@ + file-offset! 12155648Ssetje dup >r - -rot ( len' # adr r: n ) 12165648Ssetje r@ + -rot ( adr' len' # r: n ) 12175648Ssetje r> + -rot ( #' adr' len' ) 12185648Ssetje ; 12195648Ssetje 12207283Sjgj 12219941SJohn.Johnson@Sun.COM /max-bsize 5 * 12229941SJohn.Johnson@Sun.COM /uber-block + 12239941SJohn.Johnson@Sun.COM /dnode 6 * + 12249941SJohn.Johnson@Sun.COM /disk-block 6 * + ( size ) 12257283Sjgj \ ugh - sg proms can't free 512k allocations 12267283Sjgj \ that aren't a multiple of 512k in size 12279941SJohn.Johnson@Sun.COM h# 8.0000 roundup ( size' ) 12287283Sjgj constant alloc-size 12297283Sjgj 12305648Ssetje 12315648Ssetje : allocate-buffers ( -- ) 12325648Ssetje alloc-size h# a0.0000 vmem-alloc dup 0= if 12336423Sgw25295 " no memory" die 12345648Ssetje then ( adr ) 12355648Ssetje dup to temp-space /max-bsize + ( adr ) 12365648Ssetje dup to dn-cache /max-bsize + ( adr ) 12375648Ssetje dup to blk-space /max-bsize + ( adr ) 12385648Ssetje dup to ind-cache /max-bsize + ( adr ) 12395648Ssetje dup to zap-space /max-bsize + ( adr ) 12405648Ssetje dup to uber-block /uber-block + ( adr ) 12415648Ssetje dup to mos-dn /dnode + ( adr ) 12425648Ssetje dup to obj-dir /dnode + ( adr ) 12435648Ssetje dup to root-dsl /dnode + ( adr ) 12445648Ssetje dup to fs-dn /dnode + ( adr ) 12456423Sgw25295 dup to zv-dn /dnode + ( adr ) 12465648Ssetje dup to dnode /dnode + ( adr ) 12475648Ssetje to gang-space ( ) 12485648Ssetje 12495648Ssetje \ zero instance buffers 12505648Ssetje file-records /file-records erase 1251*11935SMark.Shellenbaum@Sun.COM bootprop-buf /buf-len erase 12525648Ssetje ; 12535648Ssetje 12545648Ssetje : release-buffers ( -- ) 12555648Ssetje temp-space alloc-size mem-free 12565648Ssetje ; 12575648Ssetje 12585648Ssetje external 12595648Ssetje 12605648Ssetje : open ( -- okay? ) 12615648Ssetje my-args dev-open dup 0= if 12625648Ssetje exit ( failed ) 12635648Ssetje then to dev-ih 12645648Ssetje 12655648Ssetje allocate-buffers 12665648Ssetje scan-vdev 12675648Ssetje get-ub 12685648Ssetje get-root-dsl 12695648Ssetje true 12705648Ssetje ; 12715648Ssetje 12725648Ssetje : open-fs ( fs$ -- okay? ) 12735648Ssetje fs>rootobj# if ( ) 12745648Ssetje false ( failed ) 12755648Ssetje else ( obj# ) 12765648Ssetje to root-obj# true ( succeeded ) 12775648Ssetje then ( okay? ) 12785648Ssetje ; 12795648Ssetje 12805648Ssetje : close ( -- ) 12815648Ssetje dev-ih dev-close 12825648Ssetje 0 to dev-ih 12835648Ssetje release-buffers 12845648Ssetje ; 12855648Ssetje 12865648Ssetje : open-file ( path$ -- fd true | false ) 12875648Ssetje 12885648Ssetje \ open default fs if no open-fs 12895648Ssetje root-obj# 0= if 12905648Ssetje prop>rootobj# to root-obj# 12915648Ssetje then 12925648Ssetje 12935648Ssetje get-slot if 12945648Ssetje 2drop false exit ( failed ) 12955648Ssetje then -rot ( fd path$ ) 12965648Ssetje 12975648Ssetje lookup if ( fd ) 12985648Ssetje drop false exit ( failed ) 12995648Ssetje then ( fd ) 13005648Ssetje 13016423Sgw25295 dnode fsize over init-fd 13026423Sgw25295 true ( fd succeeded ) 13035648Ssetje ; 13045648Ssetje 13056423Sgw25295 : open-volume ( vol$ -- okay? ) 13066423Sgw25295 get-slot if 13076423Sgw25295 2drop false exit ( failed ) 13086423Sgw25295 then -rot ( fd vol$ ) 13096423Sgw25295 13106423Sgw25295 get-zvol if ( fd ) 13116423Sgw25295 drop false exit ( failed ) 13126423Sgw25295 then 13136423Sgw25295 13146423Sgw25295 zvol-size over ( fd size fd ) 13156423Sgw25295 zvol-data init-fd ( fd ) 13166423Sgw25295 true ( fd succeeded ) 13176423Sgw25295 ; 13186423Sgw25295 13195648Ssetje : close-file ( fd -- ) 13205648Ssetje free-slot ( ) 13215648Ssetje ; 13225648Ssetje 13235648Ssetje : size-file ( fd -- size ) 13245648Ssetje set-fd if 0 else file-size then 13255648Ssetje ; 13265648Ssetje 13275648Ssetje : seek-file ( off fd -- off true | false ) 13285648Ssetje set-fd if ( off ) 13295648Ssetje drop false exit ( failed ) 13305648Ssetje then ( off ) 13315648Ssetje 13326423Sgw25295 dup file-size x> if ( off ) 13335648Ssetje drop false exit ( failed ) 13345648Ssetje then ( off ) 13355648Ssetje dup file-offset! true ( off succeeded ) 13365648Ssetje ; 13375648Ssetje 13385648Ssetje : read-file ( adr len fd -- #read ) 13395648Ssetje set-fd if ( adr len ) 13405648Ssetje 2drop 0 exit ( 0 ) 13415648Ssetje then ( adr len ) 13425648Ssetje 13435648Ssetje \ adjust len if reading past eof 13446423Sgw25295 dup file-offset@ + file-size x> if 13455648Ssetje dup file-offset@ + file-size - - 13465648Ssetje then 13475648Ssetje dup 0= if nip exit then 13485648Ssetje 13495648Ssetje 0 -rot ( #read adr len ) 13505648Ssetje 13515648Ssetje \ initial partial block 13525648Ssetje file-offset@ file-bsize mod ?dup if ( #read adr len off ) 13535648Ssetje temp-space file-bread 13545648Ssetje 2dup file-bsize swap - min ( #read adr len off cpy-len ) 13555648Ssetje 2over drop -rot ( #read adr len adr off cpy-len ) 13565648Ssetje >r temp-space + swap ( #read adr len cpy-src adr r: cpy-len ) 13575648Ssetje r@ move r> fio+ ( #read' adr' len' ) 13585648Ssetje then ( #read adr len ) 13595648Ssetje 13605648Ssetje dup file-bsize / 0 ?do ( #read adr len ) 13615648Ssetje over file-bread 13625648Ssetje file-bsize fio+ ( #read' adr' len' ) 13635648Ssetje loop ( #read adr len ) 13645648Ssetje 13655648Ssetje \ final partial block 13665648Ssetje dup if ( #read adr len ) 13675648Ssetje temp-space file-bread 13685648Ssetje 2dup temp-space -rot move ( #read adr len ) 13695648Ssetje dup fio+ ( #read' adr' 0 ) 13705648Ssetje then 2drop ( #read ) 13715648Ssetje ; 13725648Ssetje 13735648Ssetje : cinfo-file ( fd -- bsize fsize comp? ) 13745648Ssetje set-fd if 13755648Ssetje 0 0 0 13765648Ssetje else 13775648Ssetje file-bsize file-size ( bsize fsize ) 13785648Ssetje \ zfs does internal compression 13795648Ssetje 0 ( bsize fsize comp? ) 13805648Ssetje then 13815648Ssetje ; 13825648Ssetje 13835648Ssetje \ read ramdisk fcode at rd-offset 13845648Ssetje : get-rd ( adr len -- ) 13855648Ssetje rd-offset dev-ih read-disk 13865648Ssetje ; 13875648Ssetje 13885648Ssetje : bootprop 13895648Ssetje " /" bootprop$ $append 13905648Ssetje bootfs-obj# (xu.) bootprop$ $append 13915648Ssetje bootprop$ encode-string " zfs-bootfs" ( propval propname ) 13925648Ssetje true 13935648Ssetje ; 13945648Ssetje 13955648Ssetje 13965648Ssetje : chdir ( dir$ -- ) 13975648Ssetje current-obj# -rot ( obj# dir$ ) 13985648Ssetje lookup if ( obj# ) 13995648Ssetje to current-obj# ( ) 14005648Ssetje ." no such dir" cr exit 14015648Ssetje then ( obj# ) 14025648Ssetje dnode dir? 0= if ( obj# ) 14035648Ssetje to current-obj# ( ) 14045648Ssetje ." not a dir" cr exit 14055648Ssetje then drop ( ) 14065648Ssetje ; 14075648Ssetje 14085648Ssetje : dir ( -- ) 14095648Ssetje current-obj# get-fs-dnode 14105648Ssetje dnode zap-print 14115648Ssetje ; 14125648Ssetje 14135648Ssetjefinish-device 14145648Ssetjepop-package 1415