diff options
-rw-r--r-- | e2fsck/ChangeLog | 15 | ||||
-rw-r--r-- | e2fsck/e2fsck.c | 2 | ||||
-rw-r--r-- | e2fsck/emptydir.c | 192 | ||||
-rw-r--r-- | e2fsck/pass2.c | 5 | ||||
-rw-r--r-- | e2fsck/pass3.c | 9 | ||||
-rw-r--r-- | e2fsck/unix.c | 3 | ||||
-rw-r--r-- | lib/ext2fs/ChangeLog | 6 | ||||
-rw-r--r-- | lib/ext2fs/badblocks.c | 9 |
8 files changed, 229 insertions, 12 deletions
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 84d3e2ff..17f883b0 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,18 @@ +1998-08-01 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * pass2.c (e2fsck_pass2): Fix the progress accounting so that we + get to 100%. + + * pass3.c (e2fsck_pass3): Change progress accounting to be + consistent with the other e2fsck passes. + + * e2fsck.c (e2fsck_run): At the end of each pass, call the + progress function with the pass number set to zero. + + * unix.c (e2fsck_update_progress): If the pass number is zero, + ignore the call, since that indicates that we just want to + deallocate any progress structures. + 1998-07-09 Theodore Ts'o <tytso@rsts-11.mit.edu> * Release of E2fsprogs 1.12 diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index 41195fe9..77e0e2e1 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -153,6 +153,8 @@ int e2fsck_run(e2fsck_t ctx) if (ctx->flags & E2F_FLAG_RUN_RETURN) break; e2fsck_pass(ctx); + if (ctx->progress) + (void) (ctx->progress)(ctx, 0, 0, 0); } ctx->flags &= ~E2F_FLAG_SETJMP_OK; diff --git a/e2fsck/emptydir.c b/e2fsck/emptydir.c new file mode 100644 index 00000000..6229a6bf --- /dev/null +++ b/e2fsck/emptydir.c @@ -0,0 +1,192 @@ +/* + * emptydir.c --- clear empty directory blocks + * + * Copyright (C) 1998 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * This file has the necessary routines to search for empty directory + * blocks and get rid of them. + */ + +#include "e2fsck.h" +#include "problem.h" + +/* + * For e2fsck.h + */ +struct empty_dir_info_struct { + ext2_dblist empty_dblist; + ext2fs_block_bitmap empty_dir_blocks; + ext2fs_inode_bitmap dir_map; + char *block_buf; + ino_t ino; + struct ext2_inode inode; + blk_t logblk; + blk_t freed_blocks; +}; + +typedef struct empty_dir_info_struct *empty_dir_info; + +extern empty_dir_info init_empty_dir(e2fsck_t ctx); +extern void free_empty_dirblock(empty_dir_info edi); +extern void add_empty_dirblock(empty_dir_info edi, + struct ext2_db_entry *db); +extern void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi); + + +empty_dir_info init_empty_dir(e2fsck_t ctx) +{ + empty_dir_info edi; + errcode_t retval; + + edi = malloc(sizeof(struct empty_dir_info_struct)); + if (!edi) + return NULL; + + memset(edi, 0, sizeof(struct empty_dir_info_struct)); + + retval = ext2fs_init_dblist(ctx->fs, &edi->empty_dblist); + if (retval) + goto errout; + + retval = ext2fs_allocate_block_bitmap(ctx->fs, "empty dirblocks", + &edi->empty_dir_blocks); + if (retval) + goto errout; + + retval = ext2fs_allocate_inode_bitmap(ctx->fs, "empty dir map", + &edi->dir_map); + if (retval) + goto errout; + + return (edi); + +errout: + free_empty_dirblock(edi); + return NULL; +} + +void free_empty_dirblock(empty_dir_info edi) +{ + if (!edi) + return; + if (edi->empty_dblist) + ext2fs_free_dblist(edi->empty_dblist); + if (edi->empty_dir_blocks) + ext2fs_free_block_bitmap(edi->empty_dir_blocks); + if (edi->dir_map) + ext2fs_free_inode_bitmap(edi->dir_map); + + memset(edi, 0, sizeof(struct empty_dir_info_struct)); + free(edi); +} + +void add_empty_dirblock(empty_dir_info edi, + struct ext2_db_entry *db) +{ + if (!edi || !db) + return; + + if (db->ino == 11) + return; /* Inode number 11 is usually lost+found */ + + printf("Empty directory block %d (#%d) in inode %d\n", + db->blk, db->blockcnt, db->ino); + + ext2fs_mark_block_bitmap(edi->empty_dir_blocks, db->blk); + if (ext2fs_test_inode_bitmap(edi->dir_map, db->ino)) + return; + ext2fs_mark_inode_bitmap(edi->dir_map, db->ino); + + ext2fs_add_dir_block(edi->empty_dblist, db->ino, + db->blk, db->blockcnt); +} + +/* + * Helper function used by fix_directory. + * + * XXX need to finish this. General approach is to use bmap to + * iterate over all of the logical blocks using the bmap function, and + * copy the block reference as necessary. Big question --- what do + * about error recovery? + * + * Also question --- how to free the indirect blocks. + */ +int empty_pass1(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, void *priv_data) +{ + empty_dir_info edi = (empty_dir_info) priv_data; + blk_t block, new_block; + errcode_t retval; + + if (blockcnt < 0) + return 0; + block = *block_nr; + do { + retval = ext2fs_bmap(fs, edi->ino, &edi->inode, + edi->block_buf, 0, edi->logblk, + &new_block); + if (retval) + return DIRENT_ABORT; /* XXX what to do? */ + if (new_block == 0) + break; + edi->logblk++; + } while (ext2fs_test_block_bitmap(edi->empty_dir_blocks, new_block)); + + if (new_block == block) + return 0; + if (new_block == 0) + edi->freed_blocks++; + *block_nr = new_block; + return BLOCK_CHANGED; +} + +static int fix_directory(ext2_filsys fs, + struct ext2_db_entry *db, + void *priv_data) +{ + errcode_t retval; + + empty_dir_info edi = (empty_dir_info) priv_data; + + edi->logblk = 0; + edi->freed_blocks = 0; + edi->ino = db->ino; + + retval = ext2fs_read_inode(fs, db->ino, &edi->inode); + if (retval) + return 0; + + retval = ext2fs_block_iterate2(fs, db->ino, 0, edi->block_buf, + empty_pass1, edi); + if (retval) + return 0; + + if (edi->freed_blocks) { + edi->inode.i_size -= edi->freed_blocks * fs->blocksize; + edi->inode.i_blocks -= edi->freed_blocks * + (fs->blocksize / 512); + (void) ext2fs_write_inode(fs, db->ino, &edi->inode); + } + return 0; +} + +void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi) +{ + if (!edi) + return; + + edi->block_buf = malloc(ctx->fs->blocksize * 3); + + if (edi->block_buf) { + (void) ext2fs_dblist_iterate(edi->empty_dblist, + fix_directory, &edi); + } + free(edi->block_buf); + free_empty_dirblock(edi); +} + diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index f52bc2ee..1767d00c 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -112,8 +112,11 @@ void e2fsck_pass2(e2fsck_t ctx) cd.buf = buf; cd.ctx = ctx; - cd.count = 0; + cd.count = 1; cd.max = ext2fs_dblist_count(fs->dblist); + + if (ctx->progress) + (void) (ctx->progress)(ctx, 2, 0, cd.max); cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block, &cd); diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c index 733819ee..c87ebd9c 100644 --- a/e2fsck/pass3.c +++ b/e2fsck/pass3.c @@ -110,8 +110,12 @@ void e2fsck_pass3(e2fsck_t ctx) ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO); max = e2fsck_get_num_dirinfo(ctx); - count = 0; + count = 1; + if (ctx->progress) + if ((ctx->progress)(ctx, 3, 0, max)) + goto abort_exit; + for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) { if (ctx->progress) if ((ctx->progress)(ctx, 3, count++, max)) @@ -119,9 +123,6 @@ void e2fsck_pass3(e2fsck_t ctx) if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino)) check_directory(ctx, dir, &pctx); } - if (ctx->progress) - if ((ctx->progress)(ctx, 3, max, max)) - goto abort_exit; abort_exit: e2fsck_free_dir_info(ctx); diff --git a/e2fsck/unix.c b/e2fsck/unix.c index cd6c98d6..b4710a23 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -228,6 +228,9 @@ static int e2fsck_update_progress(e2fsck_t ctx, int pass, { const char spinner[] = "\\|/-"; char buf[80]; + + if (pass == 0) + return 0; if (ctx->progress_fd) { sprintf(buf, "%d %lu %lu\n", pass, cur, max); diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index bd83ea2c..ddce36d9 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,9 @@ +1998-07-27 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * badblocks.c (ext2fs_badblocks_list_add): Use a bigger increment + than 10 blocks when we need to expand the size of the + badblocks list. + 1998-07-09 Theodore Ts'o <tytso@rsts-11.mit.edu> * Release of E2fsprogs 1.12 diff --git a/lib/ext2fs/badblocks.c b/lib/ext2fs/badblocks.c index 3851ccd6..e2f46f15 100644 --- a/lib/ext2fs/badblocks.c +++ b/lib/ext2fs/badblocks.c @@ -107,11 +107,11 @@ errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) if (bb->num >= bb->size) { old_size = bb->size * sizeof(blk_t); - bb->size += 10; + bb->size += 100; retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t), (void **) &bb->list); if (retval) { - bb->size -= 10; + bb->size -= 100; return retval; } } @@ -215,8 +215,3 @@ void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) iter->bb = 0; ext2fs_free_mem((void **) &iter); } - - - - - |