]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase7.c
xfs_repair: validate some of the log space information
[thirdparty/xfsprogs-dev.git] / repair / phase7.c
1 /*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
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
7 * published by the Free Software Foundation.
8 *
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.
13 *
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
17 */
18
19 #include "libxfs.h"
20 #include "avl.h"
21 #include "globals.h"
22 #include "agheader.h"
23 #include "incore.h"
24 #include "protos.h"
25 #include "err_protos.h"
26 #include "dinode.h"
27 #include "versions.h"
28 #include "progress.h"
29 #include "threads.h"
30
31 static void
32 update_inode_nlinks(
33 xfs_mount_t *mp,
34 xfs_ino_t ino,
35 uint32_t nlinks)
36 {
37 xfs_trans_t *tp;
38 xfs_inode_t *ip;
39 int error;
40 int dirty;
41 int nres;
42
43 nres = no_modify ? 0 : 10;
44 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
45 ASSERT(error == 0);
46
47 error = -libxfs_trans_iget(mp, tp, ino, 0, 0, &ip);
48
49 if (error) {
50 if (!no_modify)
51 do_error(
52 _("couldn't map inode %" PRIu64 ", err = %d\n"),
53 ino, error);
54 else {
55 do_warn(
56 _("couldn't map inode %" PRIu64 ", err = %d, can't compare link counts\n"),
57 ino, error);
58 return;
59 }
60 }
61
62 dirty = 0;
63
64 /* compare and set links if they differ. */
65 if (VFS_I(ip)->i_nlink != nlinks) {
66 if (!no_modify) {
67 do_warn(
68 _("resetting inode %" PRIu64 " nlinks from %u to %u\n"),
69 ino, VFS_I(ip)->i_nlink, nlinks);
70 set_nlink(VFS_I(ip), nlinks);
71 dirty = 1;
72 } else {
73 do_warn(
74 _("would have reset inode %" PRIu64 " nlinks from %u to %u\n"),
75 ino, VFS_I(ip)->i_nlink, nlinks);
76 }
77 }
78
79 if (!dirty) {
80 libxfs_trans_cancel(tp);
81 } else {
82 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
83 /*
84 * no need to do a bmap finish since
85 * we're not allocating anything
86 */
87 ASSERT(error == 0);
88 error = -libxfs_trans_commit(tp);
89
90 ASSERT(error == 0);
91 }
92 IRELE(ip);
93 }
94
95 /*
96 * for each ag, look at each inode 1 at a time. If the number of
97 * links is bad, reset it, log the inode core, commit the transaction
98 */
99 static void
100 do_link_updates(
101 struct workqueue *wq,
102 xfs_agnumber_t agno,
103 void *arg)
104 {
105 struct xfs_mount *mp = wq->wq_ctx;
106 ino_tree_node_t *irec;
107 int j;
108 uint32_t nrefs;
109
110 for (irec = findfirst_inode_rec(agno); irec;
111 irec = next_ino_rec(irec)) {
112 for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
113 ASSERT(is_inode_confirmed(irec, j));
114
115 if (is_inode_free(irec, j))
116 continue;
117
118 ASSERT(no_modify || is_inode_reached(irec, j));
119
120 nrefs = num_inode_references(irec, j);
121 ASSERT(no_modify || nrefs > 0);
122
123 if (get_inode_disk_nlinks(irec, j) != nrefs)
124 update_inode_nlinks(wq->wq_ctx,
125 XFS_AGINO_TO_INO(mp, agno,
126 irec->ino_startnum + j),
127 nrefs);
128 }
129 }
130
131 PROG_RPT_INC(prog_rpt_done[agno], 1);
132 }
133
134 void
135 phase7(
136 struct xfs_mount *mp,
137 int scan_threads)
138 {
139 struct workqueue wq;
140 int agno;
141
142 if (!no_modify)
143 do_log(_("Phase 7 - verify and correct link counts...\n"));
144 else
145 do_log(_("Phase 7 - verify link counts...\n"));
146
147 set_progress_msg(PROGRESS_FMT_CORR_LINK, (uint64_t) glob_agcount);
148
149 create_work_queue(&wq, mp, scan_threads);
150
151 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
152 queue_work(&wq, do_link_updates, agno, NULL);
153
154 destroy_work_queue(&wq);
155
156 print_final_rpt();
157 }