📄 fsckmeta.c
字号:
/* * Copyright (c) International Business Machines Corp., 2000-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <config.h>#include <string.h>#include <time.h>/* defines and includes common among the fsck.jfs modules */#include "xfsckint.h"#include "devices.h"#include "diskmap.h"#include "jfs_byteorder.h"#include "message.h"#include "super.h"#include "utilsubs.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */extern char *Vol_Label;/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */int backout_ait_part1(int);int backout_valid_agg_inode(int, uint32_t, struct fsck_ino_msg_info *);int first_ref_check_other_ait(void);int record_ait_part1_again(int);int record_other_ait(void);int rootdir_tree_bad(struct dinode *, int *);int validate_super(int);int validate_super_2ndaryAI(int);int verify_agg_fileset_inode(struct dinode *, uint32_t, int, struct fsck_ino_msg_info *);int verify_ait_inode(struct dinode *, int, struct fsck_ino_msg_info *);int verify_ait_part1(int);int verify_ait_part2(int);int verify_badblk_inode(struct dinode *, int, struct fsck_ino_msg_info *);int verify_bmap_inode(struct dinode *, int, struct fsck_ino_msg_info *);int verify_fs_super_ext(struct dinode *, struct fsck_ino_msg_info *, int *);int verify_log_inode(struct dinode *, int, struct fsck_ino_msg_info *);int verify_metadata_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *);int verify_repair_fs_rootdir(struct dinode *, struct fsck_ino_msg_info *, int *);/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV *//***************************************************************************** * NAME: agg_clean_or_dirty * * FUNCTION: Compare the superblock state field (s_state) with fsck's * conclusions about the current state (clean | dirty) of * the aggregate. If write access, attempt to update the * state field if the superblock is incorrect. If read-only, * notify the caller if the superblock is incorrect. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int agg_clean_or_dirty(){ int acod_rc = FSCK_OK; if (!agg_recptr->ag_dirty) { /* aggregate is actually clean now */ /* announce this happy news */ fsck_send_msg(fsck_AGGCLN); if (agg_recptr->processing_readonly) { /* don't have write access */ if ((sb_ptr->s_state & FM_DIRTY) == FM_DIRTY) { /* but isn't marked clean */ fsck_send_msg(fsck_AGGCLNNOTDRTY); } } else { /* do have write access to the aggregate */ fsck_send_msg(fsck_ALLFXD); sb_ptr->s_state = FM_CLEAN; acod_rc = replicate_superblock(); if (acod_rc == FSCK_OK) { fsck_send_msg(fsck_AGGMRKDCLN); } } } else { /* aggregate is actually dirty now */ fsck_send_msg(fsck_AGGDRTY); if ((sb_ptr->s_state & FM_DIRTY) != FM_DIRTY) { /* but isn't marked dirty */ if (agg_recptr->processing_readonly) { /* don't have write access */ fsck_send_msg(fsck_AGGDRTYNOTCLN, Vol_Label); } else { /* do have write access to the aggregate */ /* * in keeping with the policy of protecting the system * from a potential panic due to a dirty file system, * if we have write access we'll mark the file system * dirty without asking permission. */ sb_ptr->s_state = FM_DIRTY; acod_rc = replicate_superblock(); if (acod_rc == FSCK_OK) { fsck_send_msg(fsck_AGGMRKDDRTY); } } } } return (acod_rc);}/***************************************************************************** * NAME: backout_ait_part1 * * FUNCTION: Unrecord, in the fsck workspace block map, all storage allocated * to inodes in part 1 (inodes 0 through 15) of the specified * (primary or secondary) aggregate inode table. * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * * NOTES: o The caller to this routine must ensure that the * calls made by backout_ait_part1 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */int backout_ait_part1(int which_ait){ int baitp1_rc = FSCK_OK; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; agg_recptr->inode_stamp = -1; msg_info_ptr->msg_inonum = AGGREGATE_I; baitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); msg_info_ptr->msg_inonum = BMAP_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); msg_info_ptr->msg_inonum = LOG_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, LOG_I, msg_info_ptr); msg_info_ptr->msg_inonum = BADBLOCK_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, BADBLOCK_I, msg_info_ptr); } } } return (baitp1_rc);}/***************************************************************************** * NAME: backout_valid_agg_inode * * FUNCTION: Unrecord, in the fsck workspace block map, storage allocated to * the specified aggregate inode, assuming that all data structures * associated with the inode are consistent. (E.g., the B+ Tree * is at least internally consistent.) * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * inoidx - input - ordinal number of the inode (i.e., inode number * as an int32_t) * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * NOTES: o The caller to this routine must ensure that the * calls made by backout_ait_part1 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */int backout_valid_agg_inode(int which_ait, uint32_t inoidx, struct fsck_ino_msg_info *msg_info_ptr){ int bvai_rc = FSCK_OK; int agg_inode = -1; int alloc_ifnull = 0; struct dinode *inoptr; struct fsck_inode_record *inorecptr; bvai_rc = inode_get(agg_inode, which_ait, inoidx, &inoptr); if (bvai_rc != FSCK_OK) { /* didn't get the inode */ bvai_rc = FSCK_FAILED_REREAD_AGGINO; } else { /* got the inode */ bvai_rc = get_inorecptr(agg_inode, alloc_ifnull, inoidx, &inorecptr); if ((bvai_rc == FSCK_OK) && (inorecptr == NULL)) { bvai_rc = FSCK_INTERNAL_ERROR_22; fsck_send_msg(fsck_INTERNALERROR, bvai_rc, 0, 0, 0); } else if (bvai_rc == FSCK_OK) { bvai_rc = unrecord_valid_inode(inoptr, inoidx, inorecptr, msg_info_ptr); } } return (bvai_rc);}/***************************************************************************** * NAME: fatal_dup_check * * FUNCTION: Determine whether any blocks are allocated to more than one * aggregate metadata object. (If so, the aggregate is too * far gone for fsck to correct it, or even to analyze it with * any confidence.) * * PARAMETERS: none * * NOTES: * This routine is called after all the following has been * completed: * - all metadata (aggregate and fileset) has been validated * - all inode extents have been recorded * - all fixed metadata has been recorded * - the block map and inode map have been recorded * * A similar check is done in validate_select_agg_inode_table * when an apparently valid part of the table has been identified. * * RETURNS: * success: FSCK_OK * failure: something else */int fatal_dup_check(){ struct dupall_blkrec *dupblk_ptr; int64_t first_in_range, this_blknum, last_blknum; uint32_t range_size; if (agg_recptr->dup_alloc_lst == NULL) return FSCK_OK; /* duplicate allocations detected during metadata validation */ dupblk_ptr = agg_recptr->dup_alloc_lst; first_in_range = dupblk_ptr->first_blk; last_blknum = dupblk_ptr->last_blk; dupblk_ptr = dupblk_ptr->next; while (dupblk_ptr != NULL) { /* for all multiply allocated blocks */ this_blknum = dupblk_ptr->first_blk; if (last_blknum != (this_blknum - 1)) { range_size = last_blknum - first_in_range + 1; fsck_send_msg(fsck_DUPBLKMDREF, range_size, (long long) first_in_range); first_in_range = this_blknum; } last_blknum = dupblk_ptr->last_blk; dupblk_ptr = dupblk_ptr->next; } range_size = last_blknum - first_in_range + 1; fsck_send_msg(fsck_DUPBLKMDREF, range_size, (long long) first_in_range); fsck_send_msg(fsck_DUPBLKMDREFS); agg_recptr->ag_dirty = 1; return (FSCK_DUPMDBLKREF);}/***************************************************************************** * NAME: first_ref_check_agg_metadata * * FUNCTION: Determine whether the storage allocated for aggregate metadata * includes a reference to any multiply-allocated aggregate blocks * for which the first reference is still unresolved. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int first_ref_check_agg_metadata(){ int frcam_rc = FSCK_OK; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = -1; /* going for aggregate inodes only */ int alloc_ifnull = 0; int which_ait; struct fsck_inode_record *inorec_ptr; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; /* * check ait part 1 inodes for first references */ (agg_recptr->primary_ait_4part1) ? (which_ait = fsck_primary) : (which_ait = fsck_secondary); /* try for the self inode */ ino_idx = AGGREGATE_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the self inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_25; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_SELF_READ3; } if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* try for the blockmap inode */ ino_idx = BMAP_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the block map inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -