]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase4.c
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
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.
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.
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
27 #include "err_protos.h"
39 * null out quota inode fields in sb if they point to non-existent inodes.
40 * this isn't as redundant as it looks since it's possible that the sb field
41 * might be set but the imap and inode(s) agree that the inode is
42 * free in which case they'd never be cleared so the fields wouldn't
43 * be cleared by process_dinode().
46 quotino_check(xfs_mount_t
*mp
)
48 ino_tree_node_t
*irec
;
50 if (mp
->m_sb
.sb_uquotino
!= NULLFSINO
&& mp
->m_sb
.sb_uquotino
!= 0) {
51 if (verify_inum(mp
, mp
->m_sb
.sb_uquotino
))
54 irec
= find_inode_rec(mp
,
55 XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_uquotino
),
56 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
));
58 if (irec
== NULL
|| is_inode_free(irec
,
59 mp
->m_sb
.sb_uquotino
- irec
->ino_startnum
)) {
60 mp
->m_sb
.sb_uquotino
= NULLFSINO
;
66 if (mp
->m_sb
.sb_gquotino
!= NULLFSINO
&& mp
->m_sb
.sb_gquotino
!= 0) {
67 if (verify_inum(mp
, mp
->m_sb
.sb_gquotino
))
70 irec
= find_inode_rec(mp
,
71 XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_gquotino
),
72 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
));
74 if (irec
== NULL
|| is_inode_free(irec
,
75 mp
->m_sb
.sb_gquotino
- irec
->ino_startnum
)) {
76 mp
->m_sb
.sb_gquotino
= NULLFSINO
;
82 if (mp
->m_sb
.sb_pquotino
!= NULLFSINO
&& mp
->m_sb
.sb_pquotino
!= 0) {
83 if (verify_inum(mp
, mp
->m_sb
.sb_pquotino
))
86 irec
= find_inode_rec(mp
,
87 XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_pquotino
),
88 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_pquotino
));
90 if (irec
== NULL
|| is_inode_free(irec
,
91 mp
->m_sb
.sb_pquotino
- irec
->ino_startnum
)) {
92 mp
->m_sb
.sb_pquotino
= NULLFSINO
;
100 quota_sb_check(xfs_mount_t
*mp
)
103 * if the sb says we have quotas and we lost both,
104 * signal a superblock downgrade. that will cause
105 * the quota flags to get zeroed. (if we only lost
106 * one quota inode, do nothing and complain later.)
108 * if the sb says we have quotas but we didn't start out
109 * with any quota inodes, signal a superblock downgrade.
111 * The sb downgrades are so that older systems can mount
114 * if the sb says we don't have quotas but it looks like
115 * we do have quota inodes, then signal a superblock upgrade.
117 * if the sb says we don't have quotas and we have no
118 * quota inodes, then leave will enough alone.
122 (mp
->m_sb
.sb_uquotino
== NULLFSINO
|| mp
->m_sb
.sb_uquotino
== 0) &&
123 (mp
->m_sb
.sb_gquotino
== NULLFSINO
|| mp
->m_sb
.sb_gquotino
== 0) &&
124 (mp
->m_sb
.sb_pquotino
== NULLFSINO
|| mp
->m_sb
.sb_pquotino
== 0)) {
127 } else if (!verify_inum(mp
, mp
->m_sb
.sb_uquotino
) &&
128 !verify_inum(mp
, mp
->m_sb
.sb_gquotino
) &&
129 !verify_inum(mp
, mp
->m_sb
.sb_pquotino
)) {
141 wait_for_inode_prefetch(arg
);
142 do_log(_(" - agno = %d\n"), agno
);
143 process_aginodes(wq
->mp
, arg
, agno
, 0, 1, 0);
145 cleanup_inode_prefetch(arg
);
148 * now recycle the per-AG duplicate extent records
150 release_dup_extent_tree(agno
);
160 do_inode_prefetch(mp
, ag_stride
, process_ag_func
, true, false);
161 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
162 error
= rmap_finish_collecting_fork_recs(mp
, i
);
165 _("unable to finish adding attr/data fork reverse-mapping data for AG %u.\n"),
178 error
= rmap_add_fixed_ag_rec(wq
->mp
, agno
);
181 _("unable to add AG %u metadata reverse-mapping data.\n"), agno
);
183 error
= rmap_fold_raw_recs(wq
->mp
, agno
);
186 _("unable to merge AG %u metadata reverse-mapping data.\n"), agno
);
188 error
= rmaps_verify_btree(wq
->mp
, agno
);
191 _("%s while checking reverse-mappings"),
197 struct xfs_mount
*mp
)
199 struct work_queue wq
;
202 if (!rmap_needs_work(mp
))
205 create_work_queue(&wq
, mp
, libxfs_nproc());
206 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++)
207 queue_work(&wq
, check_rmap_btrees
, i
, NULL
);
208 destroy_work_queue(&wq
);
212 phase4(xfs_mount_t
*mp
)
214 ino_tree_node_t
*irec
;
216 xfs_rtblock_t rt_start
;
220 xfs_agblock_t ag_end
;
222 int ag_hdr_len
= 4 * mp
->m_sb
.sb_sectsize
;
226 if (rmap_needs_work(mp
))
227 collect_rmaps
= true;
228 ag_hdr_block
= howmany(ag_hdr_len
, mp
->m_sb
.sb_blocksize
);
230 do_log(_("Phase 4 - check for duplicate blocks...\n"));
231 do_log(_(" - setting up duplicate extent list...\n"));
233 set_progress_msg(PROG_FMT_DUP_EXTENT
, (__uint64_t
) glob_agcount
);
235 irec
= find_inode_rec(mp
, XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
),
236 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rootino
));
239 * we always have a root inode, even if it's free...
240 * if the root is free, forget it, lost+found is already gone
242 if (is_inode_free(irec
, 0) || !inode_isadir(irec
, 0)) {
245 do_warn(_("root inode would be lost\n"));
247 do_warn(_("root inode lost\n"));
250 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
251 ag_end
= (i
< mp
->m_sb
.sb_agcount
- 1) ? mp
->m_sb
.sb_agblocks
:
252 mp
->m_sb
.sb_dblocks
-
253 (xfs_rfsblock_t
) mp
->m_sb
.sb_agblocks
* i
;
256 * set up duplicate extent list for this ag
258 for (j
= ag_hdr_block
; j
< ag_end
; j
+= blen
) {
259 bstate
= get_bmap_ext(i
, j
, ag_end
, &blen
);
264 _("unknown block state, ag %d, block %d\n"),
266 /* fall through .. */
276 add_dup_extent(i
, j
, blen
);
281 PROG_RPT_INC(prog_rpt_done
[i
], 1);
286 * initialize realtime bitmap
291 for (bno
= 0; bno
< mp
->m_sb
.sb_rextents
; bno
++) {
292 bstate
= get_rtbmap(bno
);
297 _("unknown rt extent state, extent %" PRIu64
"\n"),
299 /* fall through .. */
311 * add extent and reset extent state
313 add_rt_dup_extent(rt_start
, rt_len
);
322 } else if (rt_len
== MAXEXTLEN
) {
326 add_rt_dup_extent(rt_start
, rt_len
);
336 * catch tail-case, extent hitting the end of the ag
339 add_rt_dup_extent(rt_start
, rt_len
);
342 * initialize bitmaps for all AGs
346 do_log(_(" - check for inodes claiming duplicate blocks...\n"));
347 set_progress_msg(PROG_FMT_DUP_BLOCKS
, (__uint64_t
) mp
->m_sb
.sb_icount
);
350 * ok, now process the inodes -- signal 2-pass check per inode.
351 * first pass checks if the inode conflicts with a known
352 * duplicate extent. if so, the inode is cleared and second
353 * pass is skipped. second pass sets the block bitmap
354 * for all blocks claimed by the inode. directory
355 * and attribute processing is turned OFF since we did that
356 * already in phase 3.
361 * Process all the reverse-mapping data that we collected. This
362 * involves checking the rmap data against the btree.
364 process_rmap_data(mp
);
369 * free up memory used to track trealtime duplicate extents
372 free_rt_dup_extent_tree(mp
);
375 * ensure consistency of quota inode pointers in superblock,
376 * make sure they point to real inodes