usr/src/psm/stand/bootblks/zfs/common/zfs.fth
changeset 6423 437422a29d3a
parent 5648 161f8007cab9
child 6490 42b6f0b6ade0
--- a/usr/src/psm/stand/bootblks/zfs/common/zfs.fth	Fri Apr 11 16:15:33 2008 -0700
+++ b/usr/src/psm/stand/bootblks/zfs/common/zfs.fth	Fri Apr 11 18:36:28 2008 -0700
@@ -1,6 +1,6 @@
 
 \ ident	"%Z%%M%	%I%	%E% SMI"
-\ Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+\ Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 \ Use is subject to license terms.
 \
 \ CDDL HEADER START
@@ -49,13 +49,13 @@
    \ stack ops and logical ops (dup, and, etc) are 64b
    : xcmp  ( x1 x2 -- -1|0|1 )
       xlsplit rot xlsplit        ( x2.lo x2.hi x1.lo x1.hi )
-      rot 2dup  <  if            ( x2.lo x1.lo x1.hi x2.hi )
+      rot 2dup  u<  if           ( x2.lo x1.lo x1.hi x2.hi )
          2drop 2drop  -1         ( lt )
-      else  >  if                ( x2.lo x1.lo )
+      else  u>  if               ( x2.lo x1.lo )
          2drop  1                ( gt )
-      else  swap 2dup <  if      ( x1.lo x2.lo )
+      else  swap 2dup u<  if     ( x1.lo x2.lo )
          2drop  -1               ( lt )
-      else  >  if                (  )
+      else  u>  if               (  )
          1                       ( gt )
       else                       (  )
          0                       ( eq )
@@ -267,6 +267,13 @@
    : >nvdata  ( nv -- data )
       >nvname +  /l roundup
    ;
+
+   \ convert nvdata to 64b int or string
+   : nvdata>x  ( nvdata -- x )
+      /l 2* +                   ( ptr )
+      dup /l + l@  swap l@      ( x.lo x.hi )
+      lxjoin                    ( x )
+   ;
    alias nvdata>$ >nvname
 
    : nv-lookup  ( nv name$ -- nvdata false  |  true )
@@ -285,8 +292,14 @@
    : scan-vdev  ( -- )
       temp-space /nvpairs nvpairs-off    ( adr len off )
       dev-ih  read-disk                  (  )
+      temp-space " txg"  nv-lookup  if
+         " no txg nvpair"  die
+      then  nvdata>x                     ( txg )
+      x0=  if
+         " detached mirror"  die
+      then                               (  )
       temp-space " name"  nv-lookup  if
-         ." no name nvpair"  abort
+         " no name nvpair"  die
       then  nvdata>$                     ( pool$ )
       bootprop-buf swap  move            (  )
    ;
@@ -343,7 +356,7 @@
       /uber-block +loop
 
       \ make sure we found a valid ub
-      dup 0=  if  ." no ub found" abort  then
+      dup 0=  if  " no ub found" die  then
 
       uber-block /uber-block  move          (  )
    ;
