Author: wmb Date: 2008-09-07 21:23:04 +0200 (Sun, 07 Sep 2008) New Revision: 923
Modified: ofw/fs/ext2fs/bitmap.fth ofw/fs/ext2fs/blocks.fth ofw/fs/ext2fs/dir.fth ofw/fs/ext2fs/layout.fth ofw/fs/ext2fs/methods.fth ofw/fs/ext2fs/sb.fth Log: EXT2 file system - major edit to fix bugs and performance problems for writing.
Modified: ofw/fs/ext2fs/bitmap.fth =================================================================== --- ofw/fs/ext2fs/bitmap.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/bitmap.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -3,6 +3,8 @@
decimal
+\ Group descriptor access + 0 instance value gd-modified?
: gd-update ( -- ) true to gd-modified? ; @@ -10,116 +12,163 @@ : inode-bitmap ( group# -- block# ) group-desc 4 + le-l@ ; : inode-table ( group# -- block# ) group-desc 8 + le-l@ ; : free-blocks ( group# -- n ) group-desc h# 0c + le-w@ ; -: free-inodes ( group# -- n ) group-desc h# 0e + le-w@ ; : free-blocks+! ( n group# -- ) - group-desc h# 0c + - tuck le-w@ + swap le-w! gd-update + group-desc h# 0c + + tuck le-w@ + 0 max swap le-w! gd-update ; -: free-inodes+! ( n group# -- ) +: free-inodes ( group# -- n ) group-desc h# 0e + le-w@ ; +: free-inodes+! ( n inode# -- ) group-desc h# 0e + tuck le-w@ + swap le-w! gd-update ;
-\ find the lowest clear bit in a byte -: find-low ( byte -- bit ) - 1 8 0 do - 2dup and 0= if - drop i leave - then - 2* - loop - nip 1+ -; -\ find the first clear bit in a bitmap -: first-free ( map len -- n ) - -1 -rot 0 ?do ( byte map ) - dup i + c@ h# ff <> if - nip i swap leave - then - loop ( byte map ) - over 0< if 2drop 0 exit then - - over + c@ find-low ( byte bit ) - swap 8* + -; +[ifdef] 386-assembler +code find-low-zero ( n -- bit# ) + ax pop + cx cx xor + clc + begin + cx inc + 1 # ax rcr + no-carry? until + cx dec + cx push +c; +[else] +create lowbits + 8 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 0-f + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 10-1f
-: (find-free-block) ( group# -- n ) - block-bitmap block - fpg 8 / bsize min \ XXX stay in this block - first-free -; -: find-free-block ( -- n ) - 0 - #groups 0 ?do - drop - i (find-free-block) dup ?leave - loop - dup 0= abort" no free blocks found" -; + 5 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 20-2f + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 30-3f
-: (find-free-inode) ( group# -- n ) - inode-bitmap block - ipg 8 / bsize min \ XXX stay in this block - first-free + 6 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 40-4f + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 50-5f + + 5 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 20-2f + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 30-3f + + 7 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 80-8f + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ 90-9f + + 5 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ a0-af + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ b0-bf + + 6 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ c0-cf + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ d0-df + + 5 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ e0-ef + 4 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, 3 c, 0 c, 1 c, 0 c, 2 c, 0 c, 1 c, 0 c, \ f0-ff + +: find-low-zero ( byte -- bit# ) invert h# ff and lowbits + c@ ; +[then] + +\ Find the first clear bit in a bitmap, set it if found +: first-free ( len block# -- false | block#-in-group true ) + block swap ( map len ) + + 2dup h# ff bskip dup 0= if ( map len 0 ) + 3drop false exit + then ( map len residue ) + - ( map byte# ) + tuck + dup c@ dup find-low-zero ( byte# adr byte bit# ) + + \ Set the bit we just found + >r 1 r@ lshift or ( byte# adr byte' r: bit# ) + swap c! \ Write back to map ( byte# r: bit# ) + + 8* r> + ( block#-in-group ) + update ( block#-in-group ) + true ; -: find-free-inode ( -- n ) - 0 - #groups 0 ?do - drop - i (find-free-inode) dup ?leave - loop - dup 0= abort" no free inodes found" -;
: bitup ( n adr -- mask adr' ) over 3 rshift + ( n adr' ) 1 rot 7 and lshift ( adr' mask ) swap ; -: block-bit ( block# -- n adr ) 1- fpg /mod block-bitmap block bitup ; -: block-free? ( block# -- set? ) block-bit c@ and 0= ; -: set-block-bit ( block# -- ) block-bit cset update ; -: clr-block-bit ( block# -- ) block-bit creset update ; + +: clear-bit? ( bit# block# -- cleared? ) + block bitup ( mask adr' ) + tuck c@ ( adr mask byte ) + 2dup and 0= if \ Already free ( adr mask byte ) + 3drop false exit + then ( adr mask byte ) + swap invert and ( adr byte' ) + swap c! ( ) + update ( ) + true +; + : free-block ( block# -- ) - dup block-free? if drop exit then - - dup clr-block-bit ( block# ) - 1 swap 1- fpg / ( 1 group# ) - free-blocks+! + datablock0 - bpg /mod ( bit# group# ) + tuck block-bitmap ( group# bit# block# ) + clear-bit? if ( group# ) + 1 swap free-blocks+! + else ( group# ) + drop + then ; -: alloc-block ( -- block# ) - find-free-block dup set-block-bit ( block# ) - dup block bsize erase update ( block# ) - dup 1- fpg / ( block# group# ) - -1 swap free-blocks+! + +: alloc-block ( -- block# ) + #groups 0 ?do ( ) + i free-blocks if ( ) + bpg 3 rshift bsize min ( len ) \ XXX stay in this block + i block-bitmap ( len block# ) + first-free if ( block#-in-group ) + -1 i free-blocks+! ( block#-in-group ) + i bpg * + datablock0 + ( block# ) + dup buffer bsize erase update ( block# ) + unloop exit + else + \ The allocation bitmap disagrees with the free block count, + \ so fix the free block count to prevent thrashing. + i free-blocks negate i free-blocks+! + then + then + loop + true abort" no free blocks found" ;
-: inode-bit ( inode# -- n adr ) 1- ipg /mod inode-bitmap block bitup ; -: inode-free? ( inode# -- set? ) inode-bit c@ and 0= ; -: set-inode-bit ( inode# -- ) inode-bit cset update ; -: clr-inode-bit ( inode# -- ) inode-bit creset update ; : free-inode ( inode# -- ) - dup inode-free? if drop exit then - - dup clr-inode-bit - 1 swap 1- ipg / ( 1 group# ) - free-inodes+! + 1- ipg /mod ( bit# group# ) + tuck inode-bitmap ( group# bit# block# ) + clear-bit? if ( group# ) + 1 swap free-inodes+! + else ( group# ) + drop + then ; -: alloc-inode ( -- inode# ) - find-free-inode dup set-inode-bit ( inode# ) - dup inode /inode erase update ( inode# ) - dup 1- ipg / ( inode# group# ) - -1 swap free-inodes+! + +: alloc-inode ( -- inode# ) + #groups 0 ?do + ipg 3 rshift bsize min ( len ) \ XXX stay in this block + i inode-bitmap ( len block# ) + first-free if ( inode#-in-group ) + -1 i free-inodes+! ( inode#-in-group ) + i ipg * + 1+ ( inode# ) + dup inode /inode erase update ( inode# ) + unloop exit + then + loop + true abort" no free inodes found" ; + : update-sb ( -- ) 0 #groups 0 ?do i free-inodes + loop total-free-inodes! 0 #groups 0 ?do i free-blocks + loop total-free-blocks! put-super-block abort" failed to update superblock " gds /gds gds-block# write-ublocks abort" failed to update group descriptors " ; + : update-gds ( -- ) gd-modified? if - #groups 1 do 0 group-desc i fpg * 2 + block bsize move update loop + \ Copy group descriptors to backup locations + #groups 1 do + 0 group-desc ( gd0-adr ) + i bpg * 2+ block ( gd0-adr gdn-adr ) + bsize move update ( ) + loop false to gd-modified? update-sb then
Modified: ofw/fs/ext2fs/blocks.fth =================================================================== --- ofw/fs/ext2fs/blocks.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/blocks.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -66,7 +66,10 @@ dup dirty? if ( buffer# ) false over dirty! dup >buffer swap blk# ( buffer-adr block# ) - dup 3 < if dup . ." attempt to corrupt superblock or group desciptor" abort then + dup gds-fs-block# <= if + dup . ." attempt to corrupt superblock or group descriptor" abort + then + bbug? if ." W " dup . cr then write-fs-block abort" write error " else drop
Modified: ofw/fs/ext2fs/dir.fth =================================================================== --- ofw/fs/ext2fs/dir.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/dir.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -18,12 +18,31 @@
\ **** Return the address of the current directory entry : dirent ( -- adr ) dir-block# block diroff @ + ; +\ Dirent fields: +\ 00.l inode +\ 04.w offset to next dirent +\ 06.b name length +\ 07.b flags? +\ 08.s name string
+: >reclen ( name-length -- record-length ) 8 + 4 round-up ; + +: dirent-inode@ ( -- n ) dirent int@ ; +: dirent-inode! ( n -- ) dirent int! ; +: dirent-len@ ( -- n ) dirent la1+ short@ ; +: dirent-len! ( n -- ) dirent la1+ short! ; +: dirent-nameadr ( -- adr ) dirent la1+ 2 wa+ ; +: dirent-namelen@ ( -- b ) dirent la1+ wa1+ c@ ; +: dirent-namelen! ( b -- ) dirent la1+ wa1+ c! ; +: dirent-type@ ( -- b ) dirent la1+ wa1+ ca1+ c@ ; +: dirent-type! ( b -- ) dirent la1+ wa1+ ca1+ c! ; +: dirent-reclen ( -- n ) dirent-namelen@ >reclen ; + : lblk#++ ( -- ) lblk# 1+ to lblk# ;
\ **** Select the next directory entry : next-dirent ( -- end? ) - dirent la1+ short@ dup diroff +! totoff +! + dirent-len@ dup diroff +! totoff +! totoff @ file-size >= if true exit then diroff @ bsize = if lblk#++ get-dirblk if true exit then @@ -34,12 +53,12 @@
\ **** From directory, get handle of the file or subdir that it references \ For Unix, file handle is the inode # -: file-handle ( -- i# ) dirent int@ ; +: file-handle ( -- i# ) dirent-inode@ ;
\ **** From directory, get name of file : file-name ( -- adr len ) dirent la1+ wa1+ dup wa1+ ( len-adr name-adr ) - swap short@ h# ff and ( adr len ) + swap c@ ( adr len ) ;
\ @@ -59,53 +78,92 @@ update r> drop ; -: >reclen ( name-length -- record-length ) 8 + 4 round-up ; + +\ On entry: +\ current-dir @ is the inode of the directory file +\ dir-block# is the physical block number of the first directory block +\ diroff @ is 0 +\ On successful exit: +\ dir-block# is the physical block number of the current directory block +\ diroff @ is the within-block offset of the new dirent +: no-dir-space? ( #needed -- true | offset-to-next false ) + begin ( #needed ) + dirent-inode@ if ( #needed ) + dup dirent-len@ dirent-reclen - <= if ( #needed ) + \ Carve space out of active dirent + drop ( ) + dirent-len@ dirent-reclen - ( offset-to-next ) + dirent-reclen dup dirent-len! diroff +! ( offset-to-next ) + false exit + then + else ( #needed ) + dup dirent-len@ <= if ( #needed ) + \ Reuse deleted-but-present dirent + drop ( ) + dirent-len@ ( offset-to-next ) + false exit + then ( #needed ) + then ( #needed ) + next-dirent ( #needed ) + until ( #needed ) + drop true +; + \ a directory entry needs 8+n 4-aligned bytes, where n is the name length \ the last entry has a larger size; it points to the end of the block -: (last-dirent) ( -- penultimate-offset last-offset ) - diroff off 0 0 - begin ( previous' last' ) - nip diroff @ ( previous last ) - dirent la1+ short@ ( previous last rec-len ) - dup diroff @ + bsize < ( previous last rec-len not-end? ) - over dirent la1+ wa1+ short@ >reclen = and ( previous last rec-len not-end? ) - while ( previous last rec-len ) - diroff +! ( previous last ) - repeat ( previous last rec-len ) - drop +: (last-dirent) ( -- penultimate-offset ) + diroff off 0 + begin ( last ) + dirent-len@ ( last rec-len ) + dup diroff @ + bsize < ( last rec-len not-end? ) +\ over dirent-reclen = and ( last rec-len not-end? ) + while ( last rec-len ) + nip diroff @ swap ( last' rec-len ) + diroff +! ( last ) + repeat ( last ) + drop ( last ) ; : last-dirent ( -- free-bytes ) file-size bsize /mod swap 0= if 1- then to lblk# ( ) lblk# >pblk# to dir-block# - (last-dirent) 2drop - dirent la1+ dup short@ swap wa1+ short@ >reclen - + (last-dirent) drop + dirent-len@ dirent-reclen - ; : set-dirent ( name$ rec-len inode# -- ) dirent int! ( name$ rec-len ) - dirent la1+ short! ( name$ ) - dup dirent la1+ wa1+ short! - dirent la1+ 2 wa+ swap move + dirent-len! ( name$ ) + dup dirent-namelen! ( name$ ) + \ XXX set actual file type here if EXT2_FEATURE_INCOMPAT_FILETYPE + 0 dirent-type! ( name$ ) + dirent-nameadr swap move ( ) update ;
+: to-previous-dirent ( -- ) + diroff @ ( this ) + 0 diroff ! ( this ) + begin ( this ) + dup diroff @ dirent-len@ + <> ( this not-found? ) + while ( this ) + dirent-len@ diroff +! ( this ) + repeat ( this ) + diroff @ swap - totoff +! ( ) +; + \ delete directory entry at diroff : del-dirent ( -- error? ) - diroff @ >r - (last-dirent) dup r@ = if ( prev last ) - \ current entry is the last - r> 2drop ( prev ) - diroff @ 0= abort" delete this block in directory" \ XXX last is also first - dirent bsize diroff @ - erase ( prev ) - else ( prev last ) - nip ( last ) - r> diroff ! ( last ) - dirent dup la1+ wa1+ short@ >reclen ( last dirent oldlen ) - rot over - -rot ( last' dirent oldlen ) - 2dup + -rot ( last' nextent dirent reclen ) - diroff @ + bsize swap - move ( last' ) - then ( last ) - dup diroff ! - bsize swap - dirent la1+ short! + diroff @ if + \ Not first dirent in block; coalesce with previous + dirent-len@ ( deleted-len ) + to-previous-dirent ( deleted-len ) + dirent-len@ + dirent-len! ( ) + dirent dirent-reclen + ( adr ) + dirent-len@ dirent-reclen - erase ( ) + else + \ First dirent in block; zap its inode + 0 dirent-inode! + + then update false ; @@ -113,19 +171,16 @@ : ($create) ( name$ mode -- error? ) >r ( name$ ) \ check for room in the directory, and expand it if necessary - dup >reclen last-dirent tuck < if ( name$ free ) - - \ there is room. update previous entry, and point to new entry - dirent la1+ wa1+ short@ >reclen ( name$ free old-len ) - dup dirent la1+ short! diroff +! ( name$ free ) - else ( name$ free ) + dup >reclen no-dir-space? if ( name$ new-reclen ) \ doesn't fit, allocate more room - drop bsize ( name$ bsize ) + bsize ( name$ bsize ) append-block lblk#++ get-dirblk drop then ( name$ rec-len ) + + \ At this point dirent points to the place for the new dirent alloc-inode set-dirent false ( error? ) - r> file-handle init-inode + r> dirent-inode@ init-inode ;
\ On entry: @@ -138,7 +193,9 @@ \ totoff @ is the overall offset of the directory entry that matches name$ : lookup ( name$ -- not-found? ) begin - 2dup file-name $= if 2drop false exit then + dirent-inode@ if \ inode=0 for a deleted dirent at the beginning of a block + 2dup file-name $= if 2drop false exit then + then next-dirent until 2drop true @@ -257,7 +314,7 @@ r> to inode# ;
-\ Linux sometimes leaves a deleted file in the directory with an inode of 0 +\ Deleted files at the beginning of a directory block have inode=0 : next-file-info ( id -- false | id' s m h d m y len attributes name$ true ) dup if begin
Modified: ofw/fs/ext2fs/layout.fth =================================================================== --- ofw/fs/ext2fs/layout.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/layout.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -221,19 +221,20 @@
\ **** Allocate memory for necessary data structures : allocate-buffers ( -- error? ) - /super-block alloc-mem is super-block + init-io + /super-block do-alloc is super-block get-super-block ?dup if - super-block /super-block free-mem exit + super-block /super-block do-free exit then
- /gds alloc-mem is gds + /gds do-alloc is gds gds /gds gds-block# read-ublocks dup if - gds /gds free-mem - super-block /super-block free-mem exit + gds /gds do-free + super-block /super-block do-free exit then
bsize /buf-hdr + dup to /buffer - #bufs * alloc-mem is block-bufs + #bufs * do-alloc is block-bufs empty-buffers
bsize /l / dup to #ind-blocks1 ( #ind-blocks1 ) @@ -242,9 +243,9 @@ ;
: release-buffers ( -- ) - gds /gds free-mem - block-bufs /buffer #bufs * free-mem - super-block /super-block free-mem + gds /gds do-free + block-bufs /buffer #bufs * do-free + super-block /super-block do-free ;
\ LICENSE_BEGIN
Modified: ofw/fs/ext2fs/methods.fth =================================================================== --- ofw/fs/ext2fs/methods.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/methods.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -7,6 +7,8 @@
external
+: free-bytes ( -- d ) total-free-blocks bsize um* ; + : $create ( name$ -- error? ) o# 100666 ($create) ; @@ -103,7 +105,7 @@ \ XXX I am sceptical about this line. dup 0> if lblk#++ then ( actual ) true to modified? - flush \ XXX kludge for tests +\ flush \ XXX kludge for tests ;
: $ext2fsopen ( adr len mode -- false | fid fmode size align close seek write read true )
Modified: ofw/fs/ext2fs/sb.fth =================================================================== --- ofw/fs/ext2fs/sb.fth 2008-09-04 23:43:37 UTC (rev 922) +++ ofw/fs/ext2fs/sb.fth 2008-09-07 19:23:04 UTC (rev 923) @@ -8,6 +8,8 @@ 1024 constant /super-block h# ef53 constant fs-magic
+0 instance partition-offset + 0 instance value super-block 0 instance value gds
@@ -20,9 +22,11 @@ \ superblock data : +sbl ( index -- value ) super-block swap la+ int@ ; : +sbw ( index -- value ) super-block swap wa+ short@ ; +: datablock0 ( -- n ) 5 +sbl ; : logbsize ( -- n ) 6 +sbl 1+ ; : bsize ( -- n ) 1024 6 +sbl lshift ; \ 1024 : /frag ( -- n ) 1024 7 +sbl lshift ; \ 1024 +: bpg ( -- n ) 8 +sbl ; \ h#2000 blocks_per_group : fpg ( -- n ) 9 +sbl ; \ h#2000 frags_per_group : ipg ( -- n ) 10 +sbl ; \ h#790 inodes_per_group : magic ( -- n ) 28 +sbw ; @@ -36,31 +40,49 @@
\ : total-inodes ( -- n ) 0 +sbl ; : total-blocks ( -- n ) 1 +sbl ; -\ : total-free-blocks ( -- n ) 3 +sbl ; +: total-free-blocks ( -- n ) 3 +sbl ; \ : total-free-inodes ( -- n ) 4 +sbl ; \ : total-free-blocks+! ( -- n ) 3 +sbl + super-block 3 la+ int! ; \ : total-free-inodes+! ( -- n ) 4 +sbl + super-block 4 la+ int! ; : total-free-blocks! ( -- n ) super-block 3 la+ int! ; : total-free-inodes! ( -- n ) super-block 4 la+ int! ; -: #groups ( -- n ) total-blocks fpg ceiling ; +: #groups ( -- n ) total-blocks bpg ceiling ;
\ Don't write to a disk that uses extensions we don't understand : unknown-extensions? ( -- unsafe? ) - 0 super-block h# 54 + h# 14 bounds do i l@ or 4 +loop 0<> + 24 +sbl 4 and if ." ext3 journal needs recovery" cr then + + 23 +sbl h# ffffffff invert and \ Accept all compat extensions + 24 +sbl h# 00000002 invert and or \ Incompatible - accept FILETYPE + 25 +sbl h# 00000001 invert and or \ RO - accept SPARSE_SUPER ;
+: do-alloc ( adr len -- ) " dma-alloc" $call-parent ; +: do-free ( adr len -- ) " dma-free" $call-parent ; + +: init-io ( -- ) + " offset-low" $call-parent " offset-high" $call-parent + ublock um/mod nip to partition-offset +; + : write-ublocks ( adr len dev-block# -- error? ) - ublock um* " seek" $call-parent ?dup if exit then ( adr len ) - tuck " write" $call-parent <> +\ ublock um* " seek" $call-parent ?dup if exit then ( adr len ) +\ tuck " write" $call-parent <> + partition-offset + swap ublock 1- + 9 rshift ( adr block# #blocks ) + dup >r " write-blocks" $call-parent r> <> ; : put-super-block ( -- error? ) super-block /super-block super-block# write-ublocks ;
: read-ublocks ( adr len dev-block# -- error? ) - ublock um* " seek" $call-parent ?dup if exit then ( adr len ) - tuck " read" $call-parent <> + partition-offset + swap ublock 1- + 9 rshift ( adr block# #blocks ) + dup >r " read-blocks" $call-parent r> <> + +\ ublock um* " seek" $call-parent ?dup if exit then ( adr len ) +\ tuck " read" $call-parent <> ; + : get-super-block ( -- error? ) super-block /super-block super-block# read-ublocks ?dup if exit then
@@ -73,11 +95,13 @@ magic fs-magic <> ;
-: gds-block# ( -- dev-block# ) +: gds-fs-block# ( -- fs-block# ) bsize d# 1024 = if 2 else 1 then ( logical block# ) - bsize ublock / * ( dev-block# ) ; -: /gds ( -- size ) #groups h# 20 * ; +: gds-block# ( -- dev-block# ) + gds-fs-block# bsize ublock / * ( dev-block# ) +; +: /gds ( -- size ) #groups h# 20 * ublock round-up ; : group-desc ( group# -- adr ) h# 20 * gds + ; : gpimin ( group -- block# ) group-desc 2 la+ int@ ; : blkstofrags ( #blocks -- #frags ) ; \ XXX is this needed?