]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase7.c
Undoes mod: xfs-cmds:slinx:120772a
[thirdparty/xfsprogs-dev.git] / repair / phase7.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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
33 #include <libxfs.h>
34 #include "avl.h"
35 #include "globals.h"
36 #include "agheader.h"
37 #include "incore.h"
38 #include "protos.h"
39 #include "err_protos.h"
40 #include "dinode.h"
41 #include "versions.h"
42
43 /* dinoc is a pointer to the IN-CORE dinode core */
44 void
45 set_nlinks(xfs_dinode_core_t *dinoc,
46 xfs_ino_t ino,
47 __uint32_t nrefs,
48 int *dirty)
49 {
50 if (!no_modify) {
51 if (INT_GET(dinoc->di_nlink, ARCH_NOCONVERT) != nrefs) {
52 *dirty = 1;
53 do_warn("resetting inode %llu nlinks from %d to %d\n",
54 ino, INT_GET(dinoc->di_nlink, ARCH_NOCONVERT), nrefs);
55
56 if (nrefs > XFS_MAXLINK_1) {
57 ASSERT(fs_inode_nlink);
58 do_warn(
59 "nlinks %d will overflow v1 ino, ino %llu will be converted to version 2\n",
60 nrefs, ino);
61
62 }
63 INT_SET(dinoc->di_nlink, ARCH_NOCONVERT, nrefs);
64 }
65 } else {
66 if (INT_GET(dinoc->di_nlink, ARCH_NOCONVERT) != nrefs)
67 do_warn(
68 "would have reset inode %llu nlinks from %d to %d\n",
69 ino, INT_GET(dinoc->di_nlink, ARCH_NOCONVERT), nrefs);
70 }
71 }
72
73 void
74 phase7(xfs_mount_t *mp)
75 {
76 ino_tree_node_t *irec;
77 xfs_inode_t *ip;
78 xfs_trans_t *tp;
79 int i;
80 int j;
81 int error;
82 int dirty;
83 xfs_ino_t ino;
84 __uint32_t nrefs;
85
86 if (!no_modify)
87 printf("Phase 7 - verify and correct link counts...\n");
88 else
89 printf("Phase 7 - verify link counts...\n");
90
91 tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
92
93 error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10),
94 XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES,
95 XFS_REMOVE_LOG_COUNT);
96
97 ASSERT(error == 0);
98
99 /*
100 * for each ag, look at each inode 1 at a time using the
101 * sim code. if the number of links is bad, reset it,
102 * log the inode core, commit the transaction, and
103 * allocate a new transaction
104 */
105 for (i = 0; i < glob_agcount; i++) {
106 irec = findfirst_inode_rec(i);
107
108 while (irec != NULL) {
109 for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
110 ASSERT(is_inode_confirmed(irec, j));
111
112 if (is_inode_free(irec, j))
113 continue;
114
115 ASSERT(no_modify || is_inode_reached(irec, j));
116 ASSERT(no_modify ||
117 is_inode_referenced(irec, j));
118
119 nrefs = num_inode_references(irec, j);
120
121 ino = XFS_AGINO_TO_INO(mp, i,
122 irec->ino_startnum + j);
123
124 error = libxfs_trans_iget(mp, tp, ino, 0, &ip);
125
126 if (error) {
127 if (!no_modify)
128 do_error(
129 "couldn't map inode %llu, err = %d\n",
130 ino, error);
131 else {
132 do_warn(
133 "couldn't map inode %llu, err = %d, can't compare link counts\n",
134 ino, error);
135 continue;
136 }
137 }
138
139 dirty = 0;
140
141 /*
142 * compare and set links for all inodes
143 * but the lost+found inode. we keep
144 * that correct as we go.
145 */
146 if (ino != orphanage_ino)
147 set_nlinks(&ip->i_d, ino, nrefs,
148 &dirty);
149
150 if (!dirty) {
151 libxfs_trans_iput(tp, ip, 0);
152 } else {
153 libxfs_trans_log_inode(tp, ip,
154 XFS_ILOG_CORE);
155 /*
156 * no need to do a bmap finish since
157 * we're not allocating anything
158 */
159 ASSERT(error == 0);
160 error = libxfs_trans_commit(tp,
161 XFS_TRANS_RELEASE_LOG_RES|
162 XFS_TRANS_SYNC, NULL);
163
164 ASSERT(error == 0);
165
166 tp = libxfs_trans_alloc(mp,
167 XFS_TRANS_REMOVE);
168
169 error = libxfs_trans_reserve(tp,
170 (no_modify ? 0 : 10),
171 XFS_REMOVE_LOG_RES(mp),
172 0, XFS_TRANS_PERM_LOG_RES,
173 XFS_REMOVE_LOG_COUNT);
174 ASSERT(error == 0);
175 }
176 }
177 irec = next_ino_rec(irec);
178 }
179 }
180
181 /*
182 * always have one unfinished transaction coming out
183 * of the loop. cancel it.
184 */
185 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
186 }