]>
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" |
1164bde5 DC |
8 | #include "threads.h" |
9 | #include "prefetch.h" | |
2bd0ea18 NS |
10 | #include "avl.h" |
11 | #include "globals.h" | |
12 | #include "agheader.h" | |
13 | #include "incore.h" | |
14 | #include "protos.h" | |
15 | #include "err_protos.h" | |
16 | #include "dinode.h" | |
06fbdda9 | 17 | #include "progress.h" |
bd758142 | 18 | #include "bmap.h" |
8100dd79 | 19 | #include "threads.h" |
2bd0ea18 | 20 | |
62b00e63 CH |
21 | static void |
22 | process_agi_unlinked( | |
23 | struct xfs_mount *mp, | |
24 | xfs_agnumber_t agno) | |
2bd0ea18 | 25 | { |
62b00e63 CH |
26 | struct xfs_buf *bp; |
27 | struct xfs_agi *agip; | |
28 | xfs_agnumber_t i; | |
29 | int agi_dirty = 0; | |
2bd0ea18 | 30 | |
9440d84d NS |
31 | bp = libxfs_readbuf(mp->m_dev, |
32 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | |
75c8b434 | 33 | mp->m_sb.sb_sectsize/BBSIZE, 0, &xfs_agi_buf_ops); |
507f4e33 | 34 | if (!bp) |
5d1b7f0f | 35 | do_error(_("cannot read agi block %" PRId64 " for ag %u\n"), |
9440d84d | 36 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno); |
2bd0ea18 NS |
37 | |
38 | agip = XFS_BUF_TO_AGI(bp); | |
39 | ||
62b00e63 | 40 | ASSERT(be32_to_cpu(agip->agi_seqno) == agno); |
2bd0ea18 NS |
41 | |
42 | for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { | |
62b00e63 CH |
43 | if (agip->agi_unlinked[i] != cpu_to_be32(NULLAGINO)) { |
44 | agip->agi_unlinked[i] = cpu_to_be32(NULLAGINO); | |
45 | agi_dirty = 1; | |
2bd0ea18 NS |
46 | } |
47 | } | |
48 | ||
62b00e63 | 49 | if (agi_dirty) |
2bd0ea18 NS |
50 | libxfs_writebuf(bp, 0); |
51 | else | |
52 | libxfs_putbuf(bp); | |
53 | } | |
54 | ||
2556c98b BN |
55 | static void |
56 | process_ag_func( | |
62843f36 | 57 | struct workqueue *wq, |
2556c98b BN |
58 | xfs_agnumber_t agno, |
59 | void *arg) | |
3b6ac903 MV |
60 | { |
61 | /* | |
62 | * turn on directory processing (inode discovery) and | |
63 | * attribute processing (extra_attr_check) | |
64 | */ | |
2556c98b | 65 | wait_for_inode_prefetch(arg); |
3b6ac903 | 66 | do_log(_(" - agno = %d\n"), agno); |
62843f36 | 67 | process_aginodes(wq->wq_ctx, arg, agno, 1, 0, 1); |
bd758142 | 68 | blkmap_free_final(); |
2556c98b BN |
69 | cleanup_inode_prefetch(arg); |
70 | } | |
71 | ||
72 | static void | |
73 | process_ags( | |
74 | xfs_mount_t *mp) | |
75 | { | |
1164bde5 | 76 | do_inode_prefetch(mp, ag_stride, process_ag_func, false, false); |
3b6ac903 MV |
77 | } |
78 | ||
8100dd79 DC |
79 | static void |
80 | do_uncertain_aginodes( | |
62843f36 DW |
81 | struct workqueue *wq, |
82 | xfs_agnumber_t agno, | |
83 | void *arg) | |
8100dd79 | 84 | { |
62843f36 | 85 | int *count = arg; |
8100dd79 | 86 | |
62843f36 | 87 | *count = process_uncertain_aginodes(wq->wq_ctx, agno); |
8100dd79 DC |
88 | |
89 | #ifdef XR_INODE_TRACE | |
90 | fprintf(stderr, | |
91 | "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n", | |
92 | *count, j); | |
93 | #endif | |
94 | ||
95 | PROG_RPT_INC(prog_rpt_done[agno], 1); | |
96 | } | |
97 | ||
2bd0ea18 | 98 | void |
8100dd79 DC |
99 | phase3( |
100 | struct xfs_mount *mp, | |
101 | int scan_threads) | |
2bd0ea18 | 102 | { |
8100dd79 DC |
103 | int i, j; |
104 | int *counts; | |
62843f36 | 105 | struct workqueue wq; |
2bd0ea18 | 106 | |
507f4e33 | 107 | do_log(_("Phase 3 - for each AG...\n")); |
2bd0ea18 | 108 | if (!no_modify) |
507f4e33 | 109 | do_log(_(" - scan and clear agi unlinked lists...\n")); |
2bd0ea18 | 110 | else |
507f4e33 | 111 | do_log(_(" - scan (but don't clear) agi unlinked lists...\n")); |
2bd0ea18 | 112 | |
14f8b681 | 113 | set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount); |
06fbdda9 | 114 | |
62b00e63 CH |
115 | /* first clear the agi unlinked AGI list */ |
116 | if (!no_modify) { | |
117 | for (i = 0; i < mp->m_sb.sb_agcount; i++) | |
118 | process_agi_unlinked(mp, i); | |
119 | } | |
120 | ||
121 | /* now look at possibly bogus inodes */ | |
2bd0ea18 | 122 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { |
2bd0ea18 | 123 | check_uncertain_aginodes(mp, i); |
06fbdda9 | 124 | PROG_RPT_INC(prog_rpt_done[i], 1); |
2bd0ea18 | 125 | } |
06fbdda9 | 126 | print_final_rpt(); |
2bd0ea18 NS |
127 | |
128 | /* ok, now that the tree's ok, let's take a good look */ | |
129 | ||
507f4e33 NS |
130 | do_log(_( |
131 | " - process known inodes and perform inode discovery...\n")); | |
2bd0ea18 | 132 | |
14f8b681 | 133 | set_progress_msg(PROG_FMT_PROCESS_INO, (uint64_t) mp->m_sb.sb_icount); |
2556c98b BN |
134 | |
135 | process_ags(mp); | |
136 | ||
06fbdda9 | 137 | print_final_rpt(); |
2bd0ea18 NS |
138 | |
139 | /* | |
140 | * process newly discovered inode chunks | |
141 | */ | |
507f4e33 | 142 | do_log(_(" - process newly discovered inodes...\n")); |
14f8b681 | 143 | set_progress_msg(PROG_FMT_NEW_INODES, (uint64_t) glob_agcount); |
8100dd79 DC |
144 | |
145 | counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount); | |
146 | if (!counts) { | |
147 | do_abort(_("no memory for uncertain inode counts\n")); | |
148 | return; | |
149 | } | |
150 | ||
2bd0ea18 NS |
151 | do { |
152 | /* | |
153 | * have to loop until no ag has any uncertain | |
154 | * inodes | |
155 | */ | |
156 | j = 0; | |
8100dd79 DC |
157 | memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts)); |
158 | ||
159 | create_work_queue(&wq, mp, scan_threads); | |
160 | ||
161 | for (i = 0; i < mp->m_sb.sb_agcount; i++) | |
162 | queue_work(&wq, do_uncertain_aginodes, i, &counts[i]); | |
163 | ||
164 | destroy_work_queue(&wq); | |
165 | ||
166 | /* tally up the counts */ | |
167 | for (i = 0; i < mp->m_sb.sb_agcount; i++) | |
168 | j += counts[i]; | |
169 | ||
2bd0ea18 | 170 | } while (j != 0); |
8100dd79 DC |
171 | |
172 | free(counts); | |
173 | ||
06fbdda9 | 174 | print_final_rpt(); |
2bd0ea18 | 175 | } |