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
;
99 group_blk
= fs
->ext2_sb
->s_first_data_block
+
100 (group
* fs
->ext2_sb
->s_blocks_per_group
);
102 last_blk
= group_blk
+ fs
->ext2_sb
->s_blocks_per_group
;
103 if (last_blk
>= fs
->ext2_sb
->s_blocks_count
)
104 last_blk
= fs
->ext2_sb
->s_blocks_count
- 1;
106 start_blk
= group_blk
+ 3 + fs
->desc_blocks
;
107 if (start_blk
> last_blk
)
108 start_blk
= group_blk
;
111 bmap
= fs
->block_map
;
114 * Allocate the inode table
116 if (!fs
->group_desc
[group
].bg_inode_table
)
118 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
119 fs
->inode_blocks_per_group
,
124 for (j
=0, blk
= new_blk
;
125 j
< fs
->inode_blocks_per_group
;
127 ext2_mark_block_bitmap(bmap
, blk
);
129 fs
->group_desc
[group
].bg_inode_table
= new_blk
;
133 * Allocate the block and inode bitmaps, if necessary
137 start_blk
+= fs
->inode_blocks_per_group
;
138 start_blk
+= ((fs
->stride
* group
) %
139 (last_blk
- start_blk
));
140 if (start_blk
> last_blk
)
141 /* should never happen */
142 start_blk
= group_blk
;
146 start_blk
= group_blk
;
149 if (!fs
->group_desc
[group
].bg_block_bitmap
)
151 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
155 retval
= ext2_get_free_blocks(fs
, group_blk
,
156 last_blk
, 1, bmap
, &new_blk
);
161 ext2_mark_block_bitmap(bmap
, new_blk
);
162 fs
->group_desc
[group
].bg_block_bitmap
= new_blk
;
165 if (!fs
->group_desc
[group
].bg_inode_bitmap
)
167 retval
= ext2_get_free_blocks(fs
, start_blk
, last_blk
,
170 retval
= ext2_get_free_blocks(fs
, group_blk
,
171 last_blk
, 1, bmap
, &new_blk
);
175 ext2_mark_block_bitmap(bmap
, new_blk
);
176 fs
->group_desc
[group
].bg_inode_bitmap
= new_blk
;
183 bool ext2_get_free_blocks(PEXT2_FILESYS fs
, ULONG start
, ULONG finish
,
184 int num
, PEXT2_BLOCK_BITMAP map
, ULONG
*ret
)
195 b
= fs
->ext2_sb
->s_first_data_block
;
205 if (b
+num
-1 > fs
->ext2_sb
->s_blocks_count
)
206 b
= fs
->ext2_sb
->s_first_data_block
;
208 if (ext2_test_block_bitmap_range(map
, b
, num
))
216 } while (b
!= finish
);
222 bool write_inode_tables(PEXT2_FILESYS fs
)
228 for (i
= 0; (ULONG
)i
< fs
->group_desc_count
; i
++)
230 blk
= fs
->group_desc
[i
].bg_inode_table
;
231 num
= fs
->inode_blocks_per_group
;
233 retval
= zero_blocks(fs
, blk
, num
, &blk
, &num
);
236 DPRINT1("\nMke2fs: Could not write %lu blocks "
237 "in inode table starting at %lu.\n",
240 zero_blocks(0, 0, 0, 0, 0);
245 zero_blocks(0, 0, 0, 0, 0);
252 * Stupid algorithm --- we now just search forward starting from the
253 * goal. Should put in a smarter one someday....
255 bool ext2_new_block(PEXT2_FILESYS fs
, ULONG goal
,
256 PEXT2_BLOCK_BITMAP map
, ULONG
*ret
)
266 if (!goal
|| (goal
>= fs
->ext2_sb
->s_blocks_count
))
267 goal
= fs
->ext2_sb
->s_first_data_block
;
273 if (!ext2_test_block_bitmap(map
, i
))
281 if (i
>= fs
->ext2_sb
->s_blocks_count
)
282 i
= fs
->ext2_sb
->s_first_data_block
;
291 * This function zeros out the allocated block, and updates all of the
292 * appropriate filesystem records.
294 bool ext2_alloc_block(PEXT2_FILESYS fs
, ULONG goal
, ULONG
*ret
)
300 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, fs
->blocksize
);
306 retval
= ext2_read_block_bitmap(fs
);
311 retval
= ext2_new_block(fs
, goal
, 0, &block
);
316 retval
= NT_SUCCESS(Ext2WriteDisk(
318 ((LONGLONG
)block
* fs
->blocksize
),
319 fs
->blocksize
, (unsigned char *)buf
));
326 ext2_block_alloc_stats(fs
, block
, +1);
331 RtlFreeHeap(RtlGetProcessHeap(), 0, buf
);
340 RtlFreeHeap(RtlGetProcessHeap(), 0, buf
);
348 * Create new directory block
350 bool ext2_new_dir_block(PEXT2_FILESYS fs
, ULONG dir_ino
,
351 ULONG parent_ino
, char **block
)
353 PEXT2_DIR_ENTRY dir
= NULL
;
358 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, fs
->blocksize
);
362 dir
= (PEXT2_DIR_ENTRY
) buf
;
363 dir
->rec_len
= fs
->blocksize
;
367 if (fs
->ext2_sb
->s_feature_incompat
&
368 EXT2_FEATURE_INCOMPAT_FILETYPE
)
369 filetype
= EXT2_FT_DIR
<< 8;
371 * Set up entry for '.'
373 dir
->inode
= dir_ino
;
374 dir
->name_len
= 1 | filetype
;
376 rec_len
= dir
->rec_len
- EXT2_DIR_REC_LEN(1);
377 dir
->rec_len
= EXT2_DIR_REC_LEN(1);
380 * Set up entry for '..'
382 dir
= (struct ext2_dir_entry
*) (buf
+ dir
->rec_len
);
383 dir
->rec_len
= rec_len
;
384 dir
->inode
= parent_ino
;
385 dir
->name_len
= 2 | filetype
;
395 bool ext2_write_block(PEXT2_FILESYS fs
, ULONG block
, void *inbuf
)
399 retval
= NT_SUCCESS(Ext2WriteDisk(
401 ((ULONGLONG
)block
* fs
->blocksize
),
402 fs
->blocksize
, (unsigned char *)inbuf
));
407 bool ext2_read_block(PEXT2_FILESYS fs
, ULONG block
, void *inbuf
)
411 retval
= NT_SUCCESS(Ext2ReadDisk(
413 ((ULONGLONG
)block
* fs
->blocksize
),
414 fs
->blocksize
, (unsigned char *)inbuf
));