]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
0d3e0b37 | 2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. |
dfc130f3 | 3 | * |
2bd0ea18 NS |
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. | |
dfc130f3 | 7 | * |
2bd0ea18 NS |
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. | |
dfc130f3 | 11 | * |
2bd0ea18 NS |
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. | |
dfc130f3 | 18 | * |
2bd0ea18 NS |
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. | |
dfc130f3 | 22 | * |
2bd0ea18 NS |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, |
24 | * Mountain View, CA 94043, or: | |
dfc130f3 RC |
25 | * |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
2bd0ea18 NS |
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; | |
507f4e33 NS |
53 | do_warn( |
54 | _("resetting inode %llu nlinks from %d to %d\n"), | |
55 | ino, INT_GET(dinoc->di_nlink, ARCH_NOCONVERT), | |
56 | nrefs); | |
2bd0ea18 NS |
57 | |
58 | if (nrefs > XFS_MAXLINK_1) { | |
59 | ASSERT(fs_inode_nlink); | |
60 | do_warn( | |
507f4e33 | 61 | _("nlinks %d will overflow v1 ino, ino %llu will be converted to version 2\n"), |
2bd0ea18 NS |
62 | nrefs, ino); |
63 | ||
64 | } | |
65 | INT_SET(dinoc->di_nlink, ARCH_NOCONVERT, nrefs); | |
66 | } | |
67 | } else { | |
68 | if (INT_GET(dinoc->di_nlink, ARCH_NOCONVERT) != nrefs) | |
69 | do_warn( | |
507f4e33 NS |
70 | _("would have reset inode %llu nlinks from %d to %d\n"), |
71 | ino, INT_GET(dinoc->di_nlink, ARCH_NOCONVERT), | |
72 | nrefs); | |
2bd0ea18 NS |
73 | } |
74 | } | |
75 | ||
76 | void | |
77 | phase7(xfs_mount_t *mp) | |
78 | { | |
79 | ino_tree_node_t *irec; | |
80 | xfs_inode_t *ip; | |
81 | xfs_trans_t *tp; | |
82 | int i; | |
83 | int j; | |
84 | int error; | |
85 | int dirty; | |
86 | xfs_ino_t ino; | |
87 | __uint32_t nrefs; | |
88 | ||
89 | if (!no_modify) | |
507f4e33 | 90 | do_log(_("Phase 7 - verify and correct link counts...\n")); |
2bd0ea18 | 91 | else |
507f4e33 | 92 | do_log(_("Phase 7 - verify link counts...\n")); |
2bd0ea18 NS |
93 | |
94 | tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE); | |
95 | ||
96 | error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10), | |
507f4e33 NS |
97 | XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, |
98 | XFS_REMOVE_LOG_COUNT); | |
2bd0ea18 NS |
99 | |
100 | ASSERT(error == 0); | |
101 | ||
102 | /* | |
103 | * for each ag, look at each inode 1 at a time using the | |
104 | * sim code. if the number of links is bad, reset it, | |
105 | * log the inode core, commit the transaction, and | |
106 | * allocate a new transaction | |
107 | */ | |
108 | for (i = 0; i < glob_agcount; i++) { | |
109 | irec = findfirst_inode_rec(i); | |
110 | ||
111 | while (irec != NULL) { | |
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 | ASSERT(no_modify || | |
120 | is_inode_referenced(irec, j)); | |
121 | ||
122 | nrefs = num_inode_references(irec, j); | |
123 | ||
124 | ino = XFS_AGINO_TO_INO(mp, i, | |
125 | irec->ino_startnum + j); | |
126 | ||
127 | error = libxfs_trans_iget(mp, tp, ino, 0, &ip); | |
128 | ||
129 | if (error) { | |
130 | if (!no_modify) | |
131 | do_error( | |
507f4e33 | 132 | _("couldn't map inode %llu, err = %d\n"), |
2bd0ea18 NS |
133 | ino, error); |
134 | else { | |
135 | do_warn( | |
507f4e33 | 136 | _("couldn't map inode %llu, err = %d, can't compare link counts\n"), |
2bd0ea18 NS |
137 | ino, error); |
138 | continue; | |
139 | } | |
140 | } | |
141 | ||
142 | dirty = 0; | |
143 | ||
144 | /* | |
145 | * compare and set links for all inodes | |
146 | * but the lost+found inode. we keep | |
147 | * that correct as we go. | |
148 | */ | |
149 | if (ino != orphanage_ino) | |
150 | set_nlinks(&ip->i_d, ino, nrefs, | |
151 | &dirty); | |
dfc130f3 | 152 | |
2bd0ea18 NS |
153 | if (!dirty) { |
154 | libxfs_trans_iput(tp, ip, 0); | |
155 | } else { | |
156 | libxfs_trans_log_inode(tp, ip, | |
157 | XFS_ILOG_CORE); | |
158 | /* | |
159 | * no need to do a bmap finish since | |
160 | * we're not allocating anything | |
161 | */ | |
162 | ASSERT(error == 0); | |
163 | error = libxfs_trans_commit(tp, | |
164 | XFS_TRANS_RELEASE_LOG_RES| | |
165 | XFS_TRANS_SYNC, NULL); | |
166 | ||
167 | ASSERT(error == 0); | |
168 | ||
169 | tp = libxfs_trans_alloc(mp, | |
170 | XFS_TRANS_REMOVE); | |
171 | ||
172 | error = libxfs_trans_reserve(tp, | |
173 | (no_modify ? 0 : 10), | |
174 | XFS_REMOVE_LOG_RES(mp), | |
175 | 0, XFS_TRANS_PERM_LOG_RES, | |
176 | XFS_REMOVE_LOG_COUNT); | |
177 | ASSERT(error == 0); | |
178 | } | |
179 | } | |
180 | irec = next_ino_rec(irec); | |
181 | } | |
182 | } | |
183 | ||
dfc130f3 | 184 | /* |
2bd0ea18 NS |
185 | * always have one unfinished transaction coming out |
186 | * of the loop. cancel it. | |
187 | */ | |
188 | libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); | |
189 | } |