@@ -255,6 +255,7 @@ struct ex_inode *ex_inode_set(struct ex_inode *dir, const char *name,
255255
256256 if (!entry_address ) {
257257 info ("unable to find space for inode in dirinode" );
258+ // XXX: allocate indirect block
258259 return NULL ;
259260 }
260261
@@ -644,6 +645,58 @@ int ex_inode_rename(struct ex_inode *from_inode, struct ex_inode *to_inode,
644645 return 0 ;
645646}
646647
648+ static inline int ex_indirect_block_is_allocated (struct ex_inode * i , size_t n ) {
649+ return i -> blocks [n + EX_DIRECT_BLOCKS ].address ;
650+ }
651+
652+ static inline int ex_indirect_block_out_of_range (size_t n ) {
653+ return n > EX_INDIRECT_BLOCKS ;
654+ }
655+
656+ static inline int ex_indirect_block_should_be_loaded (struct ex_block_iterator * it ,
657+ size_t indirect_block_no ) {
658+ return it -> indirect_block_no != indirect_block_no || !it -> indirect .data ;
659+ }
660+
661+ struct ex_inode_block ex_inode_block_iterate_indirect (struct ex_inode * inode ,
662+ struct ex_block_iterator * it ) {
663+ assert (it -> block_number >= EX_DIRECT_BLOCKS );
664+
665+ size_t indirect_block_no = (it -> block_number - EX_DIRECT_BLOCKS ) / EX_BLOCK_SIZE ;
666+ size_t block_idx = (it -> block_number - EX_DIRECT_BLOCKS ) % EX_BLOCK_SIZE ;
667+
668+ if (ex_indirect_block_out_of_range (indirect_block_no ) ||
669+ !ex_indirect_block_is_allocated (inode , indirect_block_no )) {
670+
671+ it -> last_block .address = EX_BLOCK_INVALID_ADDRESS ;
672+ it -> last_block .data = NULL ;
673+ it -> last_block .id = EX_BLOCK_INVALID_ID ;
674+
675+ goto done ;
676+ }
677+
678+ if (ex_indirect_block_should_be_loaded (it , indirect_block_no )) {
679+ size_t indirect_block_address = inode -> blocks [indirect_block_no + EX_DIRECT_BLOCKS ].address ;
680+ ssize_t readed = 0 ;
681+ (void )ex_device_read_to_buffer (& readed , it -> indirect_buffer ,
682+ indirect_block_address , EX_BLOCK_SIZE );
683+ it -> indirect .data = it -> indirect_buffer ;
684+ }
685+
686+ // read the block
687+ size_t block_address = it -> indirect .data [block_idx ];
688+ // read the blocks data
689+ ssize_t readed = 0 ;
690+ (void )ex_device_read_to_buffer (& readed , it -> buffer , block_address , EX_BLOCK_SIZE );
691+
692+ it -> last_block .address = block_address ;
693+ it -> last_block .id = it -> block_number ;
694+ it -> last_block .data = it -> buffer ;
695+
696+ done :
697+ return it -> last_block ;
698+ }
699+
647700struct ex_inode_block ex_inode_block_iterate (struct ex_inode * inode ,
648701 struct ex_block_iterator * it ) {
649702
@@ -657,20 +710,18 @@ struct ex_inode_block ex_inode_block_iterate(struct ex_inode *inode,
657710 .address = EX_BLOCK_INVALID_ADDRESS };
658711
659712 if (it -> block_number >= EX_DIRECT_BLOCKS ) {
660- goto done ;
713+ return ex_inode_block_iterate_indirect ( inode , it ) ;
661714 }
662715
663716 block .address = inode -> blocks [it -> block_number ].address ;
664717 block .data = it -> buffer ;
718+ block .id = it -> block_number ;
665719
666- // XXX: add buffer into ex_block_iterator and use ex_device_read_to_buffer
667- // handle read error
668- ssize_t readed = 0 ;
669720 // XXX: handle read error
721+ ssize_t readed = 0 ;
670722 (void )ex_device_read_to_buffer (& readed , it -> buffer ,
671723 block .address , EX_BLOCK_SIZE );
672724
673- done :
674725 it -> last_block = block ;
675726 return block ;
676727}
0 commit comments