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 %d (#%d) in inode %d\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
edi->inode.i_blocks -= edi->freed_blocks *
172
(fs->blocksize / 512);
173
(void) ext2fs_write_inode(fs, db->ino, &edi->inode);
178
void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi)
183
edi->block_buf = malloc(ctx->fs->blocksize * 3);
185
if (edi->block_buf) {
186
(void) ext2fs_dblist_iterate(edi->empty_dblist,
187
fix_directory, &edi);
189
free(edi->block_buf);
190
free_empty_dirblock(edi);