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
= e2fsck_allocate_memzero(ctx
, 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
));
85 ext2fs_free_mem(&edi
);
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 retval
= ext2f_get_mem(ctx
, ctx
->fs
->blocksize
* 3,
187 if (edi
->block_buf
) {
188 (void) ext2fs_dblist_iterate2(edi
->empty_dblist
,
189 fix_directory
, &edi
);
191 ext2fs_free_mem(&edi
->block_buf
);
192 free_empty_dirblock(edi
);