pass1b.c (clone_file_block): Fix bugs when cloning extended attribute

blocks.  Moved free of block_buf to after the code which clones the
	extattr block, and fixed logic for changing pointers to the extended
	attribute field in the inodes which were affected.
 
(decrement_badcount): New function which is used whenever we need to
	decrement the number of files which claim a particular bad block.
	Fixed bug where delete_file wasn't checking check_if_fs_block() before
	clearing the entry in block_dup_map.  This could cause a block which
	was claimed by multiple files as well as the filesystem metadata to
	not be completely fixed.
bitmap-optimize
Theodore Ts'o 2001-07-07 13:20:34 -04:00
parent e8a3ee628a
commit 7abb2bdcd6
2 changed files with 56 additions and 28 deletions

View File

@ -1,5 +1,18 @@
2001-07-07 Theodore Tso <tytso@valinux.com> 2001-07-07 Theodore Tso <tytso@valinux.com>
* pass1b.c (clone_file_block): Fix bugs when cloning extended
attribute blocks. Moved free of block_buf to after the
code which clones the extattr block, and fixed logic for
changing pointers to the extended attribute field in the
inodes which were affected.
(decrement_badcount): New function which is used whenever
we need to decrement the number of files which claim a
particular bad block. Fixed bug where delete_file wasn't
checking check_if_fs_block() before clearing the entry in
block_dup_map. This could cause a block which was claimed
by multiple files as well as the filesystem metadata to
not be completely fixed.
* pass1.c (adjust_extattr_refcount): Add new function which * pass1.c (adjust_extattr_refcount): Add new function which
adjusts the reference counts of extended attribute blocks adjusts the reference counts of extended attribute blocks
if needed, both up and down. if needed, both up and down.

View File

@ -492,6 +492,18 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
ext2fs_free_mem((void **) &shared); ext2fs_free_mem((void **) &shared);
} }
/*
* Drop the refcount on the dup_block structure, and clear the entry
* in the block_dup_map if appropriate.
*/
static void decrement_badcount(e2fsck_t ctx, struct dup_block *p)
{
p->num_bad--;
if (p->num_bad <= 0 ||
(p->num_bad == 1 && !check_if_fs_block(ctx, p->block)))
ext2fs_unmark_block_bitmap(ctx->block_dup_map, p->block);
}
static int delete_file_block(ext2_filsys fs, static int delete_file_block(ext2_filsys fs,
blk_t *block_nr, blk_t *block_nr,
e2_blkcnt_t blockcnt, e2_blkcnt_t blockcnt,
@ -514,10 +526,7 @@ static int delete_file_block(ext2_filsys fs,
if (p->block == *block_nr) if (p->block == *block_nr)
break; break;
if (p) { if (p) {
p->num_bad--; decrement_badcount(ctx, p);
if (p->num_bad == 1)
ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
} else } else
com_err("delete_file_block", 0, com_err("delete_file_block", 0,
_("internal error; can't find dup_blk for %d\n"), _("internal error; can't find dup_blk for %d\n"),
@ -619,11 +628,7 @@ static int clone_file_block(ext2_filsys fs,
cs->errcode = retval; cs->errcode = retval;
return BLOCK_ABORT; return BLOCK_ABORT;
} }
p->num_bad--; decrement_badcount(ctx, p);
if (p->num_bad == 1 &&
!check_if_fs_block(ctx, *block_nr))
ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
*block_nr = new_block; *block_nr = new_block;
ext2fs_mark_block_bitmap(ctx->block_found_map, ext2fs_mark_block_bitmap(ctx->block_found_map,
new_block); new_block);
@ -643,6 +648,7 @@ static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
errcode_t retval; errcode_t retval;
struct clone_struct cs; struct clone_struct cs;
struct problem_context pctx; struct problem_context pctx;
blk_t blk;
clear_problem_context(&pctx); clear_problem_context(&pctx);
cs.errcode = 0; cs.errcode = 0;
@ -660,22 +666,23 @@ static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf, pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf,
clone_file_block, &cs); clone_file_block, &cs);
ext2fs_mark_bb_dirty(fs); ext2fs_mark_bb_dirty(fs);
ext2fs_free_mem((void **) &cs.buf);
if (pctx.errcode) { if (pctx.errcode) {
fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
return pctx.errcode; retval = pctx.errcode;
goto errout;
} }
if (cs.errcode) { if (cs.errcode) {
com_err("clone_file", cs.errcode, com_err("clone_file", cs.errcode,
_("returned from clone_file_block")); _("returned from clone_file_block"));
return cs.errcode; retval = cs.errcode;
goto errout;
} }
if (dp->inode.i_file_acl && blk = dp->inode.i_file_acl;
(clone_file_block(fs, &dp->inode.i_file_acl, if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
BLOCK_COUNT_EXTATTR, 0, 0, &cs) == BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
BLOCK_CHANGED)) { BLOCK_CHANGED)) {
struct dup_block *p; struct dup_block *p, *q;
struct dup_inode *q; struct dup_inode *r;
/* /*
* If we cloned the EA block, find all other inodes * If we cloned the EA block, find all other inodes
@ -683,20 +690,28 @@ static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
* them to point to the new EA block. * them to point to the new EA block.
*/ */
for (p = dup_blk; p; p = p->next_block) { for (p = dup_blk; p; p = p->next_block) {
if (!(p->flags & FLAG_EXTATTR)) if (p->block == blk)
break;
}
for (q = p; q ; q = q->next_inode) {
if (!(q->flags & FLAG_EXTATTR))
continue; continue;
for (q = dup_ino; q; q = q->next) for (r = dup_ino; r; r = r->next)
if (p->ino == q->ino) if (r->ino == q->ino)
break; break;
if (!q) if (r) {
continue; /* Should never happen */ r->inode.i_file_acl = dp->inode.i_file_acl;
q->inode.i_file_acl = dp->inode.i_file_acl; e2fsck_write_inode(ctx, q->ino, &r->inode,
e2fsck_write_inode(ctx, q->ino, &q->inode, "clone file EA");
"clone file EA"); }
q->ino = 0; /* Should free the structure... */
decrement_badcount(ctx, p);
} }
} }
retval = 0;
return 0; errout:
ext2fs_free_mem((void **) &cs.buf);
return retval;
} }
/* /*