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?