Add code to check and fix incorrect reference counts in the extended

attribute blocks.
This commit is contained in:
Theodore Ts'o 2001-07-07 11:12:50 -04:00
parent ac493821ea
commit e8a3ee628a
4 changed files with 104 additions and 3 deletions

View File

@ -1,3 +1,16 @@
2001-07-07 Theodore Tso <tytso@valinux.com>
* pass1.c (adjust_extattr_refcount): Add new function which
adjusts the reference counts of extended attribute blocks
if needed, both up and down.
(e2fsck_pass1): If the refcount or refcount_extra
structure are present, call adjust_extattr_refcount(),
and free it afterwards.
* problem.h, problem.c (PR_1_EXTATTR_READ_ABORT,
PR_1_EXTATTR_REFCOUNT, PR_1_EXTATTR_WRITE): Add new
problem codes.
2001-07-02 Theodore Tso <tytso@valinux.com>
* pass1.c (e2fsck_pass1, check_ext_attr, check_blocks): Add

View File

@ -70,6 +70,8 @@ static void process_inodes(e2fsck_t ctx, char *block_buf);
static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
dgrp_t group, void * priv_data);
static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
char *block_buf, int adjust_sign);
/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
struct process_block_struct {
@ -623,6 +625,23 @@ void e2fsck_pass1(e2fsck_t ctx)
ext2fs_close_inode_scan(scan);
ehandler_operation(0);
/*
* If any extended attribute blocks' reference counts need to
* be adjusted, either up (ctx->refcount_extra), or down
* (ctx->refcount), then fix them.
*/
if (ctx->refcount) {
adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
ea_refcount_free(ctx->refcount);
ctx->refcount = 0;
}
if (ctx->refcount_extra) {
adjust_extattr_refcount(ctx, ctx->refcount_extra,
block_buf, +1);
ea_refcount_free(ctx->refcount_extra);
ctx->refcount_extra = 0;
}
if (ctx->invalid_bitmaps)
handle_fs_bad_blocks(ctx);
@ -859,6 +878,52 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
}
}
/*
* Adjust the extended attribute block's reference counts at the end
* of pass 1, either by subtracting out references for EA blocks that
* are still referenced in ctx->refcount, or by adding references for
* EA blocks that had extra references as accounted for in
* ctx->refcount_extra.
*/
static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
char *block_buf, int adjust_sign)
{
struct ext2_ext_attr_header *header;
struct problem_context pctx;
ext2_filsys fs = ctx->fs;
errcode_t retval;
blk_t blk;
__u32 should_be;
int count;
clear_problem_context(&pctx);
ea_refcount_intr_begin(refcount);
while (1) {
if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
break;
pctx.blk = blk;
pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
if (pctx.errcode) {
fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
return;
}
header = (struct ext2_ext_attr_header *) block_buf;
pctx.blkcount = header->h_refcount;
should_be = header->h_refcount + adjust_sign * count;
pctx.num = should_be;
if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
header->h_refcount = should_be;
pctx.errcode = ext2fs_write_ext_attr(fs, blk,
block_buf);
if (pctx.errcode) {
fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
continue;
}
}
}
}
/*
* Handle processing the extended attribute blocks
*/
@ -869,7 +934,7 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
ext2_ino_t ino = pctx->ino;
struct ext2_inode *inode = pctx->inode;
blk_t blk;
static struct ext2_ext_attr_header *header;
struct ext2_ext_attr_header *header;
int count;
blk = inode->i_file_acl;
@ -941,7 +1006,6 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
goto clear_extattr;
/* XXX what if read_ext_attr returns an error */
header = (struct ext2_ext_attr_header *) block_buf;
if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {

View File

@ -577,11 +577,26 @@ static const struct e2fsck_problem problem_table[] = {
N_("Error reading @a @b %b for @i %i. "),
PROMPT_CLEAR, 0 },
/* Invalid extended attribute block */
/* Invalid extended attribute block */
{ PR_1_BAD_EA_BLOCK,
N_("@i %i has a bad @a @b %b. "),
PROMPT_CLEAR, 0 },
/* Error reading Extended Attribute block while fixing refcount */
{ PR_1_EXTATTR_READ_ABORT,
N_("Error reading @a @b %b (%m). "),
PROMPT_ABORT, 0 },
/* Extended attribute reference count incorrect */
{ PR_1_EXTATTR_REFCOUNT,
N_("@a @b %b has reference count %B, should be %N. "),
PROMPT_FIX, 0 },
/* Error writing Extended Attribute block while fixing refcount */
{ PR_1_EXTATTR_WRITE,
N_("Error writing @a @b %b (%m). "),
PROMPT_ABORT, 0 },
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */

View File

@ -336,6 +336,15 @@ struct problem_context {
/* Invalid Extended Attribute block */
#define PR_1_BAD_EA_BLOCK 0x01003A
/* Error reading Extended Attribute block while fixing refcount -- abort */
#define PR_1_EXTATTR_READ_ABORT 0x01003B
/* Extended attribute reference count incorrect */
#define PR_1_EXTATTR_REFCOUNT 0x01003C
/* Error writing Extended Attribute block while fixing refcount */
#define PR_1_EXTATTR_WRITE 0x01003D
/*
* Pass 1b errors
*/