+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
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 {
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);
}
/*
+ * 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
*/
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;
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) {
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 */