]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase7.c
libxfs: remove the flags argument to xfs_trans_cancel
[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 "xfs/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
30 /* dinoc is a pointer to the IN-CORE dinode core */
31 static void
32 set_nlinks(
33 xfs_icdinode_t *dinoc,
34 xfs_ino_t ino,
35 __uint32_t nrefs,
36 int *dirty)
37 {
38 if (dinoc->di_nlink == nrefs)
39 return;
40
41 if (!no_modify) {
42 *dirty = 1;
43 do_warn(_("resetting inode %" PRIu64 " nlinks from %u to %u\n"),
44 ino, dinoc->di_nlink, nrefs);
45
46 ASSERT(dinoc->di_version > 1);
47 dinoc->di_nlink = nrefs;
48 } else {
49 do_warn(
50 _("would have reset inode %" PRIu64 " nlinks from %u to %u\n"),
51 ino, dinoc->di_nlink, nrefs);
52 }
53 }
54
55 static void
56 update_inode_nlinks(
57 xfs_mount_t *mp,
58 xfs_ino_t ino,
59 __uint32_t nlinks)
60 {
61 xfs_trans_t *tp;
62 xfs_inode_t *ip;
63 int error;
64 int dirty;
65 int nres;
66
67 tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
68
69 nres = no_modify ? 0 : 10;
70 error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, nres, 0);
71 ASSERT(error == 0);
72
73 error = -libxfs_trans_iget(mp, tp, ino, 0, 0, &ip);
74
75 if (error) {
76 if (!no_modify)
77 do_error(
78 _("couldn't map inode %" PRIu64 ", err = %d\n"),
79 ino, error);
80 else {
81 do_warn(
82 _("couldn't map inode %" PRIu64 ", err = %d, can't compare link counts\n"),
83 ino, error);
84 return;
85 }
86 }
87
88 dirty = 0;
89
90 /*
91 * compare and set links for all inodes
92 */
93 set_nlinks(&ip->i_d, ino, nlinks, &dirty);
94
95 if (!dirty) {
96 libxfs_trans_cancel(tp);
97 } else {
98 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
99 /*
100 * no need to do a bmap finish since
101 * we're not allocating anything
102 */
103 ASSERT(error == 0);
104 error = -libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES |
105 XFS_TRANS_SYNC);
106
107 ASSERT(error == 0);
108 }
109 IRELE(ip);
110 }
111
112 void
113 phase7(xfs_mount_t *mp)
114 {
115 ino_tree_node_t *irec;
116 int i;
117 int j;
118 __uint32_t nrefs;
119
120 if (!no_modify)
121 do_log(_("Phase 7 - verify and correct link counts...\n"));
122 else
123 do_log(_("Phase 7 - verify link counts...\n"));
124
125 /*
126 * for each ag, look at each inode 1 at a time. If the number of
127 * links is bad, reset it, log the inode core, commit the transaction
128 */
129 for (i = 0; i < glob_agcount; i++) {
130 irec = findfirst_inode_rec(i);
131
132 while (irec != NULL) {
133 for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
134 ASSERT(is_inode_confirmed(irec, j));
135
136 if (is_inode_free(irec, j))
137 continue;
138
139 ASSERT(no_modify || is_inode_reached(irec, j));
140
141 nrefs = num_inode_references(irec, j);
142 ASSERT(no_modify || nrefs > 0);
143
144 if (get_inode_disk_nlinks(irec, j) != nrefs)
145 update_inode_nlinks(mp,
146 XFS_AGINO_TO_INO(mp, i,
147 irec->ino_startnum + j),
148 nrefs);
149 }
150 irec = next_ino_rec(irec);
151 }
152 }
153 }