2 * emptydir.c --- clear empty directory blocks
4 * Copyright (C) 1998 Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
11 * This file has the necessary routines to search for empty directory
12 * blocks and get rid of them.
22 struct empty_dir_info_struct
{
23 ext2_dblist empty_dblist
;
24 ext2fs_block_bitmap empty_dir_blocks
;
25 ext2fs_inode_bitmap dir_map
;
28 struct ext2_inode inode
;
33 typedef struct empty_dir_info_struct
*empty_dir_info
;
35 extern empty_dir_info
init_empty_dir(e2fsck_t ctx
);
36 extern void free_empty_dirblock(empty_dir_info edi
);
37 extern void add_empty_dirblock(empty_dir_info edi
,
38 struct ext2_db_entry2
*db
);
39 extern void process_empty_dirblock(e2fsck_t ctx
, empty_dir_info edi
);
42 empty_dir_info
init_empty_dir(e2fsck_t ctx
)
47 edi
= malloc(sizeof(struct empty_dir_info_struct
));
51 memset(edi
, 0, sizeof(struct empty_dir_info_struct
));
53 retval
= ext2fs_init_dblist(ctx
->fs
, &edi
->empty_dblist
);
57 retval
= ext2fs_allocate_block_bitmap(ctx
->fs
, _("empty dirblocks"),
58 &edi
->empty_dir_blocks
);
62 retval
= ext2fs_allocate_inode_bitmap(ctx
->fs
, _("empty dir map"),
70 free_empty_dirblock(edi
);
74 void free_empty_dirblock(empty_dir_info edi
)
78 if (edi
->empty_dblist
)
79 ext2fs_free_dblist(edi
->empty_dblist
);
80 if (edi
->empty_dir_blocks
)
81 ext2fs_free_block_bitmap(edi
->empty_dir_blocks
);
83 ext2fs_free_inode_bitmap(edi
->dir_map
);
85 memset(edi
, 0, sizeof(struct empty_dir_info_struct
));
89 void add_empty_dirblock(empty_dir_info edi
,
90 struct ext2_db_entry2
*db
)
96 return; /* Inode number 11 is usually lost+found */
98 printf(_("Empty directory block %u (#%d) in inode %u\n"),
99 db
->blk
, db
->blockcnt
, db
->ino
);
101 ext2fs_mark_block_bitmap2(edi
->empty_dir_blocks
, db
->blk
);
102 if (ext2fs_test_inode_bitmap(edi
->dir_map
, db
->ino
))
104 ext2fs_mark_inode_bitmap(edi
->dir_map
, db
->ino
);
106 ext2fs_add_dir_block2(edi
->empty_dblist
, db
->ino
,
107 db
->blk
, db
->blockcnt
);
111 * Helper function used by fix_directory.
113 * XXX need to finish this. General approach is to use bmap to
114 * iterate over all of the logical blocks using the bmap function, and
115 * copy the block reference as necessary. Big question --- what do
116 * about error recovery?
118 * Also question --- how to free the indirect blocks.
120 int empty_pass1(ext2_filsys fs
, blk64_t
*block_nr
, e2_blkcnt_t blockcnt
,
121 blk64_t ref_block
, int ref_offset
, void *priv_data
)
123 empty_dir_info edi
= (empty_dir_info
) priv_data
;
124 blk64_t block
, new_block
;
131 retval
= ext2fs_bmap2(fs
, edi
->ino
, &edi
->inode
,
132 edi
->block_buf
, 0, edi
->logblk
, 0,
135 return DIRENT_ABORT
; /* XXX what to do? */
139 } while (ext2fs_test_block_bitmap2(edi
->empty_dir_blocks
, new_block
));
141 if (new_block
== block
)
145 *block_nr
= new_block
;
146 return BLOCK_CHANGED
;
149 static int fix_directory(ext2_filsys fs
,
150 struct ext2_db_entry2
*db
,
155 empty_dir_info edi
= (empty_dir_info
) priv_data
;
158 edi
->freed_blocks
= 0;
161 retval
= ext2fs_read_inode(fs
, db
->ino
, &edi
->inode
);
165 retval
= ext2fs_block_iterate3(fs
, db
->ino
, 0, edi
->block_buf
,
170 if (edi
->freed_blocks
) {
171 edi
->inode
.i_size
-= edi
->freed_blocks
* fs
->blocksize
;
172 ext2fs_iblk_add_blocks(fs
, &edi
->inode
, edi
->freed_blocks
);
173 retval
= ext2fs_write_inode(fs
, db
->ino
, &edi
->inode
);
180 void process_empty_dirblock(e2fsck_t ctx
, empty_dir_info edi
)
185 edi
->block_buf
= malloc(ctx
->fs
->blocksize
* 3);
187 if (edi
->block_buf
) {
188 (void) ext2fs_dblist_iterate2(edi
->empty_dblist
,
189 fix_directory
, &edi
);
191 free(edi
->block_buf
);
192 free_empty_dirblock(edi
);