Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / e2fsck / pass4.c
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  */
18 int 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
68 void 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