Whamcloud - gitweb
Add code to check and fix incorrect reference counts in the extended
authorTheodore Ts'o <tytso@mit.edu>
Sat, 7 Jul 2001 15:12:50 +0000 (11:12 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 7 Jul 2001 15:12:50 +0000 (11:12 -0400)
attribute blocks.

e2fsck/ChangeLog
e2fsck/pass1.c
e2fsck/problem.c
e2fsck/problem.h

index b24e806..1f6754d 100644 (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
index a9731c6..1ef4420 100644 (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);
 
@@ -860,6 +879,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
  */
 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
@@ -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) {
index e5e62cf..4e13c53 100644 (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 */
index 7136381..aa2b706 100644 (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
  */