Whamcloud - gitweb
8c101fd2805c9953b11c3d67b9bd251b0e2d3b19
[tools/e2fsprogs.git] / e2fsck / pass4.c
1 /*
2  * pass4.c -- pass #4 of e2fsck: Check reference counts
3  *
4  * 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)
13  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
14  */
15
16 #include "config.h"
17 #include "e2fsck.h"
18 #include "problem.h"
19 #include <ext2fs/ext2_ext_attr.h>
20
21 /*
22  * This routine is called when an inode is not connected to the
23  * directory tree.
24  *
25  * This subroutine returns 1 then the caller shouldn't bother with the
26  * rest of the pass 4 tests.
27  */
28 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
29                             struct ext2_inode_large *inode)
30 {
31         ext2_filsys fs = ctx->fs;
32         struct problem_context  pctx;
33         __u32 eamagic = 0;
34         int extra_size = 0;
35
36         e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
37                                EXT2_INODE_SIZE(fs->super),
38                                "pass4: disconnect_inode");
39         if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
40                 extra_size = inode->i_extra_isize;
41         clear_problem_context(&pctx);
42         pctx.ino = i;
43         pctx.inode = EXT2_INODE(inode);
44
45         if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
46                 eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
47                                      extra_size);
48         /*
49          * Offer to delete any zero-length files that does not have
50          * blocks.  If there is an EA block, it might have useful
51          * information, so we won't prompt to delete it, but let it be
52          * reconnected to lost+found.
53          */
54         if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
55             (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
56                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
57                         e2fsck_clear_inode(ctx, i, EXT2_INODE(inode), 0,
58                                            "disconnect_inode");
59                         /*
60                          * Fix up the bitmaps...
61                          */
62                         e2fsck_read_bitmaps(ctx);
63                         ext2fs_inode_alloc_stats2(fs, i, -1,
64                                                   LINUX_S_ISDIR(inode->i_mode));
65                         quota_data_inodes(ctx->qctx, inode, i, -1);
66                         return 0;
67                 }
68         }
69
70         /*
71          * Prompt to reconnect.
72          */
73         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
74                 if (e2fsck_reconnect_file(ctx, i))
75                         ext2fs_unmark_valid(fs);
76         } else {
77                 /*
78                  * If we don't attach the inode, then skip the
79                  * i_links_test since there's no point in trying to
80                  * force i_links_count to zero.
81                  */
82                 ext2fs_unmark_valid(fs);
83                 return 1;
84         }
85         return 0;
86 }
87
88
89 void e2fsck_pass4(e2fsck_t ctx)
90 {
91         ext2_filsys fs = ctx->fs;
92         ext2_ino_t      i;
93         struct ext2_inode_large *inode;
94         int inode_size = EXT2_INODE_SIZE(fs->super);
95 #ifdef RESOURCE_TRACK
96         struct resource_track   rtrack;
97 #endif
98         struct problem_context  pctx;
99         __u16   link_count, link_counted;
100         char    *buf = 0;
101         dgrp_t  group, maxgroup;
102
103         init_resource_track(&rtrack, ctx->fs->io);
104
105 #ifdef MTRACE
106         mtrace_print("Pass 4");
107 #endif
108         /*
109          * Since pass4 is mostly CPU bound, start readahead of bitmaps
110          * ahead of pass 5 if we haven't already loaded them.
111          */
112         if (ctx->readahead_kb &&
113             (fs->block_map == NULL || fs->inode_map == NULL))
114                 e2fsck_readahead(fs, E2FSCK_READA_BBITMAP |
115                                      E2FSCK_READA_IBITMAP,
116                                  0, fs->group_desc_count);
117
118         clear_problem_context(&pctx);
119
120         if (!(ctx->options & E2F_OPT_PREEN))
121                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
122
123         group = 0;
124         maxgroup = fs->group_desc_count;
125         if (ctx->progress)
126                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
127                         return;
128
129         inode = e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
130
131         /* Protect loop from wrap-around if s_inodes_count maxed */
132         for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
133                 int isdir;
134
135                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
136                         goto errout;
137                 if ((i % fs->super->s_inodes_per_group) == 0) {
138                         group++;
139                         if (ctx->progress)
140                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
141                                         goto errout;
142                 }
143                 if (i == quota_type2inum(PRJQUOTA, ctx->fs->super) ||
144                     i == EXT2_BAD_INO ||
145                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
146                         continue;
147                 if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) ||
148                     (ctx->inode_imagic_map &&
149                      ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) ||
150                     (ctx->inode_bb_map &&
151                      ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i)))
152                         continue;
153                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
154                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
155                 if (link_counted == 0) {
156                         if (!buf)
157                                 buf = e2fsck_allocate_memory(ctx,
158                                      fs->blocksize, "bad_inode buffer");
159                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
160                                 continue;
161                         if (disconnect_inode(ctx, i, inode))
162                                 continue;
163                         ext2fs_icount_fetch(ctx->inode_link_info, i,
164                                             &link_count);
165                         ext2fs_icount_fetch(ctx->inode_count, i,
166                                             &link_counted);
167                 }
168                 isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i);
169                 if (isdir && (link_counted > EXT2_LINK_MAX))
170                         link_counted = 1;
171                 if (link_counted != link_count) {
172                         e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
173                                                inode_size, "pass4");
174                         pctx.ino = i;
175                         pctx.inode = EXT2_INODE(inode);
176                         if ((link_count != inode->i_links_count) && !isdir &&
177                             (inode->i_links_count <= EXT2_LINK_MAX)) {
178                                 pctx.num = link_count;
179                                 fix_problem(ctx,
180                                             PR_4_INCONSISTENT_COUNT, &pctx);
181                         }
182                         pctx.num = link_counted;
183                         /* i_link_count was previously exceeded, but no longer
184                          * is, fix this but don't consider it an error */
185                         if ((isdir && link_counted > 1 &&
186                              (inode->i_flags & EXT2_INDEX_FL) &&
187                              link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
188                             fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
189                                 inode->i_links_count = link_counted;
190                                 e2fsck_write_inode_full(ctx, i,
191                                                         EXT2_INODE(inode),
192                                                         inode_size, "pass4");
193                         }
194                 }
195         }
196         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
197         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
198         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
199         ctx->inode_bb_map = 0;
200         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
201         ctx->inode_imagic_map = 0;
202 errout:
203         if (buf)
204                 ext2fs_free_mem(&buf);
205
206         ext2fs_free_mem(&inode);
207         print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io);
208 }
209