4 * PROGRAMMER: Matt Wu <mattwu@163.com>
5 * HOMEPAGE: http://ext2.yeah.net
8 /* INCLUDES **************************************************************/
13 /* DEFINITIONS ***********************************************************/
15 extern char *device_name
;
17 /* FUNCTIONS *************************************************************/
21 * Return the group # of an inode number
23 int ext2_group_of_ino(PEXT2_FILESYS fs
, ULONG ino
)
25 return (ino
- 1) / fs
->ext2_sb
->s_inodes_per_group
;
29 * Return the group # of a block
31 int ext2_group_of_blk(PEXT2_FILESYS fs
, ULONG blk
)
33 return (blk
- fs
->ext2_sb
->s_first_data_block
) /
34 fs
->ext2_sb
->s_blocks_per_group
;
37 void ext2_inode_alloc_stats2(PEXT2_FILESYS fs
, ULONG ino
,
40 int group
= ext2_group_of_ino(fs
, ino
);
43 ext2_mark_inode_bitmap(fs
->inode_map
, ino
);
45 ext2_unmark_inode_bitmap(fs
->inode_map
, ino
);
47 fs
->group_desc
[group
].bg_free_inodes_count
-= inuse
;
50 fs
->group_desc
[group
].bg_used_dirs_count
+= inuse
;
52 fs
->ext2_sb
->s_free_inodes_count
-= inuse
;
56 void ext2_inode_alloc_stats(PEXT2_FILESYS fs
, ULONG ino
, int inuse
)
58 ext2_inode_alloc_stats2(fs
, ino
, inuse
, 0);
61 void ext2_block_alloc_stats(PEXT2_FILESYS fs
, ULONG blk
, int inuse
)
63 int group
= ext2_group_of_blk(fs
, blk
);
66 ext2_mark_block_bitmap(fs
->block_map
, blk
);
68 ext2_unmark_block_bitmap(fs
->block_map
, blk
);
70 fs
->group_desc
[group
].bg_free_blocks_count
-= inuse
;
71 fs
->ext2_sb
->s_free_blocks_count
-= inuse
;
75 bool ext2_allocate_tables(PEXT2_FILESYS Ext2Sys
)
80 for (i
= 0; i
< Ext2Sys
->group_desc_count
; i
++)
82 retval
= ext2_allocate_group_table(Ext2Sys
, i
, Ext2Sys
->block_map
);
92 bool ext2_allocate_group_table(PEXT2_FILESYS fs
, ULONG group
,
93 PEXT2_BLOCK_BITMAP bmap
)
96 ULONG group_blk
, start_blk
, last_blk
, new_blk
, blk
, j
;
98 group_blk
= fs
->ext2_sb
->s_first_data_block
+
99 (group
* fs
->ext2_sb
->s_blocks_per_group
);
101 last_blk
= group_blk
+ fs
->ext2_sb
->s_blocks_per_group
;
102 if (last_blk
>= fs
->ext2_sb
->s_blocks_count
)
103 last_blk
= fs
->ext2_sb
->s_blocks_count
- 1;
105 start_blk
= group_blk
+ 3 + fs
->desc_blocks
;
106 if (start_blk
> last_blk
)
107 start_blk
= group_blk
;
110 bmap
= fs
->block_map
;
113 * Allocate the inode table
115 if (!fs
->group_desc
[group
].bg_inode_table
)
117 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
118 fs
->inode_blocks_per_group
,
123 for (j
=0, blk
= new_blk
;
124 j
< fs
->inode_blocks_per_group
;
126 ext2_mark_block_bitmap(bmap
, blk
);
128 fs
->group_desc
[group
].bg_inode_table
= new_blk
;
132 * Allocate the block and inode bitmaps, if necessary
136 start_blk
+= fs
->inode_blocks_per_group
;
137 start_blk
+= ((fs
->stride
* group
) %
138 (last_blk
- start_blk
));
139 if (start_blk
> last_blk
)
140 /* should never happen */
141 start_blk
= group_blk
;
145 start_blk
= group_blk
;
148 if (!fs
->group_desc
[group
].bg_block_bitmap
)
150 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
154 retval
= ext2_get_free_blocks(fs
, group_blk
,
155 last_blk
, 1, bmap
, &new_blk
);
160 ext2_mark_block_bitmap(bmap
, new_blk
);
161 fs
->group_desc
[group
].bg_block_bitmap
= new_blk
;
164 if (!fs
->group_desc
[group
].bg_inode_bitmap
)
166 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
169 retval
= ext2_get_free_blocks(fs
, group_blk
,
170 last_blk
, 1, bmap
, &new_blk
);
174 ext2_mark_block_bitmap(bmap
, new_blk
);
175 fs
->group_desc
[group
].bg_inode_bitmap
= new_blk
;
182 bool ext2_get_free_blocks(PEXT2_FILESYS fs
, ULONG start
, ULONG finish
,
183 int num
, PEXT2_BLOCK_BITMAP map
, ULONG
*ret
)
194 b
= fs
->ext2_sb
->s_first_data_block
;
204 if (b
+num
-1 > fs
->ext2_sb
->s_blocks_count
)
205 b
= fs
->ext2_sb
->s_first_data_block
;
207 if (ext2_test_block_bitmap_range(map
, b
, num
))
215 } while (b
!= finish
);
221 bool write_inode_tables(PEXT2_FILESYS fs
)
227 for (i
= 0; (ULONG
)i
< fs
->group_desc_count
; i
++)
229 blk
= fs
->group_desc
[i
].bg_inode_table
;
230 num
= fs
->inode_blocks_per_group
;
232 retval
= zero_blocks(fs
, blk
, num
, &blk
, &num
);
235 DPRINT1("\nMke2fs: Could not write %lu blocks "
236 "in inode table starting at %lu.\n",
239 zero_blocks(0, 0, 0, 0, 0);
244 zero_blocks(0, 0, 0, 0, 0);
251 * Stupid algorithm --- we now just search forward starting from the
252 * goal. Should put in a smarter one someday....
254 bool ext2_new_block(PEXT2_FILESYS fs
, ULONG goal
,
255 PEXT2_BLOCK_BITMAP map
, ULONG
*ret
)
265 if (!goal
|| (goal
>= fs
->ext2_sb
->s_blocks_count
))
266 goal
= fs
->ext2_sb
->s_first_data_block
;
272 if (!ext2_test_block_bitmap(map
, i
))
280 if (i
>= fs
->ext2_sb
->s_blocks_count
)
281 i
= fs
->ext2_sb
->s_first_data_block
;
290 * This function zeros out the allocated block, and updates all of the
291 * appropriate filesystem records.
293 bool ext2_alloc_block(PEXT2_FILESYS fs
, ULONG goal
, ULONG
*ret
)
299 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, fs
->blocksize
);
305 retval
= ext2_read_block_bitmap(fs
);
310 retval
= ext2_new_block(fs
, goal
, 0, &block
);
315 retval
= NT_SUCCESS(Ext2WriteDisk(
317 ((LONGLONG
)block
* fs
->blocksize
),
318 fs
->blocksize
, (unsigned char *)buf
));
325 ext2_block_alloc_stats(fs
, block
, +1);
330 RtlFreeHeap(RtlGetProcessHeap(), 0, buf
);
339 RtlFreeHeap(RtlGetProcessHeap(), 0, buf
);
347 * Create new directory block
349 bool ext2_new_dir_block(PEXT2_FILESYS fs
, ULONG dir_ino
,
350 ULONG parent_ino
, char **block
)
352 PEXT2_DIR_ENTRY dir
= NULL
;
357 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, fs
->blocksize
);
361 dir
= (PEXT2_DIR_ENTRY
) buf
;
362 dir
->rec_len
= fs
->blocksize
;
366 if (fs
->ext2_sb
->s_feature_incompat
&
367 EXT2_FEATURE_INCOMPAT_FILETYPE
)
368 filetype
= EXT2_FT_DIR
<< 8;
370 * Set up entry for '.'
372 dir
->inode
= dir_ino
;
373 dir
->name_len
= 1 | filetype
;
375 rec_len
= dir
->rec_len
- EXT2_DIR_REC_LEN(1);
376 dir
->rec_len
= EXT2_DIR_REC_LEN(1);
379 * Set up entry for '..'
381 dir
= (struct ext2_dir_entry
*) (buf
+ dir
->rec_len
);
382 dir
->rec_len
= rec_len
;
383 dir
->inode
= parent_ino
;
384 dir
->name_len
= 2 | filetype
;
394 bool ext2_write_block(PEXT2_FILESYS fs
, ULONG block
, void *inbuf
)
398 retval
= NT_SUCCESS(Ext2WriteDisk(
400 ((ULONGLONG
)block
* fs
->blocksize
),
401 fs
->blocksize
, (unsigned char *)inbuf
));
406 bool ext2_read_block(PEXT2_FILESYS fs
, ULONG block
, void *inbuf
)
410 retval
= NT_SUCCESS(Ext2ReadDisk(
412 ((ULONGLONG
)block
* fs
->blocksize
),
413 fs
->blocksize
, (unsigned char *)inbuf
));