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