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