📄 fsckconn.c
字号:
/* parent isn't marked for release (yet) */ dup_parent_detected = 0; if (this_ext-> inonum == this_inorec-> parent_inonum) { dup_parent_detected = -1; } else { /* need to check for dups in rest of list */ that_ext = this_ext-> next; while ((!dup_parent_detected) && (that_ext != NULL)) { if (that_ext->ext_type == parent_extension) /* another parent extension */ if (this_ext->inonum == that_ext->inonum) { dup_parent_detected = -1; } that_ext = that_ext-> next; } } if (dup_parent_detected) { /* * mark the parent's inode record for release */ that_inorec-> selected_to_rls = 1; /* * notify the user that the directory is bad */ fsck_send_msg (fsck_BADKEYS, fsck_ref_msg(fsck_directory), fsck_ref_msg(msg_info_ptr->msg_inopfx), this_ext->inonum, 37); } } } this_ext = this_ext->next; } } } } if (cdi_rc == FSCK_OK) { cdi_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } return (cdi_rc);}/***************************************************************************** * NAME: check_link_counts * * FUNCTION: Count links from child directories to their parents. * * Verify that the link count stored in each in-use inode * matches the number of links fsck observed for the inode. * * RETURNS: * success: FSCK_OK * failure: something else */int check_link_counts(){ int clc_rc = FSCK_OK; uint32_t ino_idx; int num_parents; int invalid_count_seen = 0; int low_stored_count_seen = 0; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *this_inorec; struct fsck_inode_record *parent_inorec; int done_looking = 0; int aggregate_inode = 0; int alloc_ifnull = 0; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; /* * count links from child directories to their parents * * (These can't be counted when the parent-child relationship * is observed because that observation occurs while processing * the parent and until the child is processed we don't know * whether the child is a directory or not.) */ clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks) && (this_inorec->inode_type == directory_inode)) { /* inode is in use, not being released, and is type directory */ /* for the self entry */ this_inorec->link_count++; if ((this_inorec->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and root was * rebuilt, then don't increment parent */ if (this_inorec->inonum == ROOT_I) { /* * special case: if this IS the root, then it's * link from itself to itself DOES count */ this_inorec->link_count++; } } else if (this_inorec->parent_inonum != 0) { /* not an orphan */ clc_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &parent_inorec); if ((clc_rc != FSCK_OK) || (parent_inorec == NULL)) { clc_rc = FSCK_INTERNAL_ERROR_13; fsck_send_msg(fsck_INTERNALERROR, clc_rc, ino_idx, this_inorec->parent_inonum, 0); } else { /* handle the first (and usually the only) parent. */ parent_inorec->link_count++; } if ((clc_rc == FSCK_OK) && (this_inorec->ext_rec != NULL)) { /* there might be more parents */ num_parents = parent_count(this_inorec); if (num_parents > 1) { /* directory with illegal links */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; /* * Create an extension record for the parent inode * number now stored in the child inode record. * When we traverse the aggregate on-disk we'll copy * the stored value into this field of the inode record * for use when displaying paths to the inode. */ clc_rc = get_inode_extension (&this_ext); if (clc_rc == FSCK_OK) { /* got extension record */ this_ext->ext_type = parent_extension; this_ext->inonum = this_inorec-> parent_inonum; this_ext->next = this_inorec-> ext_rec; this_inorec->ext_rec = this_ext; this_inorec-> parent_inonum = 0; /* already counted the first * one, back when it was in the * workspace inode record itself */ this_ext = this_ext->next; while ((clc_rc == FSCK_OK) && (this_ext != NULL)) { /* exten records to check */ if (this_ext-> ext_type == parent_extension) { clc_rc = get_inorecptr (aggregate_inode, alloc_ifnull, this_ext-> inonum, &parent_inorec); if ((clc_rc != FSCK_OK) || (parent_inorec == NULL)) { clc_rc = FSCK_INTERNAL_ERROR_14; fsck_send_msg (fsck_INTERNALERROR, clc_rc, ino_idx, this_ext->inonum, 0); } else { parent_inorec-> link_count++; } } this_ext = this_ext-> next; } } } } } } if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } /* * verify that stored link counts match observed link counts * * We have added each observed link and subtracted the stored * count. If the stored count is correct the result is 0. */ if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL) && (!done_looking)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks)) { /* inode is in use and not being released */ if (this_inorec->link_count != 0) { /* stored link count doesn't match fsck's observations */ if (this_inorec->parent_inonum == 0) { /* inode is an orphan */ this_inorec->crrct_link_count = 1; } else { /* not an orphan */ this_inorec->crrct_link_count = 1; if (this_inorec->link_count > 0) { low_stored_count_seen = 1; } invalid_count_seen = 1; fsck_send_msg(fsck_BADINOLKCT, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } if ((clc_rc == FSCK_OK) && (invalid_count_seen)) { if (agg_recptr->processing_readwrite) { agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLFIXLINKCTS); } else { /* no write access */ if (low_stored_count_seen) { agg_recptr->ag_dirty = 1; } /* * reset all link counts (in the fsck workspace) to * zero so that we won't accidentally correct them * while doing link count adjustments. * * (Link count adjustments are side effects of approved * repairs. For example, if a directory inode is * released, the link count of its parent directory * is decremented.) */ clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL)) { if (this_inorec->in_use) { this_inorec->crrct_link_count = 0; this_inorec->link_count = 0; } clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } fsck_send_msg(fsck_BADLINKCTS); } } } return (clc_rc);}/***************************************************************************** * NAME: reset_parents * * FUNCTION: Adjust the fsck notations about the inode's parent(s) if * the parent(s) are corrupt or approved for release. * * PARAMETERS: * ino_recptr - input - pointer to an fsck record describing the inode * ino_idx - input - ordinal number of the inode * * RETURNS: * success: FSCK_OK * failure: something else */int reset_parents(struct fsck_inode_record *ino_recptr, uint32_t ino_idx){ int resps_rc = FSCK_OK; struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *rest_of_list; int parent_count = 0; uint32_t stored_parent_inonum = 0; struct fsck_inode_record *parent_inorecptr; int aggregate_inode = 0; int alloc_ifnull = 0; /* * if this is a directory with illegal hard links the inode * number in the fsck inode record is the one stored in the * inode on disk. */ if ((ino_recptr->inode_type == directory_inode) && (ino_recptr->unxpctd_prnts)) { /* dir with multiple parents */ /* * Save the value stored in the inode record and then clear it. */ stored_parent_inonum = ino_recptr->parent_inonum; ino_recptr->parent_inonum = 0; } else { /* not a dir with multiple parents */ /* * the 1st parent observed is in the inode record. * Any others are in extension records. */ resps_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_recptr->parent_inonum, &parent_inorecptr); if ((resps_rc == FSCK_OK) && (parent_inorecptr == NULL)) { resps_rc = FSCK_INTERNAL_ERROR_15; fsck_send_msg(fsck_INTERNALERROR, resps_rc, ino_idx, ino_recptr->parent_inonum, 0); } else if (resps_rc == FSCK_OK) { if ((ino_recptr->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and root * was rebuilt, then this is an orphan */ ino_recptr->parent_inonum = 0; ino_recptr->link_count--; } else if ((!parent_inorecptr->selected_to_rls) && (!parent_inorecptr->ignore_alloc_blks)) { /* * keeping this parent and haven't found the * tree to be corrupt */ parent_count++; } else { /* releasing this parent */ ino_recptr->parent_inonum = 0; ino_recptr->link_count--; } } } /* * detach the extensions list from the inode record */ this_ext = ino_recptr->ext_rec; ino_recptr->ext_rec = NULL; while ((resps_rc == FSCK_OK) && (this_ext != NULL)) { /* there may be more parents */ rest_of_list = this_ext->next; if (this_ext->ext_type != parent_extension) { /* not a parent */ this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; } else { /* parent extension */ resps_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_ext->inonum, &parent_inorecptr); if ((resps_rc == FSCK_OK) && (parent_inorecptr == NULL)) { resps_rc = FSCK_INTERNAL_ERROR_16; fsck_send_msg(fsck_INTERNALERROR, resps_rc, ino_idx, this_ext->inonum, 0); } else if (resps_rc == FSCK_OK) { if ((ino_recptr->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and * root was rebuilt, then this is an orphan */ release_inode_extension(this_ext); ino_recptr->link_count--; } else if ((!parent_inorecptr->selected_to_rls) && (!parent_inorecptr-> ignore_alloc_blks)) { /* keeping this parent */ parent_count++; if (ino_recptr->parent_inonum == 0) { ino_recptr->parent_inonum = this_ext->inonum; release_inode_extension (this_ext); } else { /* put it back on the list */ this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; } } else { /* releasing this parent */ release_inode_extension(this_ext); ino_recptr->link_count--; } } } this_ext = rest_of_list; } /* * at this point, if there is at least 1 observed parent which * is not being released, then a parent inode number is stored in * the inode record and any other parents are described in extension * records. * * if this is not a directory inode, we're done. * * if this is a directory inode, need to recheck for illegal hard * links and incorrect parent inode entry. */ if ((resps_rc == FSCK_OK) && (ino_recptr->inode_type == directory_inode)) { /* a directory */ if (parent_count == 1) { /* 1 parent now */ if (ino_recptr->unxpctd_prnts) { /* entered with multiple links */ /* reset flag */ ino_recptr->unxpctd_prnts = 0; if (ino_recptr->parent_inonum != stored_parent_inonum) { /* * Remaining parent doesn't match the one * the on-device inode says owns it. */ ino_recptr->crrct_prnt_inonum = 1; agg_recptr->corrections_needed = 1; agg_recptr->corrections_approved = 1; } } } else if (parent_count == 0) { /* no parents now */ ino_recptr->crrct_prnt_inonum = 0; ino_recptr->unxpctd_prnts = 0; } else { /* multiple parents still */ ino_recptr->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; resps_rc = get_inode_extension(&this_ext); if (resps_rc == FSCK_OK) { this_ext->ext_type = parent_extension; this_ext->inonum = ino_recptr->parent_inonum; this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; ino_recptr->parent_inonum = stored_parent_inonum; } } } return (resps_rc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -