]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
0d3e0b37 | 2 | * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. |
2bd0ea18 NS |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of version 2 of the GNU General Public License as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it would be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | * | |
12 | * Further, this software is distributed without any warranty that it is | |
13 | * free of the rightful claim of any third person regarding infringement | |
14 | * or the like. Any license provided herein, whether implied or | |
15 | * otherwise, applies only to this software file. Patent licenses, if | |
16 | * any, provided herein do not apply to combinations of this program with | |
17 | * other software, or any other product whatsoever. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | |
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
22 | * | |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | |
24 | * Mountain View, CA 94043, or: | |
25 | * | |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | |
31 | */ | |
32 | ||
d321ceac | 33 | #include <libxlog.h> |
2bd0ea18 NS |
34 | #include "avl.h" |
35 | #include "globals.h" | |
36 | #include "agheader.h" | |
37 | #include "protos.h" | |
38 | #include "err_protos.h" | |
39 | #include "incore.h" | |
40 | ||
41 | void set_mp(xfs_mount_t *mpp); | |
42 | void scan_ag(xfs_agnumber_t agno); | |
43 | ||
d321ceac NS |
44 | /* workaround craziness in the xlog routines */ |
45 | int xlog_recover_do_trans(xlog_t *log, xlog_recover_t *t, int p) { return 0; } | |
46 | ||
2bd0ea18 | 47 | static void |
d321ceac | 48 | zero_log(xfs_mount_t *mp) |
2bd0ea18 | 49 | { |
d321ceac NS |
50 | int error; |
51 | xlog_t log; | |
52 | xfs_daddr_t head_blk, tail_blk; | |
53 | dev_t logdev = (mp->m_sb.sb_logstart == 0) ? x.logdev : x.ddev; | |
54 | ||
55 | memset(&log, 0, sizeof(log)); | |
56 | if (!x.logdev) | |
57 | x.logdev = x.ddev; | |
58 | x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); | |
59 | x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); | |
60 | ||
61 | log.l_dev = logdev; | |
62 | log.l_logsize = BBTOB(x.logBBsize); | |
63 | log.l_logBBsize = x.logBBsize; | |
64 | log.l_logBBstart = x.logBBstart; | |
65 | log.l_mp = mp; | |
66 | ||
67 | if ((error = xlog_find_tail(&log, &head_blk, &tail_blk, 0))) { | |
94bc4126 NS |
68 | do_warn("zero_log: cannot find log head/tail " |
69 | "(xlog_find_tail=%d), zeroing it anyway\n", | |
70 | error); | |
d321ceac NS |
71 | } else { |
72 | if (verbose) { | |
73 | do_warn("zero_log: head block %lld tail block %lld\n", | |
74 | head_blk, tail_blk); | |
75 | } | |
76 | if (head_blk != tail_blk) { | |
77 | if (zap_log) { | |
78 | do_warn( | |
79 | "ALERT: The filesystem has valuable metadata changes in a log which is being\n" | |
80 | "destroyed because the -L option was used.\n"); | |
81 | } else { | |
82 | do_warn( | |
83 | "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" | |
84 | "be replayed. Mount the filesystem to replay the log, and unmount it before\n" | |
85 | "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" | |
86 | "the -L option to destroy the log and attempt a repair.\n" | |
87 | "Note that destroying the log may cause corruption -- please attempt a mount\n" | |
88 | "of the filesystem before doing this.\n"); | |
89 | exit(2); | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
2bd0ea18 NS |
94 | libxfs_log_clear(logdev, |
95 | XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), | |
96 | (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks), | |
d321ceac NS |
97 | &mp->m_sb.sb_uuid, |
98 | XLOG_FMT); | |
2bd0ea18 NS |
99 | } |
100 | ||
101 | /* | |
102 | * ok, at this point, the fs is mounted but the root inode may be | |
103 | * trashed and the ag headers haven't been checked. So we have | |
104 | * a valid xfs_mount_t and superblock but that's about it. That | |
105 | * means we can use macros that use mount/sb fields in calculations | |
106 | * but I/O or btree routines that depend on space maps or inode maps | |
107 | * being correct are verboten. | |
108 | */ | |
109 | ||
110 | void | |
d321ceac | 111 | phase2(xfs_mount_t *mp) |
2bd0ea18 NS |
112 | { |
113 | xfs_agnumber_t i; | |
114 | xfs_agblock_t b; | |
115 | int j; | |
116 | ino_tree_node_t *ino_rec; | |
117 | ||
118 | /* now we can start using the buffer cache routines */ | |
119 | set_mp(mp); | |
120 | ||
121 | /* Check whether this fs has internal or external log */ | |
122 | if (mp->m_sb.sb_logstart == 0) { | |
d321ceac | 123 | if (!x.logname) { |
2bd0ea18 NS |
124 | fprintf (stderr, |
125 | "This filesystem has an external log. " | |
126 | "Specify log device with the -l option.\n"); | |
127 | exit (1); | |
128 | } | |
129 | ||
130 | fprintf (stderr, "Phase 2 - using external log on %s\n", | |
d321ceac | 131 | x.logname); |
2bd0ea18 NS |
132 | } else |
133 | fprintf (stderr, "Phase 2 - using internal log\n"); | |
134 | ||
135 | /* Zero log if applicable */ | |
136 | if (!no_modify) { | |
137 | do_log(" - zero log...\n"); | |
d321ceac | 138 | zero_log(mp); |
2bd0ea18 NS |
139 | } |
140 | ||
141 | do_log(" - scan filesystem freespace and inode maps...\n"); | |
142 | ||
143 | /* | |
144 | * account for space used by ag headers and log if internal | |
145 | */ | |
146 | set_bmap_log(mp); | |
147 | set_bmap_fs(mp); | |
148 | ||
149 | bad_ino_btree = 0; | |
150 | ||
151 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { | |
152 | scan_ag(i); | |
153 | #ifdef XR_INODE_TRACE | |
154 | print_inode_list(i); | |
155 | #endif | |
156 | } | |
157 | ||
158 | /* | |
159 | * make sure we know about the root inode chunk | |
160 | */ | |
161 | if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL) { | |
162 | ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && | |
163 | mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); | |
164 | do_warn("root inode chunk not found\n"); | |
165 | ||
166 | /* | |
167 | * mark the first 3 used, the rest are free | |
168 | */ | |
169 | ino_rec = set_inode_used_alloc(0, | |
170 | (xfs_agino_t) mp->m_sb.sb_rootino); | |
171 | set_inode_used(ino_rec, 1); | |
172 | set_inode_used(ino_rec, 2); | |
173 | ||
174 | for (j = 3; j < XFS_INODES_PER_CHUNK; j++) | |
175 | set_inode_free(ino_rec, j); | |
176 | ||
177 | /* | |
178 | * also mark blocks | |
179 | */ | |
180 | for (b = 0; b < mp->m_ialloc_blks; b++) { | |
181 | set_agbno_state(mp, 0, | |
182 | b + XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), | |
183 | XR_E_INO); | |
184 | } | |
185 | } else { | |
186 | do_log(" - found root inode chunk\n"); | |
187 | ||
188 | /* | |
189 | * blocks are marked, just make sure they're in use | |
190 | */ | |
191 | if (is_inode_free(ino_rec, 0)) { | |
192 | do_warn("root inode marked free, "); | |
193 | set_inode_used(ino_rec, 0); | |
194 | if (!no_modify) | |
195 | do_warn("correcting\n"); | |
196 | else | |
197 | do_warn("would correct\n"); | |
198 | } | |
199 | ||
200 | if (is_inode_free(ino_rec, 1)) { | |
201 | do_warn("realtime bitmap inode marked free, "); | |
202 | set_inode_used(ino_rec, 1); | |
203 | if (!no_modify) | |
204 | do_warn("correcting\n"); | |
205 | else | |
206 | do_warn("would correct\n"); | |
207 | } | |
208 | ||
209 | if (is_inode_free(ino_rec, 2)) { | |
210 | do_warn("realtime summary inode marked free, "); | |
211 | set_inode_used(ino_rec, 2); | |
212 | if (!no_modify) | |
213 | do_warn("correcting\n"); | |
214 | else | |
215 | do_warn("would correct\n"); | |
216 | } | |
217 | } | |
218 | } |