xref: /onnv-gate/usr/src/psm/stand/bootblks/zfs/common/zfs.fth (revision 11935:538c866aaac6)
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