2 * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
4 * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Library
8 * General Public License, version 2.
20 #ifdef HAVE_SYS_STAT_H
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
31 static errcode_t
write_bitmaps(ext2_filsys fs
, int do_inode
, int do_block
)
35 int block_nbytes
, inode_nbytes
;
38 char *block_buf
= NULL
, *inode_buf
= NULL
;
41 blk64_t blk_itr
= EXT2FS_B2C(fs
, fs
->super
->s_first_data_block
);
42 ext2_ino_t ino_itr
= 1;
44 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
46 if (!(fs
->flags
& EXT2_FLAG_RW
))
47 return EXT2_ET_RO_FILSYS
;
49 csum_flag
= ext2fs_has_group_desc_csum(fs
);
51 inode_nbytes
= block_nbytes
= 0;
53 block_nbytes
= EXT2_CLUSTERS_PER_GROUP(fs
->super
) / 8;
54 retval
= io_channel_alloc_buf(fs
->io
, 0, &block_buf
);
57 memset(block_buf
, 0xff, fs
->blocksize
);
60 inode_nbytes
= (size_t)
61 ((EXT2_INODES_PER_GROUP(fs
->super
)+7) / 8);
62 retval
= io_channel_alloc_buf(fs
->io
, 0, &inode_buf
);
65 memset(inode_buf
, 0xff, fs
->blocksize
);
68 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
70 goto skip_block_bitmap
;
72 if (csum_flag
&& ext2fs_bg_flags_test(fs
, i
, EXT2_BG_BLOCK_UNINIT
)
74 goto skip_this_block_bitmap
;
76 retval
= ext2fs_get_block_bitmap_range2(fs
->block_map
,
77 blk_itr
, block_nbytes
<< 3, block_buf
);
81 if (i
== fs
->group_desc_count
- 1) {
82 /* Force bitmap padding for the last group */
83 nbits
= EXT2FS_NUM_B2C(fs
,
84 ((ext2fs_blocks_count(fs
->super
)
85 - (__u64
) fs
->super
->s_first_data_block
)
86 % (__u64
) EXT2_BLOCKS_PER_GROUP(fs
->super
)));
88 for (j
= nbits
; j
< fs
->blocksize
* 8; j
++)
89 ext2fs_set_bit(j
, block_buf
);
92 retval
= ext2fs_block_bitmap_csum_set(fs
, i
, block_buf
,
96 ext2fs_group_desc_csum_set(fs
, i
);
97 fs
->flags
|= EXT2_FLAG_DIRTY
;
99 blk
= ext2fs_block_bitmap_loc(fs
, i
);
101 retval
= io_channel_write_blk64(fs
->io
, blk
, 1,
104 retval
= EXT2_ET_BLOCK_BITMAP_WRITE
;
108 skip_this_block_bitmap
:
109 blk_itr
+= block_nbytes
<< 3;
115 if (csum_flag
&& ext2fs_bg_flags_test(fs
, i
, EXT2_BG_INODE_UNINIT
)
117 goto skip_this_inode_bitmap
;
119 retval
= ext2fs_get_inode_bitmap_range2(fs
->inode_map
,
120 ino_itr
, inode_nbytes
<< 3, inode_buf
);
124 retval
= ext2fs_inode_bitmap_csum_set(fs
, i
, inode_buf
,
128 ext2fs_group_desc_csum_set(fs
, i
);
129 fs
->flags
|= EXT2_FLAG_DIRTY
;
131 blk
= ext2fs_inode_bitmap_loc(fs
, i
);
133 retval
= io_channel_write_blk64(fs
->io
, blk
, 1,
136 retval
= EXT2_ET_INODE_BITMAP_WRITE
;
140 skip_this_inode_bitmap
:
141 ino_itr
+= inode_nbytes
<< 3;
145 fs
->flags
&= ~EXT2_FLAG_BB_DIRTY
;
146 ext2fs_free_mem(&block_buf
);
149 fs
->flags
&= ~EXT2_FLAG_IB_DIRTY
;
150 ext2fs_free_mem(&inode_buf
);
155 ext2fs_free_mem(&inode_buf
);
157 ext2fs_free_mem(&block_buf
);
161 static errcode_t
mark_uninit_bg_group_blocks(ext2_filsys fs
)
165 ext2fs_block_bitmap bmap
= fs
->block_map
;
167 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
168 if (!ext2fs_bg_flags_test(fs
, i
, EXT2_BG_BLOCK_UNINIT
))
171 ext2fs_reserve_super_and_bgd(fs
, i
, bmap
);
174 * Mark the blocks used for the inode table
176 blk
= ext2fs_inode_table_loc(fs
, i
);
178 ext2fs_mark_block_bitmap_range2(bmap
, blk
,
179 fs
->inode_blocks_per_group
);
182 * Mark block used for the block bitmap
184 blk
= ext2fs_block_bitmap_loc(fs
, i
);
186 ext2fs_mark_block_bitmap2(bmap
, blk
);
189 * Mark block used for the inode bitmap
191 blk
= ext2fs_inode_bitmap_loc(fs
, i
);
193 ext2fs_mark_block_bitmap2(bmap
, blk
);
198 static int bitmap_tail_verify(unsigned char *bitmap
, int first
, int last
)
202 for (i
= first
; i
<= last
; i
++)
203 if (bitmap
[i
] != 0xff)
208 static errcode_t
read_bitmaps(ext2_filsys fs
, int do_inode
, int do_block
)
211 char *block_bitmap
= 0, *inode_bitmap
= 0;
214 int block_nbytes
= EXT2_CLUSTERS_PER_GROUP(fs
->super
) / 8;
215 int inode_nbytes
= EXT2_INODES_PER_GROUP(fs
->super
) / 8;
220 blk64_t blk_itr
= EXT2FS_B2C(fs
, fs
->super
->s_first_data_block
);
222 ext2_ino_t ino_itr
= 1;
225 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
227 if ((block_nbytes
> (int) fs
->blocksize
) ||
228 (inode_nbytes
> (int) fs
->blocksize
))
229 return EXT2_ET_CORRUPT_SUPERBLOCK
;
231 fs
->write_bitmaps
= ext2fs_write_bitmaps
;
233 csum_flag
= ext2fs_has_group_desc_csum(fs
);
235 retval
= ext2fs_get_mem(strlen(fs
->device_name
) + 80, &buf
);
240 ext2fs_free_block_bitmap(fs
->block_map
);
241 strcpy(buf
, "block bitmap for ");
242 strcat(buf
, fs
->device_name
);
243 retval
= ext2fs_allocate_block_bitmap(fs
, buf
, &fs
->block_map
);
246 retval
= io_channel_alloc_buf(fs
->io
, 0, &block_bitmap
);
253 ext2fs_free_inode_bitmap(fs
->inode_map
);
254 strcpy(buf
, "inode bitmap for ");
255 strcat(buf
, fs
->device_name
);
256 retval
= ext2fs_allocate_inode_bitmap(fs
, buf
, &fs
->inode_map
);
259 retval
= io_channel_alloc_buf(fs
->io
, 0, &inode_bitmap
);
264 ext2fs_free_mem(&buf
);
266 if (fs
->flags
& EXT2_FLAG_IMAGE_FILE
) {
267 blk
= (ext2fs_le32_to_cpu(fs
->image_header
->offset_inodemap
) / fs
->blocksize
);
268 ino_cnt
= fs
->super
->s_inodes_count
;
269 while (inode_bitmap
&& ino_cnt
> 0) {
270 retval
= io_channel_read_blk64(fs
->image_io
, blk
++,
274 cnt
= fs
->blocksize
<< 3;
277 retval
= ext2fs_set_inode_bitmap_range2(fs
->inode_map
,
278 ino_itr
, cnt
, inode_bitmap
);
284 blk
= (ext2fs_le32_to_cpu(fs
->image_header
->offset_blockmap
) /
286 blk_cnt
= EXT2_GROUPS_TO_CLUSTERS(fs
->super
,
287 fs
->group_desc_count
);
288 while (block_bitmap
&& blk_cnt
> 0) {
289 retval
= io_channel_read_blk64(fs
->image_io
, blk
++,
293 cnt
= fs
->blocksize
<< 3;
296 retval
= ext2fs_set_block_bitmap_range2(fs
->block_map
,
297 blk_itr
, cnt
, block_bitmap
);
303 goto success_cleanup
;
306 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
308 blk
= ext2fs_block_bitmap_loc(fs
, i
);
310 ext2fs_bg_flags_test(fs
, i
, EXT2_BG_BLOCK_UNINIT
) &&
311 ext2fs_group_desc_csum_verify(fs
, i
)) ||
312 (blk
>= ext2fs_blocks_count(fs
->super
)))
315 retval
= io_channel_read_blk64(fs
->io
, blk
,
318 retval
= EXT2_ET_BLOCK_BITMAP_READ
;
321 /* verify block bitmap checksum */
323 EXT2_FLAG_IGNORE_CSUM_ERRORS
) &&
324 !ext2fs_block_bitmap_csum_verify(fs
, i
,
325 block_bitmap
, block_nbytes
)) {
327 EXT2_ET_BLOCK_BITMAP_CSUM_INVALID
;
330 if (!bitmap_tail_verify((unsigned char *) block_bitmap
,
331 block_nbytes
, fs
->blocksize
- 1))
332 tail_flags
|= EXT2_FLAG_BBITMAP_TAIL_PROBLEM
;
334 memset(block_bitmap
, 0, block_nbytes
);
335 cnt
= block_nbytes
<< 3;
336 retval
= ext2fs_set_block_bitmap_range2(fs
->block_map
,
337 blk_itr
, cnt
, block_bitmap
);
340 blk_itr
+= block_nbytes
<< 3;
343 blk
= ext2fs_inode_bitmap_loc(fs
, i
);
345 ext2fs_bg_flags_test(fs
, i
, EXT2_BG_INODE_UNINIT
) &&
346 ext2fs_group_desc_csum_verify(fs
, i
)) ||
347 (blk
>= ext2fs_blocks_count(fs
->super
)))
350 retval
= io_channel_read_blk64(fs
->io
, blk
,
353 retval
= EXT2_ET_INODE_BITMAP_READ
;
357 /* verify inode bitmap checksum */
359 EXT2_FLAG_IGNORE_CSUM_ERRORS
) &&
360 !ext2fs_inode_bitmap_csum_verify(fs
, i
,
361 inode_bitmap
, inode_nbytes
)) {
363 EXT2_ET_INODE_BITMAP_CSUM_INVALID
;
366 if (!bitmap_tail_verify((unsigned char *) inode_bitmap
,
367 inode_nbytes
, fs
->blocksize
- 1))
368 tail_flags
|= EXT2_FLAG_IBITMAP_TAIL_PROBLEM
;
370 memset(inode_bitmap
, 0, inode_nbytes
);
371 cnt
= inode_nbytes
<< 3;
372 retval
= ext2fs_set_inode_bitmap_range2(fs
->inode_map
,
373 ino_itr
, cnt
, inode_bitmap
);
376 ino_itr
+= inode_nbytes
<< 3;
380 /* Mark group blocks for any BLOCK_UNINIT groups */
382 retval
= mark_uninit_bg_group_blocks(fs
);
389 ext2fs_free_mem(&inode_bitmap
);
390 fs
->flags
&= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM
;
393 ext2fs_free_mem(&block_bitmap
);
394 fs
->flags
&= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM
;
396 fs
->flags
|= tail_flags
;
401 ext2fs_free_block_bitmap(fs
->block_map
);
405 ext2fs_free_inode_bitmap(fs
->inode_map
);
409 ext2fs_free_mem(&inode_bitmap
);
411 ext2fs_free_mem(&block_bitmap
);
413 ext2fs_free_mem(&buf
);
417 errcode_t
ext2fs_read_inode_bitmap(ext2_filsys fs
)
419 return read_bitmaps(fs
, 1, 0);
422 errcode_t
ext2fs_read_block_bitmap(ext2_filsys fs
)
424 return read_bitmaps(fs
, 0, 1);
427 errcode_t
ext2fs_write_inode_bitmap(ext2_filsys fs
)
429 return write_bitmaps(fs
, 1, 0);
432 errcode_t
ext2fs_write_block_bitmap (ext2_filsys fs
)
434 return write_bitmaps(fs
, 0, 1);
437 errcode_t
ext2fs_read_bitmaps(ext2_filsys fs
)
439 if (fs
->inode_map
&& fs
->block_map
)
442 return read_bitmaps(fs
, !fs
->inode_map
, !fs
->block_map
);
445 errcode_t
ext2fs_write_bitmaps(ext2_filsys fs
)
447 int do_inode
= fs
->inode_map
&& ext2fs_test_ib_dirty(fs
);
448 int do_block
= fs
->block_map
&& ext2fs_test_bb_dirty(fs
);
450 if (!do_inode
&& !do_block
)
453 return write_bitmaps(fs
, do_inode
, do_block
);