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_entry2 *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_entry2 *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_bitmap2(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_block2(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, blk64_t *block_nr, e2_blkcnt_t blockcnt,
120 blk64_t ref_block, int ref_offset, void *priv_data)
122 empty_dir_info edi = (empty_dir_info) priv_data;
123 blk64_t block, new_block;
130 retval = ext2fs_bmap2(fs, edi->ino, &edi->inode,
131 edi->block_buf, 0, edi->logblk, 0,
134 return DIRENT_ABORT; /* XXX what to do? */
138 } while (ext2fs_test_block_bitmap2(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_entry2 *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_iterate3(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_iterate2(edi->empty_dblist,
188 fix_directory, &edi);
190 free(edi->block_buf);
191 free_empty_dirblock(edi);