mirror of
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
synced 2025-01-26 10:23:58 +08:00
Add code to check and fix incorrect reference counts in the extended
attribute blocks.
This commit is contained in:
parent
ac493821ea
commit
e8a3ee628a
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user