📄 xchkdsk.c
字号:
} } /* may write to superblocks again */ rc = agg_clean_or_dirty(); } if (agg_recptr->ag_modified) { /* wrote to it at least once */ fsck_send_msg(fsck_MODIFIED); } if (agg_recptr->ag_dirty) { exit_value = FSCK_ERRORS_UNCORRECTED; } /* * Log fsck exit */ fsck_send_msg(fsck_SESSEND, time_stamp, rc, exit_value); /* * terminate fsck service logging */ fscklog_end(); /* * release all workspace that has been allocated */ if (rc == FSCK_OK) { rc = workspace_release(); } else { workspace_release(); } close_vol: /* * Close (Unlock) the device */ if (agg_recptr->device_is_open) { if (rc == FSCK_OK) { rc = close_volume(); } else { close_volume(); } } if (!agg_recptr->stdout_redirected) { /* end the "running" indicator */ fsck_hbeat_stop(); } main_exit: return (exit_value);}/***************************************************************************** * NAME: check_parents_and_first_refs * * FUNCTION: If any aggregate blocks are multiply allocated, find the * first reference for each. Verify that the parent inode * number stored in each directory inode matches the parent * inode observed by fsck for that inode. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int check_parents_and_first_refs(){ int rc = FSCK_OK; uint32_t ino_idx; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = 0; int which_it = 0; /* in release 1 there is only fileset 0 */ int inode_already_read, done; int dir_w_hlinks_seen = 0; int dir_w_incrrct_prnt_seen = 0; int unalloc_ino_w_prnts_seen = 0; int unconnected_inode_seen = 0; struct dinode *inoptr; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *this_inorec; struct fsck_inode_record *parent_inorec; 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_fset_inode; /* all fileset owned */ rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((rc == FSCK_OK) && (this_inorec != NULL)) { msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (this_inorec->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (this_inorec->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (this_inorec->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (this_inorec->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (this_inorec->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } if (this_inorec->in_use) goto inode_in_use; /* not in use. A record allocated means some * directory thinks this inode is its parent */ done = 0; if ((this_inorec->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { /* * either this parent isn't the root or else * the root dir has not been rebuilt */ rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &parent_inorec); if ((parent_inorec->in_use) && (!parent_inorec->ignore_alloc_blks) && (!parent_inorec->selected_to_rls)) { /* * parent inode in use and not * selected to release */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; unalloc_ino_w_prnts_seen = 1; done = -1; if (agg_recptr->processing_readonly) { /* won't be able to fix this */ fsck_send_msg(fsck_ROUALINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } this_ext = this_inorec->ext_rec; while ((this_ext != NULL) && (!done)) { if ( (this_ext->ext_type == parent_extension) && ((this_inorec->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) ) { /* * either this parent isn't the root or * else the root dir hasn't been rebuilt */ rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_ext->inonum, &parent_inorec); if ((parent_inorec->in_use) && (!parent_inorec->ignore_alloc_blks) && (!parent_inorec->selected_to_rls)) { /* * parent inode in use and * not selected to release */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; unalloc_ino_w_prnts_seen = 1; done = -1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_ROUALINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } this_ext = this_ext->next; } goto get_next; inode_in_use: /* inode is in use */ inode_already_read = 0; if ((agg_recptr->unresolved_1stref_count != 0) && (!this_inorec->ignore_alloc_blks)) { /* * there are unresolved 1st references * to multiply allocated blocks, and * blocks for this inode are reflected * in the current workspace block map */ rc = inode_get(aggregate_inode, which_it, ino_idx, &inoptr); if (rc == FSCK_OK) { /* got the inode */ inode_already_read = 1; rc = first_ref_check_inode(inoptr, ino_idx, this_inorec, msg_info_ptr); } } if (rc != FSCK_OK) goto get_next; if ((this_inorec->parent_inonum == 0) && (!this_inorec->unxpctd_prnts) && (ino_idx >= FILESET_OBJECT_I)) { /* * no parent recorded and not a dir with * unexpected parents and not a metadata inode */ if (agg_recptr->processing_readonly) { /* * won't be reconnecting this */ fsck_send_msg(fsck_ROUNCONNIO, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } else if (this_inorec->inode_type == directory_inode) { /* * a directory */ if (!inode_already_read) { /* need to read the inode */ rc = inode_get(aggregate_inode, which_it, ino_idx, &inoptr); } /* * if this is a directory with 'unexpected * parents' (aka illegal hard links) then * the inode number which was stored in * parent_inonum has already been stored in * an extension record. Save the parent * inode number stored in the on-disk inode * for use in messages. */ if (rc != FSCK_OK) goto get_next; if (this_inorec->unxpctd_prnts) { /* * unexpected parents seen */ this_inorec->parent_inonum = inoptr->di_parent; dir_w_hlinks_seen = 1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_RODIRWHLKS, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } /* * Otherwise, make sure a parent * was seen and it's the one whose * inode number is stored in the * on-disk inode. */ } else if ((this_inorec->parent_inonum != 0) && (this_inorec->parent_inonum != inoptr->di_parent)) { /* * the stored parent number is wrong */ this_inorec->crrct_prnt_inonum = 1; dir_w_incrrct_prnt_seen = 1; agg_recptr->corrections_needed = 1; agg_recptr->corrections_approved = 1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_ROINCINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_inorec->parent_inonum); } } } get_next: if (rc == FSCK_OK) { rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } if (agg_recptr->processing_readwrite) { /* we can fix these */ if (unalloc_ino_w_prnts_seen) { fsck_send_msg(fsck_WILLFIXROUALINOREFS); } if (unconnected_inode_seen) { fsck_send_msg(fsck_WILLFIXROUNCONNIOS); } if (dir_w_hlinks_seen) { fsck_send_msg(fsck_WILLFIXRODIRSWHLKS); } if (dir_w_incrrct_prnt_seen) { fsck_send_msg(fsck_WILLFIXROINCINOREFS); } } else { /* don't have write access */ if (unalloc_ino_w_prnts_seen) { fsck_send_msg(fsck_ROUALINOREFS); } if (unconnected_inode_seen) { fsck_send_msg(fsck_ROUNCONNIOS); } if (dir_w_hlinks_seen) { fsck_send_msg(fsck_RODIRSWHLKS); } if (dir_w_incrrct_prnt_seen) { fsck_send_msg(fsck_ROINCINOREFS); } } return (rc);}/***************************************************************************** * NAME: create_lost_and_found * * FUNCTION: During previous processing, fsck observed at least one inode * to be available, and saved the ordinal number of an available * inode in the fsck aggregate record. Initialize that inode * (and the fsck inode record describing it) for use as * /lost+found/ * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int create_lost_and_found(){ int claf_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_inode_record *new_inorecptr; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = -1; int which_it = FILESYSTEM_I; /* in release 1 there is only fileset 0 */ struct dinode *inoptr; int ixpxd_unequal = 0; int is_aggregate = 0; /* aggregate has no dirs */ /* * find/allocate the fsck workspace inode record * for this inode. */ claf_rc = get_inorecptr(aggregate_inode, alloc_ifnull, agg_recptr->avail_inonum, &new_inorecptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; /* * initialize the workspace inode record for * the new lost+found/ */ new_inorecptr->in_use = 1; new_inorecptr->inode_type = directory_inode; new_inorecptr->link_count = 0; new_inorecptr->parent_inonum = 0; new_inorecptr->selected_to_rls = 0; new_inorecptr->crrct_link_count = 0; new_inorecptr->crrct_prnt_inonum = 0; new_inorecptr->adj_entries = 0; new_inorecptr->clr_ea_fld = 0; new_inorecptr->clr_acl_fld = 0; new_inorecptr->inlineea_on = 0; new_inorecptr->inlineea_off = 0; new_inorecptr->inline_data_err = 0; new_inorecptr->ignore_alloc_blks = 0; new_inorecptr->reconnect = 0; new_inorecptr->unxpctd_prnts = 0; new_inorecptr->involved_in_dups = 0; /* * get the inode to be used for lost+found */ claf_rc = inode_get(aggregate_inode, which_it, agg_recptr->avail_inonum, &inoptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; /* the new lost+found inode is in the buffer */ ixpxd_unequal = memcmp((void *) &inoptr->di_ixpxd, (void *) &agg_recptr->ino_ixpxd, sizeof (pxd_t)); if ((inoptr->di_inostamp == agg_recptr->inode_stamp) && (!ixpxd_unequal) && (inoptr->di_number == agg_recptr->avail_inonum) && (inoptr->di_fileset == agg_recptr->ino_fsnum)) { /* * inode has been used before */ inoptr->di_gen++; } else { /* this inode hasn't been used before */ /* clear it */ memset(inoptr, 0, sizeof (struct dinode)); /* * initialize the inode */ inoptr->di_inostamp = agg_recptr->inode_stamp; inoptr->di_fileset = agg_recptr->ino_fsnum; inoptr->di_number = agg_recptr->avail_inonum; inoptr->di_gen = 1; memcpy((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); } inoptr->di_mode = (IDIRECTORY | IFJOURNAL | IFDIR | IREAD | IWRITE | IEXEC); inoptr->di_parent = ROOT_I; /* one from root and one from self */ inoptr->di_nlink = 2; inoptr->di_nblocks = 0; inoptr->di_size = IDATASIZE; DXDlength(&(inoptr->di_acl), (int32_t) 0); DXDaddress(&(inoptr->di_acl), (int64_t) 0); inoptr->di_acl.flag = 0; inoptr->di_acl.size = 0; DXDlength(&(inoptr->di_ea), (int32_t) 0); DXDaddress(&(inoptr->di_ea), (int64_t) 0); inoptr->di_ea.flag = 0; inoptr->di_ea.size = 0; inoptr->di_next_index = 2; inoptr->di_acltype = 0; inoptr->di_atime.tv_sec = (uint32_t) time(NULL); inoptr->di_ctime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_mtime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_otime.tv_sec = inoptr->di_atime.tv_sec; /* * initialize the d-tree */ init_dir_tree((dtroot_t *) & (inoptr->di_btroot)); /* * write the inode */ claf_rc = inode_put(inoptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; new_inorecptr->parent_inonum = ROOT_I; /* The inode is correct. After * this we'll start accumulating adjustments */ new_inorecptr->link_count = 0; /* * add an entry for it to the root directory
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -