13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass4.c -- pass #4 of e2fsck: Check reference counts 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 1021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 1121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Pass 4 frees the following data structures: 1221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * - A bitmap of which inodes are in bad blocks. (inode_bb_map) 13aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 1721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 18fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger#include <ext2fs/ext2_ext_attr.h> 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 205c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o/* 215c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * This routine is called when an inode is not connected to the 225c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * directory tree. 23efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 245c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * This subroutine returns 1 then the caller shouldn't bother with the 255c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * rest of the pass 4 tests. 265c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o */ 27fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilgerstatic int disconnect_inode(e2fsck_t ctx, ext2_ino_t i, 28fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger struct ext2_inode *inode) 295c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o{ 301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 3121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 32fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger __u32 eamagic = 0; 33fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger int extra_size = 0; 345c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o 35fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) { 36fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super), 37fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger "pass4: disconnect_inode"); 38fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize; 39fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger } else { 40fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode"); 41fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger } 4221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 4321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = i; 44fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger pctx.inode = inode; 45efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 46fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0) 47fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE + 48fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger extra_size); 490684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o /* 500684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o * Offer to delete any zero-length files that does not have 510684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o * blocks. If there is an EA block, it might have useful 520684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o * information, so we won't prompt to delete it, but let it be 530684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o * reconnected to lost+found. 540684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o */ 55fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC && 56fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) { 571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) { 58efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2fsck_clear_inode(ctx, i, inode, 0, 595c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o "disconnect_inode"); 605c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o /* 615c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * Fix up the bitmaps... 625c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o */ 63f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 640684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, i, -1, 65fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger LINUX_S_ISDIR(inode->i_mode)); 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_data_inodes(ctx->qctx, inode, i, -1); 675c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o return 0; 685c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o } 695c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o } 70efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 715c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o /* 725c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * Prompt to reconnect. 735c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o */ 741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) { 7508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (e2fsck_reconnect_file(ctx, i)) 765c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o ext2fs_unmark_valid(fs); 775c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o } else { 785c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o /* 795c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * If we don't attach the inode, then skip the 805c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * i_links_test since there's no point in trying to 815c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * force i_links_count to zero. 825c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o */ 835c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o ext2fs_unmark_valid(fs); 845c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o return 1; 855c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o } 865c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o return 0; 875c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o} 885c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o 895c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o 9008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass4(e2fsck_t ctx) 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 9386c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t i; 94fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger struct ext2_inode *inode; 958bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 978bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 9821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 9921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o __u16 link_count, link_counted; 100bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o char *buf = 0; 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t group, maxgroup; 102efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1036d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 4"); 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 10921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 1101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 1121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_4_PASS_HEADER, &pctx); 1131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 114f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o group = 0; 1157f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o maxgroup = fs->group_desc_count; 116f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if (ctx->progress) 1177f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if ((ctx->progress)(ctx, 4, 0, maxgroup)) 118a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o return; 1195830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen 120fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super), 121fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger "scratch inode"); 122fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger 1235830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen /* Protect loop from wrap-around if s_inodes_count maxed */ 1245830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) { 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int isdir; 126992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o 1274cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 12806c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorf goto errout; 129f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if ((i % fs->super->s_inodes_per_group) == 0) { 130f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o group++; 131f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if (ctx->progress) 1327f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if ((ctx->progress)(ctx, 4, group, maxgroup)) 13306c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorf goto errout; 134f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o } 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (i == EXT2_BAD_INO || 1367f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super))) 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) || 139aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o (ctx->inode_imagic_map && 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) || 1411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (ctx->inode_bb_map && 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i))) 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 1441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count); 1451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_fetch(ctx->inode_count, i, &link_counted); 14621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (link_counted == 0) { 147bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o if (!buf) 148bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf = e2fsck_allocate_memory(ctx, 149bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o fs->blocksize, "bad_inode buffer"); 150bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o if (e2fsck_process_bad_inode(ctx, 0, i, buf)) 151e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o continue; 152fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger if (disconnect_inode(ctx, i, inode)) 1531e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o continue; 1541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_fetch(ctx->inode_link_info, i, 1551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &link_count); 1561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_fetch(ctx->inode_count, i, 1571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &link_counted); 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i); 160992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o if (isdir && (link_counted > EXT2_LINK_MAX)) 161a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger link_counted = 1; 16221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (link_counted != link_count) { 163fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger e2fsck_read_inode(ctx, i, inode, "pass4"); 16421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = i; 165fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger pctx.inode = inode; 166992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o if ((link_count != inode->i_links_count) && !isdir && 167992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o (inode->i_links_count <= EXT2_LINK_MAX)) { 1681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.num = link_count; 1691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, 1701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o PR_4_INCONSISTENT_COUNT, &pctx); 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 17221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = link_counted; 173a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger /* i_link_count was previously exceeded, but no longer 174a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger * is, fix this but don't consider it an error */ 175992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o if ((isdir && link_counted > 1 && 176a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger (inode->i_flags & EXT2_INDEX_FL) && 177a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger link_count == 1 && !(ctx->options & E2F_OPT_NO)) || 178992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) { 179fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger inode->i_links_count = link_counted; 180fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger e2fsck_write_inode(ctx, i, inode, "pass4"); 18121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; 1851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; 1861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_bb_map); 1871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_bb_map = 0; 1887142db08c4e54a863fea2e757c6d3afa42ba2290Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_imagic_map); 1897142db08c4e54a863fea2e757c6d3afa42ba2290Theodore Ts'o ctx->inode_imagic_map = 0; 19006c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorferrout: 191bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o if (buf) 192c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 193fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger 194fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger ext2fs_free_mem(&inode); 1959facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io); 1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 198