From 19961cd0003564c63c33ec14e69dfec6d81a2238 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Mon, 30 Nov 2015 15:26:35 -0500 Subject: [PATCH] e2fsck: fix e2fsck -fD directory truncation When an extent-mapped directory is compacted by "e2fsck -fD" and frees enough leaf blocks that it loses an extent tree index block, the old e2fsck_rehash_dir->ext2fs_block_iterate3->write_dir_block() code would not free the extent block, which would result in the extent tree becoming corrupted when it is written out. Pass 1: Checking inodes, blocks, and sizes Inode 17825800, end of extent exceeds allowed value (logical block 710, physical block 570459684, len 1019) This results in loss of a whole index block of directory leaf blocks and maybe thousands or millions of files in lost+found. Fix e2fsck_rehash_dir() to call ext2fs_punch() to free the blocks at the end of the directory instead of trying to handle this itself while writing out the directory. That properly handles all of the cases of updating the extent tree as well as accounting for blocks that are released (both leaf blocks and index blocks). Add a test case for compacting the directory to be smaller than the index block that originally caused the corruption. Signed-off-by: Andreas Dilger Signed-off-by: Theodore Ts'o --- e2fsck/rehash.c | 72 ++++++++++++++++++---------------- tests/f_extent_htree/expect.1 | 29 ++++++++++++++ tests/f_extent_htree/expect.2 | 7 ++++ tests/f_extent_htree/image.gz | Bin 0 -> 10101 bytes tests/f_extent_htree/name | 1 + tests/f_extent_htree/script | 69 ++++++++++++++++++++++++++++++++ tests/f_h_badnode/expect.1 | 2 +- tests/f_h_badnode/expect.2 | 2 +- 8 files changed, 147 insertions(+), 35 deletions(-) create mode 100644 tests/f_extent_htree/expect.1 create mode 100644 tests/f_extent_htree/expect.2 create mode 100644 tests/f_extent_htree/image.gz create mode 100644 tests/f_extent_htree/name create mode 100644 tests/f_extent_htree/script diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c index 8ff488381..52d99a3cc 100644 --- a/e2fsck/rehash.c +++ b/e2fsck/rehash.c @@ -52,10 +52,13 @@ #include "e2fsck.h" #include "problem.h" +#undef REHASH_DEBUG + struct fill_dir_struct { char *buf; struct ext2_inode *inode; errcode_t err; + ext2_ino_t ino; e2fsck_t ctx; struct hash_entry *harray; int max_array, num_array; @@ -625,8 +628,8 @@ static errcode_t calculate_tree(ext2_filsys fs, struct write_dir_struct { struct out_dir *outdir; errcode_t err; + ext2_ino_t ino; e2fsck_t ctx; - blk64_t cleared; }; /* @@ -643,28 +646,35 @@ static int write_dir_block(ext2_filsys fs, blk64_t blk; char *dir; - if (*block_nr == 0) +#ifdef REHASH_DEBUG + printf("%u: write_dir_block %lld:%lld", wd->ino, blockcnt, *block_nr); +#endif + if (*block_nr == 0) { +#ifdef REHASH_DEBUG + printf(" - skip\n"); +#endif return 0; + } + /* Don't free blocks at the end of the directory, they will be + * truncated by the caller. */ if (blockcnt >= wd->outdir->num) { - e2fsck_read_bitmaps(wd->ctx); - blk = *block_nr; - /* - * In theory, we only release blocks from the end of the - * directory file, so it's fine to clobber a whole cluster at - * once. - */ - if (blk % EXT2FS_CLUSTER_RATIO(fs) == 0) { - ext2fs_block_alloc_stats2(fs, blk, -1); - wd->cleared++; - } - *block_nr = 0; - return BLOCK_CHANGED; +#ifdef REHASH_DEBUG + printf(" - not freed\n"); +#endif + return 0; } - if (blockcnt < 0) + if (blockcnt < 0) { +#ifdef REHASH_DEBUG + printf(" - skip\n"); +#endif return 0; + } dir = wd->outdir->buf + (blockcnt * fs->blocksize); wd->err = ext2fs_write_dir_block3(fs, *block_nr, dir, 0); +#ifdef REHASH_DEBUG + printf(" - write (%d)\n", wd->err); +#endif if (wd->err) return BLOCK_ABORT; return 0; @@ -684,10 +694,10 @@ static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs, wd.outdir = outdir; wd.err = 0; + wd.ino = ino; wd.ctx = ctx; - wd.cleared = 0; - retval = ext2fs_block_iterate3(fs, ino, 0, 0, + retval = ext2fs_block_iterate3(fs, ino, 0, NULL, write_dir_block, &wd); if (retval) return retval; @@ -699,14 +709,17 @@ static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs, inode.i_flags &= ~EXT2_INDEX_FL; else inode.i_flags |= EXT2_INDEX_FL; - retval = ext2fs_inode_size_set(fs, &inode, - outdir->num * fs->blocksize); +#ifdef REHASH_DEBUG + printf("%u: set inode size to %u blocks = %u bytes\n", + ino, outdir->num, outdir->num * fs->blocksize); +#endif + retval = ext2fs_inode_size_set(fs, &inode, (ext2_off64_t)outdir->num * + fs->blocksize); if (retval) return retval; - ext2fs_iblk_sub_blocks(fs, &inode, wd.cleared); - e2fsck_write_inode(ctx, ino, &inode, "rehash_dir"); - return 0; + /* ext2fs_punch() calls ext2fs_write_inode() which writes the size */ + return ext2fs_punch(fs, ino, &inode, NULL, outdir->num, ~0ULL); } errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) @@ -715,32 +728,25 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) errcode_t retval; struct ext2_inode inode; char *dir_buf = 0; - struct fill_dir_struct fd; - struct out_dir outdir; + struct fill_dir_struct fd = { NULL }; + struct out_dir outdir = { 0 }; - outdir.max = outdir.num = 0; - outdir.buf = 0; - outdir.hashes = 0; e2fsck_read_inode(ctx, ino, &inode, "rehash_dir"); retval = ENOMEM; - fd.harray = 0; dir_buf = malloc(inode.i_size); if (!dir_buf) goto errout; fd.max_array = inode.i_size / 32; - fd.num_array = 0; fd.harray = malloc(fd.max_array * sizeof(struct hash_entry)); if (!fd.harray) goto errout; + fd.ino = ino; fd.ctx = ctx; fd.buf = dir_buf; fd.inode = &inode; - fd.err = 0; - fd.dir_size = 0; - fd.compress = 0; if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) || (inode.i_size / fs->blocksize) < 2) fd.compress = 1; diff --git a/tests/f_extent_htree/expect.1 b/tests/f_extent_htree/expect.1 new file mode 100644 index 000000000..223ca6979 --- /dev/null +++ b/tests/f_extent_htree/expect.1 @@ -0,0 +1,29 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 3A: Optimizing directories +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** + + 352 inodes used (41.12%, out of 856) + 0 non-contiguous files (0.0%) + 1 non-contiguous directory (0.3%) + # of inodes with ind/dind/tind blocks: 0/0/0 + Extent depth histogram: 342/1 + 586 blocks used (68.94%, out of 850) + 0 bad blocks + 0 large files + + 340 regular files + 3 directories + 0 character device files + 0 block device files + 0 fifos + 0 links + 0 symbolic links (0 fast symbolic links) + 0 sockets +------------ + 343 files +Exit status is 1 diff --git a/tests/f_extent_htree/expect.2 b/tests/f_extent_htree/expect.2 new file mode 100644 index 000000000..860b491e5 --- /dev/null +++ b/tests/f_extent_htree/expect.2 @@ -0,0 +1,7 @@ +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_filesys: 352/856 files (0.3% non-contiguous), 586/850 blocks +Exit status is 0 diff --git a/tests/f_extent_htree/image.gz b/tests/f_extent_htree/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..284207efb12a04136c9f26c33f2197fed97cbd99 GIT binary patch literal 10101 zc-p0Td0Z1o7cJ_iamGIlSR@#rb#O$17*P?G zCGNPA5kzDO?M7e(5)mN^geXA+M$(1|owe%~ev0Au{(Fyql1_DXRo#2ex#u>Nq``yF zo4al9KOktoUtqwTg?l2x0s`iS`yDjvkdR6?)^)Y1?D78Ale(K9|7D#R-cWU6M_Kbf zhj(~v{Bz^kVHTtN72A!Oee?M788hbZbf1=Z-(lXM;+>&44Zd!g-Qqx-H~)YP?lA7W5S@LV&L#i-SEPE+ zZP1A7o9~U99;5m9$r|nfL4Bg{b>9eRDVWVD|>ZaxqiYoNc?$ zAwtlyJeY-TTEcs%NaM5SjMF{sq{xv+hbkUlrf=`8DWi#f4eC2;`W@{%xq9!~_Du`l z-D_xw-z@(8VZptefnP#*S2bO%PoiBcFqSlwNkg^DVm@-gCHl!Hd~AnZkfG&msJMHp zadq)^61BT#6TQpu5EOq%Iz-!|_e)sm{Bh2wZLHT>8#asMV%Bv5oMUMw_>@$e32q}s z&p1L8N0-=Xg0)sFHc3hul8681KBZ?|I3TansZ~S4rPT@TH{M)&0%8qga;IPvP3S^C z=>GVKODjXW)!C~S=|kfPyIS#Kq+Wzx*o4?44!BzgUuRHOeFlXW-|6;A*U^zGqH}a? zeuWEXQy^{1a$~09OhTPeV@xsx`Xk3sTpgvM`5C|pVuV0zs~`J;C;EbS(*3B!Y<4-4 z${>Q1)%0Kk!Lbw48kj`+I5{Oa0}PVkNQO!iY9~bU7{u0OwRCR=Qo1uD&SD-Iyb47jBTY=j@<<=ovFNRdi~A697s$H_rHgGfkL)AnT`HyFfn z_zgbmoJzzkPc8>X8N^$G775G%Gi8QwIJSQqA{r-0>X`(0p%DDVAjY!QsDF%szcT}D zk{Nj8QJ{wNiWmfKoCr|ZYLSBwz~>gQIcQX}8V#lb%t{U(JAwp(mbO3$?lTC_WHquo z1BA;Abhw=tjzBEXqVt8|9)rM=#Zru2j=pgOBV`8KI5~ZHjA4!g8F1jP7G;4k0vRZC z1l(jbZ-J1$D+8_9Xh6C-uBTWcPaKiRCkF|uaq`eT8OR(Nj^0;k#EXQ|*GwXPyqsRn zB*gY)a7dsPI|$LsDm|LQAlPg3)F3P&(pW*BRQ0ynsw zTMWWapj|!=1!?0sAWWvB2W5a+GJ_W!7h7_WYYbwYKur@k0&kfX6*_{U0&V$tIa=cg zss-g>4t!vpBVfu5qmredk*$^nQNbwq0S^@-Gn|3gV8LDU7{o1s7F#H!RckcqAyk5t zTuyt&G@y%w;1mQY1e2W*z|bs*-yn3(Gl=QQYSAJ>t6w5h(E_N1lR(Rbs0f5Wg)DKB z;b5T5U<-l2TA-yvM8UX-;S7k}Zvd5ZLk(*A8kr#!rhAD%E43GbECyi?@dy!fgh6oF z3NT8hLiT<~Ckp76a?s!i90V9x1_vN9STZf$KLa_zASlUdTYDke1R+?%G|gYLIxke)uJ0kFSQmG?=2r-ApFkeIllLa!`Ye(>2phloP41*tMRT|DBA(G7afz7uX z4Nb^2lv~MZPnd+~0wI#CGDN|FYIp@X7bMUYTgl;K;5V6!m#xykbRzKdz5=bt-h~h@ zBqJ1=Ar?ZItJ095=D~EFQt6RWmBx0S5V@=}n8W>+LB*Ue{0`0pD>+)_2tEk3Ja`8@ z{2ewz_(FoEK;Vv-Q}#m*g)2wGafd9(99a)I*Fe3T9|uD1g-E)};5m;BIv@aHbWXtW zN=GoY2b@v>!AXPU-2f2_sft^1pnPg5^Mv4%%Fu%bH-Q>h$yDFbDYcYy17Zx$P|_GO zEq8wgh=SwSR2s-W1m2CoCkC?1K?Z}6L-E{WAW+EqH28Hd74RTxa#R{RlsF31(PMCy zl^m&c1Y03IA%b%l1PnSpCbLAX#uhComTQ3)P=K3k<33u(VZ zW{_IRzd;mgemsM?F3_ey-qIkF|78+hP;$%Q2V`-oN)rsR)xb2Y-=B`|$Ut8>A_HWG zp=>oopA<@P0|X~jQ&>JG$_&+PH7_s&iIo|w3`w1UMgtHg0)f^6qU{2MsAhA(H;88R z$YUd%78GL$4WtqsQ1HIPGns?dLoqFLMADIEac2KNe~*zHvtsSfEZfuwCVFkkuLHFk zW$bG!H}RT{qz6t{@yF_-Vs!cfv}oNXa3njDc83y9GGqtq=%0}2u8TU-yAy-{=(p53 z;1bdAPhfTvF?&rj`$RG8GC!;%{qJW(_Dx~jf9(8cnept-ps~R7GQ;&)8$I)e>Mkn_ z30qt{u=T}wKFh(+;(rq#Q`kf7{~l6Ow`flLgs->L6Y5+R;2v%F7y zU#$&pdXVDz2#(&^C|f;QuZHJS}LPk;R}I*DgQ zrLmzS6DO=`z)8w+CDcpYe-AWoq+1RzqV0V z)l(N%l!^bn7)UDA{2punqNVX`{$>m5`#7P$YHIAg%(4wl+{sB;n!R-S=N1y2v~rul zD)!!)GPKT1Z4Fna9r4%!%E9 zx(sU%uC?*K#H-HLY>3^TRYw05oMhvBlQ$=inNs@jMay+v!{Q|5m3Wa)$$EO@Zq;7s zmRe>>9#pmbx9IKMr1ZAkdYh1(^ohC50g}(>%hKC!Y_bTwoSvD>w32+zC~IuL5ouBI zs(P+ZNm59IKVz%p^To2uAqOj4PKPw?R`DY8SQgkO@9>UONsWr%D|X`H_Ejxzk)r|_ zB*}B1nBn*sK(!(sG>egH=%Wl7Mx-78mqnA(2!;ppmRdmtYDM|YF-69+E zwRC>2W|`!3W?5R>ZmtbECp|V#^Q+{6s3kZek8Z)KuO@tA_#wk?(um0L9Yz%|J^m91 zkxbZz7!)5*>11?=gn9}na=J@s#MSS+%F&RMJ-60g?zv9+c73~NYDCY}T|HAH?$U@M zF$Ad%+(IB0A7g-8qV!0w@*2`iCv6JjYZs^p9J%a?f?Y?#$3@)H%q-|K0!VgTto zIJ2oVEK~U+3OVZc;Nx3EDHqr#-2JhNVee;_C@n`@>WYbgSAER#47mu*p7vwhOb23` z0o@`xA^La|J}IYC4W2%~8f@kb`niA}=DY;@2!PBVS@;*r?5`E__k-ROAnZif57Gi| zWvRo6x2L0z&u+j^UI&~PRABydEY3F3<76Otr-OOp0V6UlwKp_hLG)+v>`KMbkCW$~ zb5HyV{2pt6$bk`Y!2rj@C6N4dm31!3h&Immjhzd5VM7 zo%KJb&*ibqN2R2nPpB~V-?2eO7?AZgxj%J4&E!WpSwyqdU>cr}OQA>k)!QUxd?h|o zjCBYx*PS>Y=M9m9u~U1)S<(&SaQ?~}VY`pWCly&q!BRjONOm?m+(mh(?pgkDD3l60 zkc4A7t@xyM7ZWp{szH2Mh3>n?RRjYJH-h`!tjTil?2=6`#fVfuO#E+oEkuk9;C`Ag zp%Qa#SuwrkfT|R5WDEKTk(fW$E#+;M+vsW5@>ig|3H*3;D8Rb3;I*^TxFZLc&sscU zz8EA>!S`I9k`hu(-F!W@WI_W;wA`8%0_Q?p|q;4kF0@D3%zN8(<=Iu0om*tm0 zt~!KWoBHbJs%x%(sbZ09(`L@!AF^;F^(C(%@CPTB0<1PV6gQw#oB-w8t%^V1>%e*S zPpECnQm>h9op~X_aaK|cjNF*^pQ{&Av5AAMix-$P3a!H|M8JF%Su)_U&isq^e~Fi7 z>w#pfSby-wK8xZ7C-uuFUpCgl$F@iR$GKCnGzt$-;0qkqbg z3}AlR+N7wZiTJBM_G$?lZa?@HJeEx-q|&#|Ee+8lsJ_`-zQe+Zd@Ah@N&aF0XHC^9 zORAojxUISixL%75-6{kL5V5`S(tgHwrqp}|uIGJ~toWq~E>&rr zRs)ug(e=>_F##NP;L=_7KMqEus+Ul3qg3hEUp*G>B%j_nwR68j4UDDc*8V1|s-r_s zROn#f&RnS&TncQDuQCxwYBzsc2Yya%KHXwUo(>VpIn*}I`BKn#2Rx=&K z)ge&?h=WnHPWgRP4xoSNQUmY4(CPpb_<+~j0az>s)2Svv5GnX)mbNa`fk!vXpZ@k< z3nI;znJ$hMMx|7ED}nj4%!IL!jh#1*z54WSJD|&;`YtA=L6uu))5&Hc1nur<)4)Ob zKfTlA+8p)pv`Xu%-;AF3P7|HMbq3^A+l0H=JH3C+ggf%H_1jJdn^^~I+xWoK9 z#H=1UEc&)YX%~p20eYivG)EfmUgqw<6`pfS79jOf?}M>fsYL>7K)LIzSAP+-&Wr{YQZF%Br697_DM>0`lV(G#a3~K@1r|BEB%!aWfAKNg3t3y$QdZjX7k&yTib3n*WrMeM)W#0{vCz zEV&oT8uvCWOe)}QQE$IAw|S*3FYggsAoo`(E%6sED`eq$kM63XeVW$Fnte(N1hKhH z8e6|x_a?6(QrA|s(vX?q9sdx`{Mv~`i<^c=t6_wT}rbsZ>Uv|ADvz-zZE(~_QA78M*5X(7F%viG5`kp<^5j|ryaY5dsB15{TnIl`9dcH}c< zox!jnLQ(;6dbTOrTA0NcwNu5JtlGxI5X8e8q9Jc8#Qq=1Vs}cj#*u1wxGbjhfWjOaHu3lt$5WjK3r` z=nvYH~=fy^mNu|C6HPGW^k02V*zn^M;-(b)5z!(da#9)H@Tvg`*N^sb_666BG%+AuUvcffZ6H?He`&80 zeFZLE{2(8Hw~v!&3amY0JziH~`dm~Fz2N}$@EZ+yvn!x5j6aox8ymV#4@O-`c$0~{ z93yB4Me(NP7>fyY8WU6jgS1i)aA*diDE~3lq1aIG5k4=dM}sCUI7!fEg&R%H4wxMT zz;Ei|f8VP3RR>NHKMzwY=a*Sa7n=KR85#ZHoeo%X<&(SGIuVl-`DOxJk~Ozp($m;& z#orXmhBR}5d6RmQNpW(b!fr`>I(qQzlnQ7#Cf)p}PbN35PtiL9?1n43Rfpig!%a-& zFdi#P1h%dMl%n$H>dWwKDx^12C5oQH(?6X{zd|*mNZA&bmcr=+9x` zB0-OJre08<#S*h2YAdbv2LR%o>}^tPjio)TB14aJZN^B5zkZ@0g#jWV7h5w*tUiQH zJi5eaI|LrAv+XObkB{I_8s<@ddt}g`-XFTUfYNDjr87#pvhC}gZXc8W^)*OapArBM zyvy0*#;;P4)~B8G#rf0l$WXbOb?S{X9x?>5Bl7ly8u&@vO;8aY)x2azVuU}r#ar$-yQiOV8D{%qPfQN3CVB;d&&Wv~LnbtY=~d zAelsQP7vyFIQn=}K+5!XaCL@hQ`cF9pRSlEgkEUY0=5Foo>t#yZHp71pHQDq%S_l! z1-5@YGNF^G)M2y_^a`+>jDStvR8t3bA8=M%H_kI>OdA=r5>WJC2b%R2q+*)|?C9gC z|MVXY#f8z=)ynyWJbv1!Hn0nC(&s>(?IrQ4MnbBNvmLEH5k0svAVt&$+_)xrGBcu{ zM&!29HxPRG6$4VP_B@!y#|VL`YXgYQf~@G{t8P_XDI!n-rf~H(Wfw>~QZcZ~ zZQE}io8ertGr{SFSCkQ9OGPZPljB)}c5=3LUOTAl&0lK)v`1Q`Y@>hp$H@mpu4iWn z0V_gp$^xDa+?=t18-0A6OmT=V;)1bhyG-AOVE8bPhWX}*&Kq3_w{UxEUt>2dGd}kKA%$IWq8z05mY#23mx~R}*MbYtgSX3A$051b zn+ka+0TL^UtK2reCXl61^aO1MRoCClRBt7?@8}DUjo=820B5!V`dm}b_!cixG^0Dn zPgmK5Er8Xq)a1QVt)h8DitK!X<0|*tx3>ZGg#wH3MIekBPgRW7IgNu-yJ?lR(GgIl zj_9LUM&J80!WO||cztQ>a!7bL(}3xl6BorqEi_+uYsP|j0$pap)gWj^qp!R(#ty%w zZ_q=|K06Fs;-6c_JW?vALX0GySV4!i;j#%0A=Y5K=UnA>_L{Z$6(ITbDZ{AOTK8qJ zVP0-M(};}wPu~ncYw;e2v4)Ut*OflUrSUI+dINPd8nx1Y20RL5UF&EaIIl42qo~-# zJ!sTW*i3A8pW6yIwD$jc;lcPgIq`+HxCU;>w0_IFn#&R^>fmnAxtHEmfZ&p>gav(G zD}Zn*C>Ww1o_(Z(SEg5kb)Rc&`@S{gM|tRhvZrBxfX&$$4I8Z)hc@choU=c>)`#jr z-!dpSAisj|Q*uwRA&*I7W0ftL_N8>Z=*;#z+VQ`B_gy;D7cA$#6vbv1Vu&w*A>HEd%LizWV zcYL?!cm1xEQVw)HOfLdN$uDyjg(JW--h~u#^VLg8`E|xqn>{JH#ma0U^Ygr@63MIGs`p2f(n97w65h2i zbX#t2JmGzMOn&f0S&paWm$#`CB>^+5%}d+foL1s*+b;^0^X)n47oR{}aofo@Qn8+) zX1Ft7@gh(!sg-9)wmvngK0@M#cSxBJ8?%bg{m+%z*mb=}O`UUhz44PrFt?DS#6V}! zLcGo>PWtcHeLQ`2bMd>o#wN#v>+;Xo$C(!y!hTBQ1^bq!0g<5outYbZbyz012zU0z zcNJG*$Z=&6gJ0`oSI59uu1!vzr`SS41_P zbs>kHtwd!hX%jk#V)H7rbzD?Treo`?lSOpLs5b|qkS*w13fplro<1S&NkC>KWl*|r zbJ;|5UI(*`5dvD`y(VHGjn7q6JYO249FoUHUeRMzyST3_LtF+;SkIENowtG1s z+XdT@#3fmQzRXW_ z_rKxt3ya=$FO;Z87L;7gUZPA3byC?lD80}k#XbqeOaE0OZzE)nYFmAaxM5w}&xj&r zO$Tb6<%K}`wnN#`aWdOEE308S&PpC1iO?m|nvd^;j7`*#(|=$X!S_`3u{g*G?ELK;z8<9%WWetSLTdu|Glr- zQB}3V%b8x(G?7D!U}}Gr*wXweW_x{#<43dydleew{COhh)hy0?hmtt9GJ*c6+YlTH z{JAGWPrf#Gr4DE&U)Q@xe~XKHpm(YXB3QecxS<7nmvM@dvj2J^F`4>57VHvE7b^%p zX)$srUN2vJLI2j#fySAjDPt?;PZPgXrbi&vxlibl&xF?HYH49vH7m(tNN8kvhstYi z$r{|M%30H>Dhdr#BuLjDP%|rTVj)rLktLmyiA7w#|JN%^B;4ub68|fexG-?FGE5d5 z_W9MykW%5AG|4@^#n55iE^jAtcX?`5WUqqNT;0DC+d}Z{`WU6}zjdCak6uZpJC(?v k(+XKrm&7(4>N3VW_|N~tzi /dev/null) +TMPFILE=${TMPFILE:-"$TMPDIR/image"} +BSIZE=1024 + +> $OUT +mkdir -p $SRC/$SUB +# calculate the number of files needed to create the directory extent tree +# deep enough to exceed the in-inode index and spill into an index block. +# +# dirents per block * extents per block * (index blocks > i_blocks) +NUM=$(((BSIZE / (NAMELEN + 8)) * (BSIZE / 12) * 2)) +# Create source files. Unfortunately hard links will be copied as links, +# and blocks with only NULs will be turned into holes. +if [ ! -f $BASE.1 ]; then + for N in $(seq $NUM); do + echo "foo" > $BASE.$N + done >> $OUT +fi + +# make filesystem with enough inodes and blocks to hold all the test files +> $TMPFILE +NUM=$((NUM * 5 / 3)) +echo "mke2fs -b $BSIZE -O dir_index,extent -d$SRC -N$NUM $TMPFILE $NUM" >> $OUT +$MKE2FS -b $BSIZE -O dir_index,extent -d$SRC -N$NUM $TMPFILE $NUM >> $OUT 2>&1 +rm -r $SRC + +# Run e2fsck to convert dir to htree before deleting the files, as mke2fs +# doesn't do this. Run second e2fsck to verify there is no corruption yet. +( + EXP1=$test_dir/expect.pre.1 + EXP2=$test_dir/expect.pre.2 + OUT1=$test_name.pre.1.log + OUT2=$test_name.pre.2.log + DESCRIPTION="$(cat $test_dir/name) setup" + . $cmd_dir/run_e2fsck +) + +# generate a list of filenames for debugfs to delete, one from each leaf block +DELETE_LIST=$TMPDIR/delete.$$ +$DEBUGFS -c -R "htree subdir" $TMPFILE 2>> $OUT | + grep -A2 "Reading directory block" | + awk '/yyyyy/ { print "rm '$SUB'/"$4 }' > $DELETE_LIST +$DEBUGFS -w -f $DELETE_LIST $TMPFILE >> $OUT 2>&1 +rm $DELETE_LIST +cp $TMPFILE $TMPFILE.sav + +. $cmd_dir/run_e2fsck diff --git a/tests/f_h_badnode/expect.1 b/tests/f_h_badnode/expect.1 index ce2adb3f4..95b1cee8a 100644 --- a/tests/f_h_badnode/expect.1 +++ b/tests/f_h_badnode/expect.1 @@ -14,5 +14,5 @@ Pass 4: Checking reference counts Pass 5: Checking group summary information test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks +test_filesys: 47730/100192 files (0.0% non-contiguous), 13550/31745 blocks Exit status is 1 diff --git a/tests/f_h_badnode/expect.2 b/tests/f_h_badnode/expect.2 index b9dadb739..65985d140 100644 --- a/tests/f_h_badnode/expect.2 +++ b/tests/f_h_badnode/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks +test_filesys: 47730/100192 files (0.0% non-contiguous), 13550/31745 blocks Exit status is 0 -- 2.47.2