Message ID | 20140726003404.28334.18860.stgit@birch.djwong.org |
---|---|
State | Accepted, archived |
Headers | show |
Wouldn't it be possible to use this information to determine which of the inodes sharing a duplicate mapped block is the right one and which inode is the bad one? Cheers, Andreas > On Jul 25, 2014, at 18:34, "Darrick J. Wong" <darrick.wong@oracle.com> wrote: > > As far as I can tell, logical block mappings on a bigalloc filesystem are > supposed to follow a few constraints: > > * The logical cluster offset must match the physical cluster offset. > * A logical cluster may not map to multiple physical clusters. > > Since the multiply-claimed block recovery code can be used to fix these > problems, teach e2fsck to find these transgressions and fix them. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > e2fsck/pass1.c | 52 +++++++++++ > e2fsck/pass1b.c | 42 ++++++++- > e2fsck/problem.c | 5 + > e2fsck/problem.h | 3 + > tests/f_badcluster/expect | 198 +++++++++++++++++++++++++++++++++++++++++++ > tests/f_badcluster/image.gz | Bin > tests/f_badcluster/name | 2 > tests/f_badcluster/script | 25 +++++ > 8 files changed, 320 insertions(+), 7 deletions(-) > create mode 100644 tests/f_badcluster/expect > create mode 100644 tests/f_badcluster/image.gz > create mode 100644 tests/f_badcluster/name > create mode 100644 tests/f_badcluster/script > > > diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c > index a6552e5..646ef8a 100644 > --- a/e2fsck/pass1.c > +++ b/e2fsck/pass1.c > @@ -1945,6 +1945,40 @@ void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, > e2fsck_write_inode(ctx, ino, inode, source); > } > > +/* > + * Use the multiple-blocks reclamation code to fix alignment problems in > + * a bigalloc filesystem. We want a logical cluster to map to *only* one > + * physical cluster, and we want the block offsets within that cluster to > + * line up. > + */ > +static int has_unaligned_cluster_map(e2fsck_t ctx, > + blk64_t last_pblk, e2_blkcnt_t last_lblk, > + blk64_t pblk, blk64_t lblk) > +{ > + blk64_t cluster_mask; > + > + if (!ctx->fs->cluster_ratio_bits) > + return 0; > + cluster_mask = EXT2FS_CLUSTER_MASK(ctx->fs); > + > + /* > + * If the block in the logical cluster doesn't align with the block in > + * the physical cluster... > + */ > + if ((lblk & cluster_mask) != (pblk & cluster_mask)) > + return 1; > + > + /* > + * If we cross a physical cluster boundary within a logical cluster... > + */ > + if (last_pblk && (lblk & cluster_mask) != 0 && > + EXT2FS_B2C(ctx->fs, lblk) == EXT2FS_B2C(ctx->fs, last_lblk) && > + EXT2FS_B2C(ctx->fs, pblk) != EXT2FS_B2C(ctx->fs, last_pblk)) > + return 1; > + > + return 0; > +} > + > static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, > struct process_block_struct *pb, > blk64_t start_block, blk64_t end_block, > @@ -2249,7 +2283,16 @@ alloc_later: > mark_block_used(ctx, blk); > pb->num_blocks++; > } > - > + if (has_unaligned_cluster_map(ctx, pb->previous_block, > + pb->last_block, blk, > + blockcnt)) { > + pctx->blk = blockcnt; > + pctx->blk2 = blk; > + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); > + mark_block_used(ctx, blk); > + mark_block_used(ctx, blk); > + } > + pb->last_block = blockcnt; > pb->previous_block = blk; > > if (is_dir) { > @@ -2815,6 +2858,13 @@ static int process_block(ext2_filsys fs, > ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) { > mark_block_used(ctx, blk); > p->num_blocks++; > + } else if (has_unaligned_cluster_map(ctx, p->previous_block, > + p->last_block, blk, blockcnt)) { > + pctx->blk = blockcnt; > + pctx->blk2 = blk; > + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); > + mark_block_used(ctx, blk); > + mark_block_used(ctx, blk); > } > if (blockcnt >= 0) > p->last_block = blockcnt; > diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c > index 8d42d10..c0bfa07 100644 > --- a/e2fsck/pass1b.c > +++ b/e2fsck/pass1b.c > @@ -261,7 +261,7 @@ struct process_block_struct { > e2fsck_t ctx; > ext2_ino_t ino; > int dup_blocks; > - blk64_t cur_cluster; > + blk64_t cur_cluster, phys_cluster; > blk64_t last_blk; > struct ext2_inode *inode; > struct problem_context *pctx; > @@ -317,6 +317,7 @@ static void pass1b(e2fsck_t ctx, char *block_buf) > pb.dup_blocks = 0; > pb.inode = &inode; > pb.cur_cluster = ~0; > + pb.phys_cluster = ~0; > pb.last_blk = 0; > pb.pctx->blk = pb.pctx->blk2 = 0; > > @@ -360,7 +361,7 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), > { > struct process_block_struct *p; > e2fsck_t ctx; > - blk64_t lc; > + blk64_t lc, pc; > problem_t op; > > if (HOLE_BLKADDR(*block_nr)) > @@ -368,6 +369,7 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), > p = (struct process_block_struct *) priv_data; > ctx = p->ctx; > lc = EXT2FS_B2C(fs, blockcnt); > + pc = EXT2FS_B2C(fs, *block_nr); > > if (!ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) > goto finish; > @@ -389,11 +391,19 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), > p->dup_blocks++; > ext2fs_mark_inode_bitmap2(inode_dup_map, p->ino); > > - if (blockcnt < 0 || lc != p->cur_cluster) > + /* > + * Qualifications for submitting a block for duplicate processing: > + * It's an extent/indirect block (and has a negative logical offset); > + * we've crossed a logical cluster boundary; or the physical cluster > + * suddenly changed, which indicates that blocks in a logical cluster > + * are mapped to multiple physical clusters. > + */ > + if (blockcnt < 0 || lc != p->cur_cluster || pc != p->phys_cluster) > add_dupe(ctx, p->ino, EXT2FS_B2C(fs, *block_nr), p->inode); > > finish: > p->cur_cluster = lc; > + p->phys_cluster = pc; > return 0; > } > > @@ -563,7 +573,11 @@ static void pass1d(e2fsck_t ctx, char *block_buf) > pctx.dir = t->dir; > fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); > } > - if (file_ok) { > + /* > + * Even if the file shares blocks with itself, we still need to > + * clone the blocks. > + */ > + if (file_ok && (meta_data ? shared_len+1 : shared_len) != 0) { > fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); > continue; > } > @@ -706,9 +720,10 @@ struct clone_struct { > errcode_t errcode; > blk64_t dup_cluster; > blk64_t alloc_block; > - ext2_ino_t dir; > + ext2_ino_t dir, ino; > char *buf; > e2fsck_t ctx; > + struct ext2_inode *inode; > }; > > static int clone_file_block(ext2_filsys fs, > @@ -756,13 +771,26 @@ static int clone_file_block(ext2_filsys fs, > decrement_badcount(ctx, *block_nr, p); > > cs->dup_cluster = c; > - > + /* > + * Let's try an implied cluster allocation. If we get the same > + * cluster back, then we need to find a new block; otherwise, > + * we're merely fixing the problem of one logical cluster being > + * mapped to multiple physical clusters. > + */ > + new_block = 0; > + retval = ext2fs_map_cluster_block(fs, cs->ino, cs->inode, > + blockcnt, &new_block); > + if (retval == 0 && new_block != 0 && > + EXT2FS_B2C(ctx->fs, new_block) != > + EXT2FS_B2C(ctx->fs, *block_nr)) > + goto cluster_alloc_ok; > retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, > &new_block); > if (retval) { > cs->errcode = retval; > return BLOCK_ABORT; > } > +cluster_alloc_ok: > cs->alloc_block = new_block; > > got_block: > @@ -817,6 +845,8 @@ static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, > cs.dup_cluster = ~0; > cs.alloc_block = 0; > cs.ctx = ctx; > + cs.ino = ino; > + cs.inode = &dp->inode; > retval = ext2fs_get_mem(fs->blocksize, &cs.buf); > if (retval) > return retval; > diff --git a/e2fsck/problem.c b/e2fsck/problem.c > index 60c02af..4da8ba8 100644 > --- a/e2fsck/problem.c > +++ b/e2fsck/problem.c > @@ -1048,6 +1048,11 @@ static struct e2fsck_problem problem_table[] = { > N_("@d @i %i has @x marked uninitialized at @b %c. "), > PROMPT_FIX, PR_PREEN_OK }, > > + /* Inode logical block (physical block ) is misaligned. */ > + { PR_1_MISALIGNED_CLUSTER, > + N_("@i %i logical @b %b (physical @b %c) violates cluster allocation rules.\nWill fix in pass 1B.\n"), > + PROMPT_NONE, 0 }, > + > /* Pass 1b errors */ > > /* Pass 1B: Rescan for duplicate/bad blocks */ > diff --git a/e2fsck/problem.h b/e2fsck/problem.h > index 6cd3d50..80ef4a2 100644 > --- a/e2fsck/problem.h > +++ b/e2fsck/problem.h > @@ -609,6 +609,9 @@ struct problem_context { > /* uninit directory block */ > #define PR_1_UNINIT_DBLOCK 0x010073 > > +/* Inode logical block is misaligned */ > +#define PR_1_MISALIGNED_CLUSTER 0x010074 > + > /* > * Pass 1b errors > */ > diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect > new file mode 100644 > index 0000000..eb3bcf0 > --- /dev/null > +++ b/tests/f_badcluster/expect > @@ -0,0 +1,198 @@ > +Pass 1: Checking inodes, blocks, and sizes > +Inode 12 logical block 2 (physical block 1154) violates cluster allocation rules. > +Will fix in pass 1B. > +Inode 12, i_blocks is 32, should be 64. Fix? yes > + > +Inode 16 logical block 5 (physical block 1173) violates cluster allocation rules. > +Will fix in pass 1B. > +Inode 16, i_size is 3072, should be 6144. Fix? yes > + > +Inode 16, i_blocks is 32, should be 64. Fix? yes > + > +Inode 17 logical block 0 (physical block 1186) violates cluster allocation rules. > +Will fix in pass 1B. > +Inode 17 logical block 2 (physical block 1184) violates cluster allocation rules. > +Will fix in pass 1B. > +Inode 17, i_blocks is 32, should be 64. Fix? yes > + > +Inode 18 logical block 3 (physical block 1201) violates cluster allocation rules. > +Will fix in pass 1B. > +Inode 18, i_blocks is 32, should be 64. Fix? yes > + > + > +Running additional passes to resolve blocks claimed by more than one inode... > +Pass 1B: Rescanning for multiply-claimed blocks > +Multiply-claimed block(s) in inode 12: 1154 > +Multiply-claimed block(s) in inode 13: 1152--1154 > +Multiply-claimed block(s) in inode 14: 1648--1650 > +Multiply-claimed block(s) in inode 15: 1650 > +Multiply-claimed block(s) in inode 16: 1173 > +Multiply-claimed block(s) in inode 17: 1186 1185 1184 > +Multiply-claimed block(s) in inode 18: 1201 > +Pass 1C: Scanning directories for inodes with multiply-claimed blocks > +Pass 1D: Reconciling multiply-claimed blocks > +(There are 7 inodes containing multiply-claimed blocks.) > + > +File /a (inode #12, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 1 file(s): > + /b (inode #13, mod time Tue Jun 17 08:00:50 2014) > +Clone multiply-claimed blocks? yes > + > +File /b (inode #13, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 1 file(s): > + /a (inode #12, mod time Tue Jun 17 08:00:50 2014) > +Multiply-claimed blocks already reassigned or cloned. > + > +File /c (inode #14, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 1 file(s): > + /d (inode #15, mod time Tue Jun 17 08:00:50 2014) > +Clone multiply-claimed blocks? yes > + > +File /d (inode #15, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 1 file(s): > + /c (inode #14, mod time Tue Jun 17 08:00:50 2014) > +Multiply-claimed blocks already reassigned or cloned. > + > +File /e (inode #16, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 0 file(s): > +Clone multiply-claimed blocks? yes > + > +File /f (inode #17, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 0 file(s): > +Clone multiply-claimed blocks? yes > + > +File /g (inode #18, mod time Tue Jun 17 08:00:50 2014) > + has 1 multiply-claimed block(s), shared with 0 file(s): > +Clone multiply-claimed blocks? yes > + > +Pass 2: Checking directory structure > +Pass 3: Checking directory connectivity > +Pass 4: Checking reference counts > +Pass 5: Checking group summary information > +Free blocks count wrong for group #0 (50, counted=47). > +Fix? yes > + > +Free blocks count wrong (800, counted=752). > +Fix? yes > + > + > +test_fs: ***** FILE SYSTEM WAS MODIFIED ***** > +test_fs: 18/128 files (22.2% non-contiguous), 1296/2048 blocks > +Pass 1: Checking inodes, blocks, and sizes > +Inode 12, i_blocks is 64, should be 32. Fix? yes > + > +Inode 16, i_blocks is 64, should be 32. Fix? yes > + > +Inode 17, i_blocks is 64, should be 32. Fix? yes > + > +Inode 18, i_blocks is 64, should be 32. Fix? yes > + > +Pass 2: Checking directory structure > +Pass 3: Checking directory connectivity > +Pass 4: Checking reference counts > +Pass 5: Checking group summary information > +Block bitmap differences: -(1168--1200) > +Fix? yes > + > +Free blocks count wrong for group #0 (47, counted=50). > +Fix? yes > + > +Free blocks count wrong (752, counted=800). > +Fix? yes > + > + > +test_fs: ***** FILE SYSTEM WAS MODIFIED ***** > +test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks > +Pass 1: Checking inodes, blocks, and sizes > +Pass 2: Checking directory structure > +Pass 3: Checking directory connectivity > +Pass 4: Checking reference counts > +Pass 5: Checking group summary information > +test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks > +debugfs: stat /a > +Inode: 12 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152157 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0-1):1136-1137, (2):1138 > +debugfs: stat /b > +Inode: 13 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152158 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0-2):1152-1154 > +debugfs: stat /c > +Inode: 14 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152159 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0-1):1216-1217, (2):1218 > +debugfs: stat /d > +Inode: 15 Type: regular Mode: 0644 Flags: 0x0 > +Generation: 1117152160 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +BLOCKS: > +(TIND):1650 > +TOTAL: 1 > + > +debugfs: stat /e > +Inode: 16 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152161 Version: 0x00000001 > +User: 0 Group: 0 Size: 6144 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0-2):1664-1666, (5):1669 > +debugfs: stat /f > +Inode: 17 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152162 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0):1232, (1):1233, (2):1234 > +debugfs: stat /g > +Inode: 18 Type: regular Mode: 0644 Flags: 0x80000 > +Generation: 1117152163 Version: 0x00000001 > +User: 0 Group: 0 Size: 3072 > +File ACL: 0 Directory ACL: 0 > +Links: 1 Blockcount: 32 > +Fragment: Address: 0 Number: 0 Size: 0 > +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 > +EXTENTS: > +(0-2):1680-1682, (3):1683 > +debugfs: > \ No newline at end of file > diff --git a/tests/f_badcluster/image.gz b/tests/f_badcluster/image.gz > new file mode 100644 > index 0000000000000000000000000000000000000000..e02ee1866868361e6e82bfbe29982365b2e3aa55 > GIT binary patch > literal 3131 > zcmeH`eNfVO9LF)YGArHAl6flRwbV_eOvC0A4VPY_dFBj}kaU;3`An&ypmc4h9VhIf > zG;+!qGBs1@gsG+2gU*y0Y50JcUV;y)D1xAjhu^x}b(h}$+@E~@_&j|7`F=jH&*u%L > z*?=Z=?ARUF%2(nv2aF3y#X5Z+g%u<)LiS(y@}tx>cPz)&G0Qe&A*OK@Raq{8^q_F- > zbB{#>iF|Dz=b)|E490O%W`;sOzn*Dtd$W+q>f!h2aWn3xA)rK!kjYY12Cz2VS^ia? > zJKzn{oZ*j8$vKNhzKW^O#IziXdU8FzD*|<eD@NYnUd~^Sa_N2j2lXf(hj_l!WF(Xz > z^@k=+XFN;5_JiKlfolqV3uj7S$m~OhGOU?ARvy2Z3xiBLmvwf9s?~oQZlIxv;1!zu > zbzM+@IZwGj2G3`h`BuLoys*(veF#j!uuCmX7XnXQP{(9>l8|3~Qb0L3W_@O8Bou2S > z#LwPyeSHU4SGh|_3O@<jVw-ulMAQSCYtw-BmUoczrKImN`3b_5sj-MBHFstycPr9Q > zyDc_LT!%)FD#_s5hLIl5UXnDPD@{u}7ViyT0SH2%u*0u$j#2PSivDR6be36cLR7JI > z>P9Io$LN#}Hy;+P)k<}%cC(5=1%>EC`mJ`K9DhLsMXNnTY7b5%xHS-GMy*X>nRI$s > zn4{EJv>{B*zOB8Z6U4SCeQg`RoRS%(Z&ez2MRsCB5pII*p9!eO5eo6@SX?5Fv~;uk > zMYgdE|JNdavOxx(M+a9JGE#v?A50YtD7>vh#2-d%9rOK)Okcl?dlmE3Udha-PBwlx > zw<*_LcZb-D6dfZP2dfe{<%37d#Ki?z2z!rK7Yx~>r3c$JM1<s%-6TO8VzA^PvIA2p > zr@^=X@pVnNrWr5+)70e+;E{U_fA>jX*E;3D-245!%MWU2YQwru2>?*S{bGVA^+1FB > z8-;3y!|ILos18QJB|+U;YN8OP0+aw@s+)wy9IvNaJ!a&tRX-rM!{|#hNL**Yt+QAN > zJh9_Kysv$_Bh~mb8`5JR&ddJMoa1}#T#i6&vzy$;rqF-rzqsGWd$8<0N-IB0;jPp~ > z22J;hV9a6Hf&ScQfGR<EF*<B2wZ4daZ;nx^i0)Iqacq`d{&rb6l&4^4_yVusv+Swi > z1ak*`wtFPmFfS9Bu<1ZooEm+61;F<$9g=?5M=jQYQ<c*bH6}vQ?^dJ9a3$sY-ekEM > zucY8tA{+GF>N<>h`Nd1)Ci8h@bC`iSpmOlA7MwV}^GPJS^lC&^e~*O6GRb2rQ1h+d > zB*q7XIxlAAlVK8>hUhH`Qg4!ZahPpe$wQ2fuN{FV4;STob=J3cl1ux;sphvTO-et5 > za=9(yX3Y%vwwp~zE$z|267_p4(cyK{(@S=d<tY<GLiz(@c9y?d_xCfA^QuQ;p;6U- > zgkHj3QM@#;1&o%EeQo}R%l?CeiQ{1XPRZF1iUXvrAI<|wei)IyMDNH*+K}a%dA%B_ > zeZmRAs#0yds@p(lDKZT^e7?L|o5?bXMz^W(-3eHtg@A>Cg@A>Cg@A>?|4(4iWQ{Gq > K#Rh>6g8l&!3vo*T > > literal 0 > HcmV?d00001 > > diff --git a/tests/f_badcluster/name b/tests/f_badcluster/name > new file mode 100644 > index 0000000..266f81c > --- /dev/null > +++ b/tests/f_badcluster/name > @@ -0,0 +1,2 @@ > +test alignment problems with bigalloc clusters > + > diff --git a/tests/f_badcluster/script b/tests/f_badcluster/script > new file mode 100644 > index 0000000..ba6b248 > --- /dev/null > +++ b/tests/f_badcluster/script > @@ -0,0 +1,25 @@ > +if test -x $DEBUGFS_EXE; then > + IMAGE=$test_dir/../f_badcluster/image.gz > + OUT=$test_name.log > + EXP=$test_dir/expect > + gzip -d < $IMAGE > $TMPFILE > + ../misc/tune2fs -L test_fs $TMPFILE > + ../e2fsck/e2fsck -fy $TMPFILE > $OUT > + ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > + ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > + for i in a b c d e f g; do echo "stat /$i"; done | $DEBUGFS_EXE $TMPFILE >> $OUT > + > + cmp -s $OUT $EXP > + status=$? > + > + if [ "$status" = 0 ]; then > + echo "$test_name: $test_description: ok" > + touch $test_name.ok > + else > + echo "$test_name: $test_description: failed" > + diff $DIFF_OPTS $EXP $OUT > $test_name.failed > + rm -f $test_name.tmp > + fi > +else > + echo "$test_name: skipped" > +fi > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sat, Jul 26, 2014 at 12:02:10AM -0600, Andreas Dilger wrote: > Wouldn't it be possible to use this information to determine which > of the inodes sharing a duplicate mapped block is the right one > and which inode is the bad one? Yes, although I'm not sure it's worth the effort. Putting in more intelligent hueristics for using the metadata checksums will help all file systems, and not just bigalloc file systems --- and I think it would be easier. > On Jul 25, 2014, at 18:34, "Darrick J. Wong" <darrick.wong@oracle.com> wrote: > > As far as I can tell, logical block mappings on a bigalloc filesystem are > supposed to follow a few constraints: > > * The logical cluster offset must match the physical cluster offset. > * A logical cluster may not map to multiple physical clusters. > > Since the multiply-claimed block recovery code can be used to fix these > problems, teach e2fsck to find these transgressions and fix them. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Thanks, applied, but a couple of tips about writing test scripts. You originally had this: ../misc/tune2fs -L test_fs $TMPFILE ../e2fsck/e2fsck -fy $TMPFILE > $OUT ../e2fsck/e2fsck -fy $TMPFILE >> $OUT ../e2fsck/e2fsck -fy $TMPFILE >> $OUT This spits out the version numbers to stderr, which is ugly. I fixed up the binary image file to have the test_fs label, and I changed the lines above to: $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed > $OUT $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT The advantage of doing things this way is that any errors get captured in the log file. Also, if the user has requested valgrind be used, that gets reflected in the value of $FSCK. Cheers, - Ted -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sat, Jul 26, 2014 at 04:27:28PM -0400, Theodore Ts'o wrote: > On Sat, Jul 26, 2014 at 12:02:10AM -0600, Andreas Dilger wrote: > > Wouldn't it be possible to use this information to determine which > > of the inodes sharing a duplicate mapped block is the right one > > and which inode is the bad one? > > Yes, although I'm not sure it's worth the effort. Putting in more > intelligent hueristics for using the metadata checksums will help all > file systems, and not just bigalloc file systems --- and I think it > would be easier. > > > On Jul 25, 2014, at 18:34, "Darrick J. Wong" <darrick.wong@oracle.com> wrote: > > > > As far as I can tell, logical block mappings on a bigalloc filesystem are > > supposed to follow a few constraints: > > > > * The logical cluster offset must match the physical cluster offset. > > * A logical cluster may not map to multiple physical clusters. > > > > Since the multiply-claimed block recovery code can be used to fix these > > problems, teach e2fsck to find these transgressions and fix them. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > Thanks, applied, but a couple of tips about writing test scripts. > > You originally had this: > > ../misc/tune2fs -L test_fs $TMPFILE > ../e2fsck/e2fsck -fy $TMPFILE > $OUT > ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > > This spits out the version numbers to stderr, which is ugly. I fixed > up the binary image file to have the test_fs label, and I changed the > lines above to: > > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed > $OUT > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT > > The advantage of doing things this way is that any errors get captured > in the log file. Also, if the user has requested valgrind be used, > that gets reflected in the value of $FSCK. Got it, thanks. I'll do that next time. --D > > Cheers, > > - Ted > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sat, Jul 26, 2014 at 04:27:28PM -0400, Theodore Ts'o wrote: > On Sat, Jul 26, 2014 at 12:02:10AM -0600, Andreas Dilger wrote: > > Wouldn't it be possible to use this information to determine which > > of the inodes sharing a duplicate mapped block is the right one > > and which inode is the bad one? > > Yes, although I'm not sure it's worth the effort. Putting in more > intelligent hueristics for using the metadata checksums will help all > file systems, and not just bigalloc file systems --- and I think it > would be easier. > > > On Jul 25, 2014, at 18:34, "Darrick J. Wong" <darrick.wong@oracle.com> wrote: > > > > As far as I can tell, logical block mappings on a bigalloc filesystem are > > supposed to follow a few constraints: > > > > * The logical cluster offset must match the physical cluster offset. > > * A logical cluster may not map to multiple physical clusters. > > > > Since the multiply-claimed block recovery code can be used to fix these > > problems, teach e2fsck to find these transgressions and fix them. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > Thanks, applied, but a couple of tips about writing test scripts. > > You originally had this: > > ../misc/tune2fs -L test_fs $TMPFILE > ../e2fsck/e2fsck -fy $TMPFILE > $OUT > ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > ../e2fsck/e2fsck -fy $TMPFILE >> $OUT > > This spits out the version numbers to stderr, which is ugly. I fixed > up the binary image file to have the test_fs label, and I changed the > lines above to: > > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed > $OUT > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT > $FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT > > The advantage of doing things this way is that any errors get captured > in the log file. Also, if the user has requested valgrind be used, > that gets reflected in the value of $FSCK. Hmm... the f_badcluster test seems to be missing from -maint and -next. Did it get lost in the merge? --D > > Cheers, > > - Ted > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Jul 28, 2014 at 10:55:54AM -0700, Darrick J. Wong wrote: > > Hmm... the f_badcluster test seems to be missing from -maint and -next. > Did it get lost in the merge? Oh, whoops. It's in my tree, but I forgot to "git add" the directory. (Because of some patch conflicts that caused "git am" to be unhappy, I ended up having to apply the patch manually.) I'll fix it up and push it out. - Ted -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index a6552e5..646ef8a 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1945,6 +1945,40 @@ void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, e2fsck_write_inode(ctx, ino, inode, source); } +/* + * Use the multiple-blocks reclamation code to fix alignment problems in + * a bigalloc filesystem. We want a logical cluster to map to *only* one + * physical cluster, and we want the block offsets within that cluster to + * line up. + */ +static int has_unaligned_cluster_map(e2fsck_t ctx, + blk64_t last_pblk, e2_blkcnt_t last_lblk, + blk64_t pblk, blk64_t lblk) +{ + blk64_t cluster_mask; + + if (!ctx->fs->cluster_ratio_bits) + return 0; + cluster_mask = EXT2FS_CLUSTER_MASK(ctx->fs); + + /* + * If the block in the logical cluster doesn't align with the block in + * the physical cluster... + */ + if ((lblk & cluster_mask) != (pblk & cluster_mask)) + return 1; + + /* + * If we cross a physical cluster boundary within a logical cluster... + */ + if (last_pblk && (lblk & cluster_mask) != 0 && + EXT2FS_B2C(ctx->fs, lblk) == EXT2FS_B2C(ctx->fs, last_lblk) && + EXT2FS_B2C(ctx->fs, pblk) != EXT2FS_B2C(ctx->fs, last_pblk)) + return 1; + + return 0; +} + static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, struct process_block_struct *pb, blk64_t start_block, blk64_t end_block, @@ -2249,7 +2283,16 @@ alloc_later: mark_block_used(ctx, blk); pb->num_blocks++; } - + if (has_unaligned_cluster_map(ctx, pb->previous_block, + pb->last_block, blk, + blockcnt)) { + pctx->blk = blockcnt; + pctx->blk2 = blk; + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); + mark_block_used(ctx, blk); + mark_block_used(ctx, blk); + } + pb->last_block = blockcnt; pb->previous_block = blk; if (is_dir) { @@ -2815,6 +2858,13 @@ static int process_block(ext2_filsys fs, ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) { mark_block_used(ctx, blk); p->num_blocks++; + } else if (has_unaligned_cluster_map(ctx, p->previous_block, + p->last_block, blk, blockcnt)) { + pctx->blk = blockcnt; + pctx->blk2 = blk; + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); + mark_block_used(ctx, blk); + mark_block_used(ctx, blk); } if (blockcnt >= 0) p->last_block = blockcnt; diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index 8d42d10..c0bfa07 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -261,7 +261,7 @@ struct process_block_struct { e2fsck_t ctx; ext2_ino_t ino; int dup_blocks; - blk64_t cur_cluster; + blk64_t cur_cluster, phys_cluster; blk64_t last_blk; struct ext2_inode *inode; struct problem_context *pctx; @@ -317,6 +317,7 @@ static void pass1b(e2fsck_t ctx, char *block_buf) pb.dup_blocks = 0; pb.inode = &inode; pb.cur_cluster = ~0; + pb.phys_cluster = ~0; pb.last_blk = 0; pb.pctx->blk = pb.pctx->blk2 = 0; @@ -360,7 +361,7 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), { struct process_block_struct *p; e2fsck_t ctx; - blk64_t lc; + blk64_t lc, pc; problem_t op; if (HOLE_BLKADDR(*block_nr)) @@ -368,6 +369,7 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), p = (struct process_block_struct *) priv_data; ctx = p->ctx; lc = EXT2FS_B2C(fs, blockcnt); + pc = EXT2FS_B2C(fs, *block_nr); if (!ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) goto finish; @@ -389,11 +391,19 @@ static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), p->dup_blocks++; ext2fs_mark_inode_bitmap2(inode_dup_map, p->ino); - if (blockcnt < 0 || lc != p->cur_cluster) + /* + * Qualifications for submitting a block for duplicate processing: + * It's an extent/indirect block (and has a negative logical offset); + * we've crossed a logical cluster boundary; or the physical cluster + * suddenly changed, which indicates that blocks in a logical cluster + * are mapped to multiple physical clusters. + */ + if (blockcnt < 0 || lc != p->cur_cluster || pc != p->phys_cluster) add_dupe(ctx, p->ino, EXT2FS_B2C(fs, *block_nr), p->inode); finish: p->cur_cluster = lc; + p->phys_cluster = pc; return 0; } @@ -563,7 +573,11 @@ static void pass1d(e2fsck_t ctx, char *block_buf) pctx.dir = t->dir; fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); } - if (file_ok) { + /* + * Even if the file shares blocks with itself, we still need to + * clone the blocks. + */ + if (file_ok && (meta_data ? shared_len+1 : shared_len) != 0) { fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); continue; } @@ -706,9 +720,10 @@ struct clone_struct { errcode_t errcode; blk64_t dup_cluster; blk64_t alloc_block; - ext2_ino_t dir; + ext2_ino_t dir, ino; char *buf; e2fsck_t ctx; + struct ext2_inode *inode; }; static int clone_file_block(ext2_filsys fs, @@ -756,13 +771,26 @@ static int clone_file_block(ext2_filsys fs, decrement_badcount(ctx, *block_nr, p); cs->dup_cluster = c; - + /* + * Let's try an implied cluster allocation. If we get the same + * cluster back, then we need to find a new block; otherwise, + * we're merely fixing the problem of one logical cluster being + * mapped to multiple physical clusters. + */ + new_block = 0; + retval = ext2fs_map_cluster_block(fs, cs->ino, cs->inode, + blockcnt, &new_block); + if (retval == 0 && new_block != 0 && + EXT2FS_B2C(ctx->fs, new_block) != + EXT2FS_B2C(ctx->fs, *block_nr)) + goto cluster_alloc_ok; retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, &new_block); if (retval) { cs->errcode = retval; return BLOCK_ABORT; } +cluster_alloc_ok: cs->alloc_block = new_block; got_block: @@ -817,6 +845,8 @@ static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, cs.dup_cluster = ~0; cs.alloc_block = 0; cs.ctx = ctx; + cs.ino = ino; + cs.inode = &dp->inode; retval = ext2fs_get_mem(fs->blocksize, &cs.buf); if (retval) return retval; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 60c02af..4da8ba8 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1048,6 +1048,11 @@ static struct e2fsck_problem problem_table[] = { N_("@d @i %i has @x marked uninitialized at @b %c. "), PROMPT_FIX, PR_PREEN_OK }, + /* Inode logical block (physical block ) is misaligned. */ + { PR_1_MISALIGNED_CLUSTER, + N_("@i %i logical @b %b (physical @b %c) violates cluster allocation rules.\nWill fix in pass 1B.\n"), + PROMPT_NONE, 0 }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 6cd3d50..80ef4a2 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -609,6 +609,9 @@ struct problem_context { /* uninit directory block */ #define PR_1_UNINIT_DBLOCK 0x010073 +/* Inode logical block is misaligned */ +#define PR_1_MISALIGNED_CLUSTER 0x010074 + /* * Pass 1b errors */ diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect new file mode 100644 index 0000000..eb3bcf0 --- /dev/null +++ b/tests/f_badcluster/expect @@ -0,0 +1,198 @@ +Pass 1: Checking inodes, blocks, and sizes +Inode 12 logical block 2 (physical block 1154) violates cluster allocation rules. +Will fix in pass 1B. +Inode 12, i_blocks is 32, should be 64. Fix? yes + +Inode 16 logical block 5 (physical block 1173) violates cluster allocation rules. +Will fix in pass 1B. +Inode 16, i_size is 3072, should be 6144. Fix? yes + +Inode 16, i_blocks is 32, should be 64. Fix? yes + +Inode 17 logical block 0 (physical block 1186) violates cluster allocation rules. +Will fix in pass 1B. +Inode 17 logical block 2 (physical block 1184) violates cluster allocation rules. +Will fix in pass 1B. +Inode 17, i_blocks is 32, should be 64. Fix? yes + +Inode 18 logical block 3 (physical block 1201) violates cluster allocation rules. +Will fix in pass 1B. +Inode 18, i_blocks is 32, should be 64. Fix? yes + + +Running additional passes to resolve blocks claimed by more than one inode... +Pass 1B: Rescanning for multiply-claimed blocks +Multiply-claimed block(s) in inode 12: 1154 +Multiply-claimed block(s) in inode 13: 1152--1154 +Multiply-claimed block(s) in inode 14: 1648--1650 +Multiply-claimed block(s) in inode 15: 1650 +Multiply-claimed block(s) in inode 16: 1173 +Multiply-claimed block(s) in inode 17: 1186 1185 1184 +Multiply-claimed block(s) in inode 18: 1201 +Pass 1C: Scanning directories for inodes with multiply-claimed blocks +Pass 1D: Reconciling multiply-claimed blocks +(There are 7 inodes containing multiply-claimed blocks.) + +File /a (inode #12, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 1 file(s): + /b (inode #13, mod time Tue Jun 17 08:00:50 2014) +Clone multiply-claimed blocks? yes + +File /b (inode #13, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 1 file(s): + /a (inode #12, mod time Tue Jun 17 08:00:50 2014) +Multiply-claimed blocks already reassigned or cloned. + +File /c (inode #14, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 1 file(s): + /d (inode #15, mod time Tue Jun 17 08:00:50 2014) +Clone multiply-claimed blocks? yes + +File /d (inode #15, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 1 file(s): + /c (inode #14, mod time Tue Jun 17 08:00:50 2014) +Multiply-claimed blocks already reassigned or cloned. + +File /e (inode #16, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 0 file(s): +Clone multiply-claimed blocks? yes + +File /f (inode #17, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 0 file(s): +Clone multiply-claimed blocks? yes + +File /g (inode #18, mod time Tue Jun 17 08:00:50 2014) + has 1 multiply-claimed block(s), shared with 0 file(s): +Clone multiply-claimed blocks? yes + +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +Free blocks count wrong for group #0 (50, counted=47). +Fix? yes + +Free blocks count wrong (800, counted=752). +Fix? yes + + +test_fs: ***** FILE SYSTEM WAS MODIFIED ***** +test_fs: 18/128 files (22.2% non-contiguous), 1296/2048 blocks +Pass 1: Checking inodes, blocks, and sizes +Inode 12, i_blocks is 64, should be 32. Fix? yes + +Inode 16, i_blocks is 64, should be 32. Fix? yes + +Inode 17, i_blocks is 64, should be 32. Fix? yes + +Inode 18, i_blocks is 64, should be 32. Fix? yes + +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +Block bitmap differences: -(1168--1200) +Fix? yes + +Free blocks count wrong for group #0 (47, counted=50). +Fix? yes + +Free blocks count wrong (752, counted=800). +Fix? yes + + +test_fs: ***** FILE SYSTEM WAS MODIFIED ***** +test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks +debugfs: stat /a +Inode: 12 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152157 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0-1):1136-1137, (2):1138 +debugfs: stat /b +Inode: 13 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152158 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0-2):1152-1154 +debugfs: stat /c +Inode: 14 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152159 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0-1):1216-1217, (2):1218 +debugfs: stat /d +Inode: 15 Type: regular Mode: 0644 Flags: 0x0 +Generation: 1117152160 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +BLOCKS: +(TIND):1650 +TOTAL: 1 + +debugfs: stat /e +Inode: 16 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152161 Version: 0x00000001 +User: 0 Group: 0 Size: 6144 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0-2):1664-1666, (5):1669 +debugfs: stat /f +Inode: 17 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152162 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0):1232, (1):1233, (2):1234 +debugfs: stat /g +Inode: 18 Type: regular Mode: 0644 Flags: 0x80000 +Generation: 1117152163 Version: 0x00000001 +User: 0 Group: 0 Size: 3072 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 32 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014 +EXTENTS: +(0-2):1680-1682, (3):1683 +debugfs: \ No newline at end of file diff --git a/tests/f_badcluster/image.gz b/tests/f_badcluster/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..e02ee1866868361e6e82bfbe29982365b2e3aa55 GIT binary patch literal 3131 zcmeH`eNfVO9LF)YGArHAl6flRwbV_eOvC0A4VPY_dFBj}kaU;3`An&ypmc4h9VhIf zG;+!qGBs1@gsG+2gU*y0Y50JcUV;y)D1xAjhu^x}b(h}$+@E~@_&j|7`F=jH&*u%L z*?=Z=?ARUF%2(nv2aF3y#X5Z+g%u<)LiS(y@}tx>cPz)&G0Qe&A*OK@Raq{8^q_F- zbB{#>iF|Dz=b)|E490O%W`;sOzn*Dtd$W+q>f!h2aWn3xA)rK!kjYY12Cz2VS^ia? zJKzn{oZ*j8$vKNhzKW^O#IziXdU8FzD*|<eD@NYnUd~^Sa_N2j2lXf(hj_l!WF(Xz z^@k=+XFN;5_JiKlfolqV3uj7S$m~OhGOU?ARvy2Z3xiBLmvwf9s?~oQZlIxv;1!zu zbzM+@IZwGj2G3`h`BuLoys*(veF#j!uuCmX7XnXQP{(9>l8|3~Qb0L3W_@O8Bou2S z#LwPyeSHU4SGh|_3O@<jVw-ulMAQSCYtw-BmUoczrKImN`3b_5sj-MBHFstycPr9Q zyDc_LT!%)FD#_s5hLIl5UXnDPD@{u}7ViyT0SH2%u*0u$j#2PSivDR6be36cLR7JI z>P9Io$LN#}Hy;+P)k<}%cC(5=1%>EC`mJ`K9DhLsMXNnTY7b5%xHS-GMy*X>nRI$s zn4{EJv>{B*zOB8Z6U4SCeQg`RoRS%(Z&ez2MRsCB5pII*p9!eO5eo6@SX?5Fv~;uk zMYgdE|JNdavOxx(M+a9JGE#v?A50YtD7>vh#2-d%9rOK)Okcl?dlmE3Udha-PBwlx zw<*_LcZb-D6dfZP2dfe{<%37d#Ki?z2z!rK7Yx~>r3c$JM1<s%-6TO8VzA^PvIA2p zr@^=X@pVnNrWr5+)70e+;E{U_fA>jX*E;3D-245!%MWU2YQwru2>?*S{bGVA^+1FB z8-;3y!|ILos18QJB|+U;YN8OP0+aw@s+)wy9IvNaJ!a&tRX-rM!{|#hNL**Yt+QAN zJh9_Kysv$_Bh~mb8`5JR&ddJMoa1}#T#i6&vzy$;rqF-rzqsGWd$8<0N-IB0;jPp~ z22J;hV9a6Hf&ScQfGR<EF*<B2wZ4daZ;nx^i0)Iqacq`d{&rb6l&4^4_yVusv+Swi z1ak*`wtFPmFfS9Bu<1ZooEm+61;F<$9g=?5M=jQYQ<c*bH6}vQ?^dJ9a3$sY-ekEM zucY8tA{+GF>N<>h`Nd1)Ci8h@bC`iSpmOlA7MwV}^GPJS^lC&^e~*O6GRb2rQ1h+d zB*q7XIxlAAlVK8>hUhH`Qg4!ZahPpe$wQ2fuN{FV4;STob=J3cl1ux;sphvTO-et5 za=9(yX3Y%vwwp~zE$z|267_p4(cyK{(@S=d<tY<GLiz(@c9y?d_xCfA^QuQ;p;6U- zgkHj3QM@#;1&o%EeQo}R%l?CeiQ{1XPRZF1iUXvrAI<|wei)IyMDNH*+K}a%dA%B_ zeZmRAs#0yds@p(lDKZT^e7?L|o5?bXMz^W(-3eHtg@A>Cg@A>Cg@A>?|4(4iWQ{Gq K#Rh>6g8l&!3vo*T literal 0 HcmV?d00001 diff --git a/tests/f_badcluster/name b/tests/f_badcluster/name new file mode 100644 index 0000000..266f81c --- /dev/null +++ b/tests/f_badcluster/name @@ -0,0 +1,2 @@ +test alignment problems with bigalloc clusters + diff --git a/tests/f_badcluster/script b/tests/f_badcluster/script new file mode 100644 index 0000000..ba6b248 --- /dev/null +++ b/tests/f_badcluster/script @@ -0,0 +1,25 @@ +if test -x $DEBUGFS_EXE; then + IMAGE=$test_dir/../f_badcluster/image.gz + OUT=$test_name.log + EXP=$test_dir/expect + gzip -d < $IMAGE > $TMPFILE + ../misc/tune2fs -L test_fs $TMPFILE + ../e2fsck/e2fsck -fy $TMPFILE > $OUT + ../e2fsck/e2fsck -fy $TMPFILE >> $OUT + ../e2fsck/e2fsck -fy $TMPFILE >> $OUT + for i in a b c d e f g; do echo "stat /$i"; done | $DEBUGFS_EXE $TMPFILE >> $OUT + + cmp -s $OUT $EXP + status=$? + + if [ "$status" = 0 ]; then + echo "$test_name: $test_description: ok" + touch $test_name.ok + else + echo "$test_name: $test_description: failed" + diff $DIFF_OPTS $EXP $OUT > $test_name.failed + rm -f $test_name.tmp + fi +else + echo "$test_name: skipped" +fi
As far as I can tell, logical block mappings on a bigalloc filesystem are supposed to follow a few constraints: * The logical cluster offset must match the physical cluster offset. * A logical cluster may not map to multiple physical clusters. Since the multiply-claimed block recovery code can be used to fix these problems, teach e2fsck to find these transgressions and fix them. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- e2fsck/pass1.c | 52 +++++++++++ e2fsck/pass1b.c | 42 ++++++++- e2fsck/problem.c | 5 + e2fsck/problem.h | 3 + tests/f_badcluster/expect | 198 +++++++++++++++++++++++++++++++++++++++++++ tests/f_badcluster/image.gz | Bin tests/f_badcluster/name | 2 tests/f_badcluster/script | 25 +++++ 8 files changed, 320 insertions(+), 7 deletions(-) create mode 100644 tests/f_badcluster/expect create mode 100644 tests/f_badcluster/image.gz create mode 100644 tests/f_badcluster/name create mode 100644 tests/f_badcluster/script -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html