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.
21 struct empty_dir_info_struct
{
22 ext2_dblist empty_dblist
;
23 ext2fs_block_bitmap empty_dir_blocks
;
24 ext2fs_inode_bitmap dir_map
;
27 struct ext2_inode inode
;
32 typedef struct empty_dir_info_struct
*empty_dir_info
;
34 extern empty_dir_info
init_empty_dir(e2fsck_t ctx
);
35 extern void free_empty_dirblock(empty_dir_info edi
);
36 extern void add_empty_dirblock(empty_dir_info edi
,
37 struct ext2_db_entry
*db
);
38 extern void process_empty_dirblock(e2fsck_t ctx
, empty_dir_info edi
);
41 empty_dir_info
init_empty_dir(e2fsck_t ctx
)
46 edi
= malloc(sizeof(struct empty_dir_info_struct
));
50 memset(edi
, 0, sizeof(struct empty_dir_info_struct
));
52 retval
= ext2fs_init_dblist(ctx
->fs
, &edi
->empty_dblist
);
56 retval
= ext2fs_allocate_block_bitmap(ctx
->fs
, _("empty dirblocks"),
57 &edi
->empty_dir_blocks
);
61 retval
= ext2fs_allocate_inode_bitmap(ctx
->fs
, _("empty dir map"),
69 free_empty_dirblock(edi
);
73 void free_empty_dirblock(empty_dir_info edi
)
77 if (edi
->empty_dblist
)
78 ext2fs_free_dblist(edi
->empty_dblist
);
79 if (edi
->empty_dir_blocks
)
80 ext2fs_free_block_bitmap(edi
->empty_dir_blocks
);
82 ext2fs_free_inode_bitmap(edi
->dir_map
);
84 memset(edi
, 0, sizeof(struct empty_dir_info_struct
));
88 void add_empty_dirblock(empty_dir_info edi
,
89 struct ext2_db_entry
*db
)
95 return; /* Inode number 11 is usually lost+found */
97 printf(_("Empty directory block %u (#%d) in inode %u\n"),
98 db
->blk
, db
->blockcnt
, db
->ino
);
100 ext2fs_mark_block_bitmap(edi
->empty_dir_blocks
, db
->blk
);
101 if (ext2fs_test_inode_bitmap(edi
->dir_map
, db
->ino
))
103 ext2fs_mark_inode_bitmap(edi
->dir_map
, db
->ino
);
105 ext2fs_add_dir_block(edi
->empty_dblist
, db
->ino
,
106 db
->blk
, db
->blockcnt
);
110 * Helper function used by fix_directory.
112 * XXX need to finish this. General approach is to use bmap to
113 * iterate over all of the logical blocks using the bmap function, and
114 * copy the block reference as necessary. Big question --- what do
115 * about error recovery?
117 * Also question --- how to free the indirect blocks.
119 int empty_pass1(ext2_filsys fs
, blk_t
*block_nr
, e2_blkcnt_t blockcnt
,
120 blk_t ref_block
, int ref_offset
, void *priv_data
)
122 empty_dir_info edi
= (empty_dir_info
) priv_data
;
123 blk_t block
, new_block
;
130 retval
= ext2fs_bmap(fs
, edi
->ino
, &edi
->inode
,
131 edi
->block_buf
, 0, edi
->logblk
,
134 return DIRENT_ABORT
; /* XXX what to do? */
138 } while (ext2fs_test_block_bitmap(edi
->empty_dir_blocks
, new_block
));
140 if (new_block
== block
)
144 *block_nr
= new_block
;
145 return BLOCK_CHANGED
;
148 static int fix_directory(ext2_filsys fs
,
149 struct ext2_db_entry
*db
,
154 empty_dir_info edi
= (empty_dir_info
) priv_data
;
157 edi
->freed_blocks
= 0;
160 retval
= ext2fs_read_inode(fs
, db
->ino
, &edi
->inode
);
164 retval
= ext2fs_block_iterate2(fs
, db
->ino
, 0, edi
->block_buf
,
169 if (edi
->freed_blocks
) {
170 edi
->inode
.i_size
-= edi
->freed_blocks
* fs
->blocksize
;
171 ext2fs_iblk_add_blocks(fs
, &edi
->inode
, edi
->freed_blocks
);
172 retval
= ext2fs_write_inode(fs
, db
->ino
, &edi
->inode
);
179 void process_empty_dirblock(e2fsck_t ctx
, empty_dir_info edi
)
184 edi
->block_buf
= malloc(ctx
->fs
->blocksize
* 3);
186 if (edi
->block_buf
) {
187 (void) ext2fs_dblist_iterate(edi
->empty_dblist
,
188 fix_directory
, &edi
);
190 free(edi
->block_buf
);
191 free_empty_dirblock(edi
);