* [PATCH 1/3] e2fsck: Fix directory with holes even when i_size is wrong [not found] <20091128152750.GD6763@thunk.org> @ 2009-11-28 15:30 ` Theodore Ts'o 2009-11-29 20:31 ` [PATCH -v2] " Theodore Ts'o 2009-11-28 15:30 ` [PATCH 2/3] e2fsck: Move check to add an index to a directory after fixing i_size Theodore Ts'o 2009-11-28 15:30 ` [PATCH 3/3] filefrag: Fix a core dump on sparc32 platforms with 8k file systems Theodore Ts'o 2 siblings, 1 reply; 4+ messages in thread From: Theodore Ts'o @ 2009-11-28 15:30 UTC (permalink / raw) To: Ext4 Developers List; +Cc: Mikulas Patocka, Theodore Ts'o The old method for detecting directories with holes depended on i_size being correct, even though the correct value of i_size hadn't been calculated yet. Hence, a directory inode with holes and an i_size of 0 would require two e2fsck passes to fix completely. The replacement method for determining whether or not ext2fs_add_dir_block() should be called is more reliable, and reduces the size of e2fsck and makes the code more readable as a bonus. Thanks to Mikulas Patocka for providing a sample file system which demonstrated this problem. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> --- e2fsck/pass1.c | 61 ++++++++++++++----------------------------------------- 1 files changed, 16 insertions(+), 45 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 2531e57..f87d3ed 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -83,6 +83,7 @@ struct process_block_struct { blk_t num_blocks; blk_t max_blocks; e2_blkcnt_t last_block; + e2_blkcnt_t last_db_block; int num_illegal_blocks; blk_t previous_block; struct ext2_inode *inode; @@ -767,6 +768,7 @@ void e2fsck_pass1(e2fsck_t ctx) } pb.ino = EXT2_BAD_INO; pb.num_blocks = pb.last_block = 0; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; @@ -1820,6 +1822,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.ino = ino; pb.num_blocks = 0; pb.last_block = -1; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.fragmented = 0; @@ -1883,26 +1886,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, return; } - if (pb.is_dir) { - while (1) { - struct ext2_db_entry *entry; - - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino) || - (entry->blk != 0) || - (entry->blockcnt == 0)) - break; - /* printf("Dropping ino %lu blk %lu blockcnt %d\n", - entry->ino, entry->blk, entry->blockcnt); */ - ext2fs_dblist_drop_last(fs->dblist); - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino)) - pb.last_block--; - else - pb.last_block = entry->blockcnt; - } - } - if (inode->i_flags & EXT2_INDEX_FL) { if (handle_htree(ctx, pctx, ino, inode, block_buf)) { inode->i_flags &= ~EXT2_INDEX_FL; @@ -2094,31 +2077,8 @@ static int process_block(ext2_filsys fs, return 0; } - if (blk == 0) { - if (p->is_dir == 0) { - /* - * Should never happen, since only directories - * get called with BLOCK_FLAG_HOLE - */ -#if DEBUG_E2FSCK - printf("process_block() called with blk == 0, " - "blockcnt=%d, inode %lu???\n", - blockcnt, p->ino); -#endif - return 0; - } - if (blockcnt < 0) - return 0; - if (blockcnt * fs->blocksize < p->inode->i_size) { -#if 0 - printf("Missing block (#%d) in directory inode %lu!\n", - blockcnt, p->ino); -#endif - p->last_block = blockcnt; - goto mark_dir; - } - return 0; - } + if (blk == 0) + return; #if 0 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, @@ -2203,11 +2163,22 @@ static int process_block(ext2_filsys fs, p->last_block = blockcnt; mark_dir: if (p->is_dir && (blockcnt >= 0)) { + while (++p->last_db_block < blockcnt) { + pctx->errcode = ext2fs_add_dir_block(fs->dblist, + p->ino, 0, + p->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = p->last_db_block; + goto failed_add_dir_block; + } + } pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, blk, blockcnt); if (pctx->errcode) { pctx->blk = blk; pctx->num = blockcnt; + failed_add_dir_block: fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); /* Should never get here */ ctx->flags |= E2F_FLAG_ABORT; -- 1.6.5.216.g5288a.dirty ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH -v2] e2fsck: Fix directory with holes even when i_size is wrong 2009-11-28 15:30 ` [PATCH 1/3] e2fsck: Fix directory with holes even when i_size is wrong Theodore Ts'o @ 2009-11-29 20:31 ` Theodore Ts'o 0 siblings, 0 replies; 4+ messages in thread From: Theodore Ts'o @ 2009-11-29 20:31 UTC (permalink / raw) To: Ext4 Developers List; +Cc: Mikulas Patocka, Theodore Ts'o The old method for detecting directories with holes depended on i_size being correct, even though the correct value of i_size hadn't been calculated yet. Hence, a directory inode with holes and an i_size of 0 would require two e2fsck passes to fix completely. The replacement method for determining whether or not ext2fs_add_dir_block() should be called is more reliable, and reduces the size of e2fsck and makes the code more readable as a bonus. Thanks to Mikulas Patocka for providing a sample file system which demonstrated this problem. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> --- e2fsck/pass1.c | 59 ++++++++++++++----------------------------------------- 1 files changed, 15 insertions(+), 44 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 2531e57..b534841 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -83,6 +83,7 @@ struct process_block_struct { blk_t num_blocks; blk_t max_blocks; e2_blkcnt_t last_block; + e2_blkcnt_t last_db_block; int num_illegal_blocks; blk_t previous_block; struct ext2_inode *inode; @@ -767,6 +768,7 @@ void e2fsck_pass1(e2fsck_t ctx) } pb.ino = EXT2_BAD_INO; pb.num_blocks = pb.last_block = 0; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; @@ -1820,6 +1822,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.ino = ino; pb.num_blocks = 0; pb.last_block = -1; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.fragmented = 0; @@ -1883,26 +1886,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, return; } - if (pb.is_dir) { - while (1) { - struct ext2_db_entry *entry; - - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino) || - (entry->blk != 0) || - (entry->blockcnt == 0)) - break; - /* printf("Dropping ino %lu blk %lu blockcnt %d\n", - entry->ino, entry->blk, entry->blockcnt); */ - ext2fs_dblist_drop_last(fs->dblist); - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino)) - pb.last_block--; - else - pb.last_block = entry->blockcnt; - } - } - if (inode->i_flags & EXT2_INDEX_FL) { if (handle_htree(ctx, pctx, ino, inode, block_buf)) { inode->i_flags &= ~EXT2_INDEX_FL; @@ -2094,31 +2077,8 @@ static int process_block(ext2_filsys fs, return 0; } - if (blk == 0) { - if (p->is_dir == 0) { - /* - * Should never happen, since only directories - * get called with BLOCK_FLAG_HOLE - */ -#if DEBUG_E2FSCK - printf("process_block() called with blk == 0, " - "blockcnt=%d, inode %lu???\n", - blockcnt, p->ino); -#endif - return 0; - } - if (blockcnt < 0) - return 0; - if (blockcnt * fs->blocksize < p->inode->i_size) { -#if 0 - printf("Missing block (#%d) in directory inode %lu!\n", - blockcnt, p->ino); -#endif - p->last_block = blockcnt; - goto mark_dir; - } + if (blk == 0) return 0; - } #if 0 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, @@ -2203,11 +2163,22 @@ static int process_block(ext2_filsys fs, p->last_block = blockcnt; mark_dir: if (p->is_dir && (blockcnt >= 0)) { + while (++p->last_db_block < blockcnt) { + pctx->errcode = ext2fs_add_dir_block(fs->dblist, + p->ino, 0, + p->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = p->last_db_block; + goto failed_add_dir_block; + } + } pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, blk, blockcnt); if (pctx->errcode) { pctx->blk = blk; pctx->num = blockcnt; + failed_add_dir_block: fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); /* Should never get here */ ctx->flags |= E2F_FLAG_ABORT; -- 1.6.5.216.g5288a.dirty ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] e2fsck: Move check to add an index to a directory after fixing i_size [not found] <20091128152750.GD6763@thunk.org> 2009-11-28 15:30 ` [PATCH 1/3] e2fsck: Fix directory with holes even when i_size is wrong Theodore Ts'o @ 2009-11-28 15:30 ` Theodore Ts'o 2009-11-28 15:30 ` [PATCH 3/3] filefrag: Fix a core dump on sparc32 platforms with 8k file systems Theodore Ts'o 2 siblings, 0 replies; 4+ messages in thread From: Theodore Ts'o @ 2009-11-28 15:30 UTC (permalink / raw) To: Ext4 Developers List; +Cc: Mikulas Patocka, Theodore Ts'o The check that determines whether an directory needs to be have an index added to it depends on i_size. So move it after we have fixed up i_size so that we reliable will rehash a directory that needs it, even if its i_size field was originally incorrect. Otherwise, a second run of e2fsck would be needed before the directory gets an index added. Thanks to Mikulas Patocka for providing a sample file system which demonstrated this problem. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> --- e2fsck/pass1.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index f87d3ed..40948e7 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1896,10 +1896,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, #endif } } - if (ctx->dirs_to_hash && pb.is_dir && - !(inode->i_flags & EXT2_INDEX_FL) && - ((inode->i_size / fs->blocksize) >= 3)) - ext2fs_u32_list_add(ctx->dirs_to_hash, ino); if (!pb.num_blocks && pb.is_dir) { if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { @@ -1977,6 +1973,12 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, } pctx->num = 0; } + + if (ctx->dirs_to_hash && pb.is_dir && + !(inode->i_flags & EXT2_INDEX_FL) && + ((inode->i_size / fs->blocksize) >= 3)) + ext2fs_u32_list_add(ctx->dirs_to_hash, ino); + out: if (dirty_inode) e2fsck_write_inode(ctx, ino, inode, "check_blocks"); -- 1.6.5.216.g5288a.dirty ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] filefrag: Fix a core dump on sparc32 platforms with 8k file systems [not found] <20091128152750.GD6763@thunk.org> 2009-11-28 15:30 ` [PATCH 1/3] e2fsck: Fix directory with holes even when i_size is wrong Theodore Ts'o 2009-11-28 15:30 ` [PATCH 2/3] e2fsck: Move check to add an index to a directory after fixing i_size Theodore Ts'o @ 2009-11-28 15:30 ` Theodore Ts'o 2 siblings, 0 replies; 4+ messages in thread From: Theodore Ts'o @ 2009-11-28 15:30 UTC (permalink / raw) To: Ext4 Developers List; +Cc: Mikulas Patocka, Theodore Ts'o On 32-bit platforms where the file system block size is 8k or greater, the calculation bpib*bpib*bpib* will overflow a 32-bit calculation, leading to a divide by zero error. Fix this. Thanks to Mikulas Patocka for pointing this out. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> --- misc/filefrag.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/misc/filefrag.c b/misc/filefrag.c index 11783fd..1611f90 100644 --- a/misc/filefrag.c +++ b/misc/filefrag.c @@ -341,7 +341,7 @@ static void frag_report(const char *filename) if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) last_block++; if (((i-EXT2_DIRECT-bpib-bpib*bpib) % - (bpib*bpib*bpib)) == 0) + (((__u64) bpib)*bpib*bpib)) == 0) last_block++; } rc = get_bmap(fd, i, &block); -- 1.6.5.216.g5288a.dirty ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-11-29 20:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20091128152750.GD6763@thunk.org>
2009-11-28 15:30 ` [PATCH 1/3] e2fsck: Fix directory with holes even when i_size is wrong Theodore Ts'o
2009-11-29 20:31 ` [PATCH -v2] " Theodore Ts'o
2009-11-28 15:30 ` [PATCH 2/3] e2fsck: Move check to add an index to a directory after fixing i_size Theodore Ts'o
2009-11-28 15:30 ` [PATCH 3/3] filefrag: Fix a core dump on sparc32 platforms with 8k file systems Theodore Ts'o
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).