@@ -398,7 +411,7 @@
       2dup over  dn_indblkshift  rshift    ( dn bp-off dn blk#  r: lvl )
       r> 1+  blk@lvl>bp                    ( dn bp-off bp )
 
-      \ read parent indir and index
+      \ read parent indir blk and index
       rot tuck dn-indsize                  ( bp-off dn bp len )
       ind-cache swap rot  read-bp          ( bp-off dn )
       dn-indmask  and                      ( bp-off' )
@@ -708,6 +721,8 @@
 
    : dd_head_dataset_obj  ( dd -- n )  h#  8 +  x@  ;
    : dd_child_dir_zapobj  ( dd -- n )  h# 20 +  x@  ;
+
+   : ds_snapnames_zapobj  ( ds -- n )  h# 20 +  x@  ;
    : ds_bp                ( ds -- p )  h# 80 +      ;
 
    0 instance value mos-dn
@@ -725,7 +740,7 @@
    alias  >dsl-dir  dn_bonus
    alias  >dsl-ds   dn_bonus
 
-   : #dn/blk  ( dn -- n )  dn-bsize /dnode  /  ;
+   : #dn/blk  ( dn -- n )     dn-bsize /dnode  /  ;
 
    \ read block into dn-cache
    : get-dnblk  ( dn blk# -- )
@@ -775,13 +790,23 @@
 
       \ read root dataset
       obj-dir " root_dataset"  zap-lookup  if
-         ." no root_dataset"  abort
+         " no root_dataset"  die
       then                                   ( obj# )
       dup to root-dsl#
       get-mos-dnode                          (  )
       dnode root-dsl  /dnode  move
    ;
 
+   \ find snapshot of given dataset
+   : snap-look  ( snap$ ds-obj# -- [ss-obj# ] not-found? )
+      get-mos-dnode  dnode >dsl-ds         ( snap$ ds )
+      ds_snapnames_zapobj  get-mos-dnode   ( snap$ )
+      dnode -rot  zap-lookup               ( [ss-obj# ] not-found? )
+   ;
+
+   \ dsl dir to dataset
+   : dir>ds   ( dn -- obj# )  >dsl-dir dd_head_dataset_obj  ;
+
    \ look thru the dsl hierarchy for path
    \ this looks almost exactly like a FS directory lookup
    : dsl-lookup ( path$ -- [ ds-obj# ] not-found? )
@@ -794,18 +819,34 @@
          r>  >dsl-dir dd_child_dir_zapobj         ( path$ file$ obj# )
          get-mos-dnode                            ( path$ file$ )
 
+         \ check for snapshot names
+         ascii @  left-parse-string               ( path$ snap$ file$ )
+
          \ search it
-         dnode -rot zap-lookup  if                ( path$ )
+         dnode -rot zap-lookup  if                ( path$ snap$ )
             \ not found
-            2drop true  exit                      ( not-found )
-         then                                     ( path$ obj# )
-         get-mos-dnode                            ( path$ )
+            2drop 2drop true  exit                ( not-found )
+         then                                     ( path$ snap$ obj# )
+         get-mos-dnode                            ( path$ snap$ )
+
+         \ lookup any snapshot name
+         dup  if
+            \ must be last path component
+            2swap  nip  if                        ( snap$ )
+               2drop true  exit                   ( not-found )
+            then
+            dnode dir>ds  snap-look  if           (  )
+               true  exit                         ( not-found )
+            then                                  ( obj# )
+            false  exit                           ( obj# found )
+         else  2drop  then                        ( path$ )
+
          dnode >r                                 ( path$  r: dn )
       repeat                                      ( path$ file$  r: dn)
       2drop 2drop  r> drop                        (  )
 
       \ found it, return dataset obj#
-      dnode >dsl-dir dd_head_dataset_obj          ( ds-obj# )
+      dnode  dir>ds                               ( ds-obj# )
       false                                       ( ds-obj# found )
    ;
 
@@ -837,7 +878,6 @@
    : fsize     ( dn -- n )     >znode zp_size  ;
    : ftype     ( dn -- n )     >znode zp_mode  h# f000  and  ;
    : dir?      ( dn -- flag )  ftype  h# 4000  =  ;
-   : regular?  ( dn -- flag )  ftype  h# 8000  =  ;
    : symlink?  ( dn -- flag )  ftype  h# a000  =  ;
 
    \ read obj# from fs objset
@@ -855,17 +895,17 @@
       \ get root obj# from master node
       master-node#  get-fs-dnode
       dnode  " ROOT"  zap-lookup  if
-         ." no ROOT"  abort
+         " no ROOT"  die
       then                             ( fsroot-obj# )
    ;
 
    : prop>rootobj#  ( -- )
       obj-dir " pool_props" zap-lookup  if
-         ." no pool_props"  abort
+         " no pool_props"  die
       then                               ( prop-obj# )
       get-mos-dnode                      (  )
       dnode " bootfs" zap-lookup  if
-         ." no bootfs"  abort
+         " no bootfs"  die
       then                               ( ds-obj# )
       get-rootobj#                       ( fsroot-obj# )
    ;
@@ -972,6 +1012,38 @@
    ;
 
    \
+   \   ZFS volume (ZVOL) routines
+   \
+   1 constant  zvol-data#
+   2 constant  zvol-prop#
+
+   0 instance value zv-dn
+
+   : get-zvol  ( zvol$ -- not-found? )
+      dsl-lookup  if
+         drop true  exit           ( failed )
+      then                         ( ds-obj# )
+
+      \ get zvol objset
+      get-mos-dnode                (  )
+      zv-dn dnode  get-objset
+      false                        ( succeeded )
+   ;
+
+   \ get zvol data dnode
+   : zvol-data  ( -- )
+      zv-dn zvol-data#  get-dnode
+   ;
+
+   : zvol-size  ( -- size )
+       zv-dn zvol-prop#   get-dnode
+       dnode " size"  zap-lookup  if
+          " no zvol size"  die
+       then                            ( size )
+   ;
+       
+
+   \
    \	ZFS installation routines
    \
 
@@ -979,6 +1051,7 @@
    struct
       /x     field >busy
       /x     field >offset
+      /x     field >fsize
       /dnode field >dnode
    constant /file-record
 
@@ -993,7 +1066,7 @@
    : file-offset@  ( -- off )     current-fd fd>record >offset  x@  ;
    : file-offset!  ( off -- )     current-fd fd>record >offset  x!  ;
    : file-dnode    ( -- dn )      current-fd fd>record >dnode  ;
-   : file-size     ( -- size )    file-dnode  fsize  ;
+   : file-size     ( -- size )    current-fd fd>record >fsize  x@  ;
    : file-bsize    ( -- bsize )   file-dnode  dn-bsize  ;
 
    \ find free fd slot
@@ -1010,11 +1083,12 @@
    ;
 
    \ init fd to offset 0 and copy dnode
-   : init-fd  ( fd -- )
-      fd>record                ( rec )
+   : init-fd  ( fsize fd -- )
+      fd>record                ( fsize rec )
       dup  >busy  1 swap  x!
       dup  >dnode  dnode swap  /dnode  move
-      >offset  0 swap  x!
+      dup  >fsize  rot swap  x!     ( rec )
+      >offset  0 swap  x!      (  )
    ;
 
    \ make fd current
@@ -1043,13 +1117,13 @@
 
    /max-bsize  5 *
    /uber-block      +
-   /dnode      5 *  +
+   /dnode      6 *  +
    /disk-block      +
    constant alloc-size
 
    : allocate-buffers  ( -- )
       alloc-size h# a0.0000 vmem-alloc  dup 0=  if
-         ." no memory"  abort
+         " no memory"  die
       then                                ( adr )
       dup to temp-space    /max-bsize  +  ( adr )
       dup to dn-cache      /max-bsize  +  ( adr )
@@ -1061,6 +1135,7 @@
       dup to obj-dir       /dnode      +  ( adr )
       dup to root-dsl      /dnode      +  ( adr )
       dup to fs-dn         /dnode      +  ( adr )
+      dup to zv-dn         /dnode      +  ( adr )
       dup to dnode         /dnode      +  ( adr )
           to gang-space                   (  )
 
@@ -1116,9 +1191,24 @@
          drop false  exit          ( failed )
       then                         ( fd )
 
-      dup init-fd  true            ( fd succeeded )
+      dnode fsize  over init-fd
+      true                         ( fd succeeded )
    ;
 
+   : open-volume ( vol$ -- okay? )
+      get-slot  if
+         2drop false  exit         ( failed )
+      then  -rot                   ( fd vol$ )
+
+      get-zvol  if                 ( fd )
+         drop false  exit          ( failed )
+      then
+
+      zvol-size over               ( fd size fd )
+      zvol-data init-fd            ( fd )
+      true                         ( fd succeeded )
+   ;
+      
    : close-file  ( fd -- )
       free-slot   (  )
    ;
@@ -1132,7 +1222,7 @@
          drop false  exit       ( failed )
       then                      ( off )
 
-      dup file-size >  if       ( off )
+      dup file-size x>  if      ( off )
          drop false  exit       ( failed )
       then                      ( off )
       dup  file-offset!  true   ( off succeeded )
@@ -1143,10 +1233,8 @@
          2drop 0  exit             ( 0 )
       then                         ( adr len )
 
-      file-dnode regular? 0=  if  2drop 0  exit  then
-
       \ adjust len if reading past eof
-      dup  file-offset@ +  file-size  >  if
+      dup  file-offset@ +  file-size  x>  if
          dup  file-offset@ +  file-size -  -
       then
       dup 0=  if  nip exit  then