pass4.c revision 5c576477ccb2f0ca8c5d5af2e2354fd8eeff1589
1/*
2 * pass4.c -- pass #4 of e2fsck: Check reference counts
3 *
4 * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
5 * under the terms of the GNU Public License.
6 *
7 */
8
9#include "e2fsck.h"
10
11/*
12 * This routine is called when an inode is not connected to the
13 * directory tree.
14 *
15 * This subroutine returns 1 then the caller shouldn't bother with the
16 * rest of the pass 4 tests.
17 */
18int disconnect_inode(ext2_filsys fs, ino_t i)
19{
20	struct ext2_inode	inode;
21
22	e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode");
23	if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
24				LINUX_S_ISDIR(inode.i_mode))) {
25		/*
26		 * This is a zero-length file; prompt to delete it...
27		 */
28		printf("Unattached zero-length inode %lu\n", i);
29		if (ask("Clear", 1)) {
30			inode_link_info[i] = 0;
31			inode.i_links_count = 0;
32			inode.i_dtime = time(0);
33			e2fsck_write_inode(fs, i, &inode,
34					   "disconnect_inode");
35			/*
36			 * Fix up the bitmaps...
37			 */
38			read_bitmaps(fs);
39			ext2fs_unmark_inode_bitmap(inode_used_map, i);
40			ext2fs_unmark_inode_bitmap(inode_dir_map, i);
41			ext2fs_unmark_inode_bitmap(fs->inode_map, i);
42			ext2fs_mark_ib_dirty(fs);
43			return 0;
44		}
45	}
46
47	/*
48	 * Prompt to reconnect.
49	 */
50	printf("Unattached inode %lu\n", i);
51	preenhalt(fs);
52	if (ask("Connect to /lost+found", 1)) {
53		if (reconnect_file(fs, i))
54			ext2fs_unmark_valid(fs);
55	} else {
56		/*
57		 * If we don't attach the inode, then skip the
58		 * i_links_test since there's no point in trying to
59		 * force i_links_count to zero.
60		 */
61		ext2fs_unmark_valid(fs);
62		return 1;
63	}
64	return 0;
65}
66
67
68void pass4(ext2_filsys fs)
69{
70	ino_t	i;
71	struct ext2_inode	inode;
72	struct resource_track	rtrack;
73
74	init_resource_track(&rtrack);
75
76#ifdef MTRACE
77	mtrace_print("Pass 4");
78#endif
79
80	if (!preen)
81		printf("Pass 4: Checking reference counts\n");
82	for (i=1; i <= fs->super->s_inodes_count; i++) {
83		if (i == EXT2_BAD_INO ||
84		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
85			continue;
86		if (!(ext2fs_test_inode_bitmap(inode_used_map, i)))
87			continue;
88		if (inode_count[i] == 0) {
89			if (disconnect_inode(fs, i))
90				continue;
91		}
92		if (inode_count[i] != inode_link_info[i]) {
93			e2fsck_read_inode(fs, i, &inode, "pass4");
94			if (inode_link_info[i] != inode.i_links_count) {
95				printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
96				printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
97				       "A MOUNTED (LIVE) FILESYSTEM.\n");
98				printf("inode_link_info[%ld] is %u, "
99				       "inode.i_links_count is %d.  "
100				       "They should be the same!\n",
101				       i, inode_link_info[i],
102				       inode.i_links_count);
103			}
104			printf("Inode %lu has ref count %d, expecting %d.\n",
105			       i, inode.i_links_count, inode_count[i]);
106			if (ask("Set i_nlinks to count", 1)) {
107				inode.i_links_count = inode_count[i];
108				e2fsck_write_inode(fs, i, &inode, "pass4");
109			} else
110				ext2fs_unmark_valid(fs);
111		}
112	}
113	free(inode_link_info);	inode_link_info = 0;
114	free(inode_count);	inode_count = 0;
115	if (tflag > 1) {
116		printf("Pass 4: ");
117		print_resource_track(&rtrack);
118	}
119}
120
121