]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2bd0ea18 | 2 | /* |
da23017d NS |
3 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
2bd0ea18 NS |
5 | */ |
6 | ||
6b803e5a | 7 | #include "libxfs.h" |
2bd0ea18 NS |
8 | #include "avl.h" |
9 | #include "globals.h" | |
10 | #include "agheader.h" | |
11 | #include "incore.h" | |
12 | #include "protos.h" | |
13 | #include "err_protos.h" | |
14 | #include "dinode.h" | |
15 | #include "versions.h" | |
06fbdda9 | 16 | #include "progress.h" |
e161d4a8 | 17 | #include "threads.h" |
2bd0ea18 | 18 | |
0f012a4c BN |
19 | static void |
20 | update_inode_nlinks( | |
21 | xfs_mount_t *mp, | |
22 | xfs_ino_t ino, | |
14f8b681 | 23 | uint32_t nlinks) |
0f012a4c BN |
24 | { |
25 | xfs_trans_t *tp; | |
26 | xfs_inode_t *ip; | |
27 | int error; | |
28 | int dirty; | |
48ea6cb9 | 29 | int nres; |
0f012a4c | 30 | |
48ea6cb9 | 31 | nres = no_modify ? 0 : 10; |
9074815c | 32 | error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); |
0f012a4c BN |
33 | ASSERT(error == 0); |
34 | ||
e2dd0e1c | 35 | error = -libxfs_iget(mp, tp, ino, 0, &ip, &xfs_default_ifork_ops); |
0f012a4c BN |
36 | if (error) { |
37 | if (!no_modify) | |
5d1b7f0f CH |
38 | do_error( |
39 | _("couldn't map inode %" PRIu64 ", err = %d\n"), | |
0f012a4c BN |
40 | ino, error); |
41 | else { | |
2bd0ea18 | 42 | do_warn( |
5d1b7f0f | 43 | _("couldn't map inode %" PRIu64 ", err = %d, can't compare link counts\n"), |
0f012a4c BN |
44 | ino, error); |
45 | return; | |
46 | } | |
47 | } | |
48 | ||
49 | dirty = 0; | |
50 | ||
bcbe04c1 DC |
51 | /* compare and set links if they differ. */ |
52 | if (VFS_I(ip)->i_nlink != nlinks) { | |
53 | if (!no_modify) { | |
54 | do_warn( | |
55 | _("resetting inode %" PRIu64 " nlinks from %u to %u\n"), | |
56 | ino, VFS_I(ip)->i_nlink, nlinks); | |
57 | set_nlink(VFS_I(ip), nlinks); | |
58 | dirty = 1; | |
59 | } else { | |
60 | do_warn( | |
61 | _("would have reset inode %" PRIu64 " nlinks from %u to %u\n"), | |
62 | ino, VFS_I(ip)->i_nlink, nlinks); | |
63 | } | |
64 | } | |
0f012a4c BN |
65 | |
66 | if (!dirty) { | |
3d7434fe | 67 | libxfs_trans_cancel(tp); |
0f012a4c | 68 | } else { |
e2dd0e1c | 69 | libxfs_trans_ijoin(tp, ip, 0); |
0f012a4c BN |
70 | libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
71 | /* | |
72 | * no need to do a bmap finish since | |
73 | * we're not allocating anything | |
74 | */ | |
75 | ASSERT(error == 0); | |
de5a3f46 | 76 | error = -libxfs_trans_commit(tp); |
0f012a4c BN |
77 | |
78 | ASSERT(error == 0); | |
2bd0ea18 | 79 | } |
31845e4c | 80 | libxfs_irele(ip); |
2bd0ea18 NS |
81 | } |
82 | ||
e161d4a8 DC |
83 | /* |
84 | * for each ag, look at each inode 1 at a time. If the number of | |
85 | * links is bad, reset it, log the inode core, commit the transaction | |
86 | */ | |
87 | static void | |
88 | do_link_updates( | |
62843f36 | 89 | struct workqueue *wq, |
e161d4a8 DC |
90 | xfs_agnumber_t agno, |
91 | void *arg) | |
2bd0ea18 | 92 | { |
62843f36 | 93 | struct xfs_mount *mp = wq->wq_ctx; |
2bd0ea18 | 94 | ino_tree_node_t *irec; |
2bd0ea18 | 95 | int j; |
14f8b681 | 96 | uint32_t nrefs; |
2bd0ea18 | 97 | |
e161d4a8 DC |
98 | for (irec = findfirst_inode_rec(agno); irec; |
99 | irec = next_ino_rec(irec)) { | |
100 | for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { | |
101 | ASSERT(is_inode_confirmed(irec, j)); | |
102 | ||
103 | if (is_inode_free(irec, j)) | |
104 | continue; | |
105 | ||
106 | ASSERT(no_modify || is_inode_reached(irec, j)); | |
107 | ||
108 | nrefs = num_inode_references(irec, j); | |
109 | ASSERT(no_modify || nrefs > 0); | |
110 | ||
111 | if (get_inode_disk_nlinks(irec, j) != nrefs) | |
62843f36 DW |
112 | update_inode_nlinks(wq->wq_ctx, |
113 | XFS_AGINO_TO_INO(mp, agno, | |
e161d4a8 DC |
114 | irec->ino_startnum + j), |
115 | nrefs); | |
116 | } | |
117 | } | |
118 | ||
119 | PROG_RPT_INC(prog_rpt_done[agno], 1); | |
120 | } | |
121 | ||
122 | void | |
123 | phase7( | |
124 | struct xfs_mount *mp, | |
125 | int scan_threads) | |
126 | { | |
62843f36 | 127 | struct workqueue wq; |
e161d4a8 DC |
128 | int agno; |
129 | ||
2bd0ea18 | 130 | if (!no_modify) |
507f4e33 | 131 | do_log(_("Phase 7 - verify and correct link counts...\n")); |
2bd0ea18 | 132 | else |
507f4e33 | 133 | do_log(_("Phase 7 - verify link counts...\n")); |
2bd0ea18 | 134 | |
14f8b681 | 135 | set_progress_msg(PROGRESS_FMT_CORR_LINK, (uint64_t) glob_agcount); |
2bd0ea18 | 136 | |
e161d4a8 | 137 | create_work_queue(&wq, mp, scan_threads); |
2bd0ea18 | 138 | |
e161d4a8 DC |
139 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) |
140 | queue_work(&wq, do_link_updates, agno, NULL); | |
2bd0ea18 | 141 | |
e161d4a8 | 142 | destroy_work_queue(&wq); |
2bd0ea18 | 143 | |
e161d4a8 | 144 | print_final_rpt(); |
2bd0ea18 | 145 | } |