blob: 627b55488bfa77e215caf50b7cd2b2bbb555a867 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * pass4.c -- pass #4 of e2fsck: Check reference counts
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 *
11 * Pass 4 frees the following data structures:
12 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
Theodore Ts'o3839e651997-04-26 13:21:57 +000013 */
14
15#include "e2fsck.h"
Theodore Ts'o21c84b71997-04-29 16:15:03 +000016#include "problem.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000017
Theodore Ts'o5c576471997-04-29 15:29:49 +000018/*
19 * This routine is called when an inode is not connected to the
20 * directory tree.
21 *
22 * This subroutine returns 1 then the caller shouldn't bother with the
23 * rest of the pass 4 tests.
24 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +000025static int disconnect_inode(ext2_filsys fs, ino_t i)
Theodore Ts'o5c576471997-04-29 15:29:49 +000026{
27 struct ext2_inode inode;
Theodore Ts'o21c84b71997-04-29 16:15:03 +000028 struct problem_context pctx;
Theodore Ts'o5c576471997-04-29 15:29:49 +000029
30 e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode");
Theodore Ts'o21c84b71997-04-29 16:15:03 +000031 clear_problem_context(&pctx);
32 pctx.ino = i;
33 pctx.inode = &inode;
34
Theodore Ts'o5c576471997-04-29 15:29:49 +000035 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
36 LINUX_S_ISDIR(inode.i_mode))) {
37 /*
38 * This is a zero-length file; prompt to delete it...
39 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +000040 if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) {
41 ext2fs_icount_store(inode_link_info, i, 0);
Theodore Ts'o5c576471997-04-29 15:29:49 +000042 inode.i_links_count = 0;
43 inode.i_dtime = time(0);
44 e2fsck_write_inode(fs, i, &inode,
45 "disconnect_inode");
46 /*
47 * Fix up the bitmaps...
48 */
49 read_bitmaps(fs);
50 ext2fs_unmark_inode_bitmap(inode_used_map, i);
51 ext2fs_unmark_inode_bitmap(inode_dir_map, i);
52 ext2fs_unmark_inode_bitmap(fs->inode_map, i);
53 ext2fs_mark_ib_dirty(fs);
54 return 0;
55 }
56 }
57
58 /*
59 * Prompt to reconnect.
60 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +000061 if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) {
Theodore Ts'o5c576471997-04-29 15:29:49 +000062 if (reconnect_file(fs, i))
63 ext2fs_unmark_valid(fs);
64 } else {
65 /*
66 * If we don't attach the inode, then skip the
67 * i_links_test since there's no point in trying to
68 * force i_links_count to zero.
69 */
70 ext2fs_unmark_valid(fs);
71 return 1;
72 }
73 return 0;
74}
75
76
Theodore Ts'o3839e651997-04-26 13:21:57 +000077void pass4(ext2_filsys fs)
78{
Theodore Ts'of3db3561997-04-26 13:34:30 +000079 ino_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +000080 struct ext2_inode inode;
81 struct resource_track rtrack;
Theodore Ts'o21c84b71997-04-29 16:15:03 +000082 struct problem_context pctx;
83 __u16 link_count, link_counted;
Theodore Ts'o3839e651997-04-26 13:21:57 +000084
85 init_resource_track(&rtrack);
86
87#ifdef MTRACE
88 mtrace_print("Pass 4");
89#endif
90
91 if (!preen)
Theodore Ts'of3db3561997-04-26 13:34:30 +000092 printf("Pass 4: Checking reference counts\n");
Theodore Ts'o21c84b71997-04-29 16:15:03 +000093 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +000094 for (i=1; i <= fs->super->s_inodes_count; i++) {
95 if (i == EXT2_BAD_INO ||
Theodore Ts'o7f88b041997-04-26 14:48:50 +000096 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
Theodore Ts'o3839e651997-04-26 13:21:57 +000097 continue;
Theodore Ts'o21c84b71997-04-29 16:15:03 +000098 if (!(ext2fs_test_inode_bitmap(inode_used_map, i)) ||
99 (inode_bb_map &&
100 ext2fs_test_inode_bitmap(inode_bb_map, i)))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000101 continue;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000102 ext2fs_icount_fetch(inode_link_info, i, &link_count);
103 ext2fs_icount_fetch(inode_count, i, &link_counted);
104 if (link_counted == 0) {
Theodore Ts'o5c576471997-04-29 15:29:49 +0000105 if (disconnect_inode(fs, i))
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000106 continue;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000107 ext2fs_icount_fetch(inode_link_info, i, &link_count);
108 ext2fs_icount_fetch(inode_count, i, &link_counted);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000109 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000110 if (link_counted != link_count) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000111 e2fsck_read_inode(fs, i, &inode, "pass4");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000112 pctx.ino = i;
113 pctx.inode = &inode;
114 if (link_count != inode.i_links_count) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000115 printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000116 printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
117 "A MOUNTED (LIVE) FILESYSTEM.\n");
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000118 printf("inode_link_info[%ld] is %u, "
Theodore Ts'o3839e651997-04-26 13:21:57 +0000119 "inode.i_links_count is %d. "
120 "They should be the same!\n",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000121 i, link_count,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000122 inode.i_links_count);
123 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000124 pctx.num = link_counted;
125 if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) {
126 inode.i_links_count = link_counted;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000127 e2fsck_write_inode(fs, i, &inode, "pass4");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000128 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000129 }
130 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000131 ext2fs_free_icount(inode_link_info); inode_link_info = 0;
132 ext2fs_free_icount(inode_count); inode_count = 0;
133 ext2fs_free_inode_bitmap(inode_bb_map);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000134 if (tflag > 1) {
135 printf("Pass 4: ");
136 print_resource_track(&rtrack);
137 }
138}
139