📄 fsckino.c
字号:
* failure: something else */int unrecord_valid_inode(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int uvi_rc = FSCK_OK; int64_t ea_blocks = 0; int64_t acl_blocks = 0; /* * unrecord the extent (if any) containing the EA */ if ((inoptr->di_ea.flag == DXD_EXTENT) && (!inorecptr->ignore_ea_blks)) { ea_blocks = lengthDXD(&(inoptr->di_ea)); agg_recptr->blocks_for_eas -= ea_blocks; uvi_rc = backout_EA(inoptr, inorecptr); } /* * unrecord the extent (if any) containing the ACL */ if ((inoptr->di_acl.flag == DXD_EXTENT) && (!inorecptr->ignore_acl_blks)) { acl_blocks = lengthDXD(&(inoptr->di_acl)); agg_recptr->blocks_for_acls -= acl_blocks; uvi_rc = backout_ACL(inoptr, inorecptr); } /* * unrecord the extents (if any) describing data * * note that the tree is valid or we'd be ignoring these allocated * blocks. */ if (uvi_rc == FSCK_OK) { if (inorecptr->inode_type == directory_inode) { agg_recptr->blocks_for_dirs -= inoptr->di_nblocks - ea_blocks; uvi_rc = process_valid_dir_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); } else { agg_recptr->blocks_for_files -= inoptr->di_nblocks - ea_blocks; uvi_rc = process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); } } return (uvi_rc);}/***************************************************************************** * NAME: validate_ACL * * FUNCTION: Determine whether the structures in the specified inode to * describe ACL data owned by the inode are consistent and (as * far as fsck can tell) correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int validate_ACL(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int vacl_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t recorded_length, shortest_valid, longest_valid; uint32_t ext_length; int64_t ext_address; int8_t extent_is_valid = 0; uint16_t size16; struct dinode an_inode; dxd_ptr = &(inoptr->di_acl); msg_info_ptr->msg_dxdtyp = fsck_ACL; if (dxd_ptr->flag == 0) goto out; /* there is an ACL for this inode */ if ((dxd_ptr->flag != DXD_EXTENT) && (dxd_ptr->flag != DXD_INLINE) && (dxd_ptr->flag != DXD_CORRUPT)) { /* not a single extent AND not inline AND not already * reported */ fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; inorecptr->ignore_acl_blks = 1; agg_recptr->corrections_needed = 1; goto out; } /* else the acl flag is ok */ if (dxd_ptr->flag == DXD_INLINE) { /* ACL is inline */ size16 = sizeof (an_inode.di_inlineea); agg_recptr->this_inode.acl_inline = 1; agg_recptr->this_inode.inline_acl_length = (uint16_t) dxd_ptr->size; agg_recptr->this_inode.inline_acl_offset = (uint16_t) addressDXD(dxd_ptr); if ((dxd_ptr->size == 0) || (dxd_ptr->size > (size16 - agg_recptr->this_inode.inline_acl_offset))) { /* * the length extends * beyond the end of the inode */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; } } else if (dxd_ptr->flag == DXD_EXTENT) { /* else the ACL is a single extent */ ext_length = lengthDXD(dxd_ptr); shortest_valid = (ext_length - 1) * sb_ptr->s_bsize + 1; longest_valid = ext_length * sb_ptr->s_bsize; if ((ext_length == 0) || (dxd_ptr->size < shortest_valid) || (dxd_ptr->size > longest_valid)) { /* invalid length */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; inorecptr->ignore_acl_blks = 1; agg_recptr->corrections_needed = 1; recorded_length = 0; extent_is_valid = 0; } else { /* length and size might be ok */ agg_recptr->this_inode.acl_blks = ext_length; ext_address = addressDXD(dxd_ptr); vacl_rc = process_extent(inorecptr, ext_length, ext_address, 0, -1, msg_info_ptr, &recorded_length, &extent_is_valid, FSCK_RECORD_DUPCHECK); /* * add the blocks in the ACL extent to the running * totals for the fileset and inode, but not for * the object represented by the object. */ agg_recptr->blocks_this_fset += recorded_length; agg_recptr->this_inode.all_blks += recorded_length; } if (!extent_is_valid) { inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; } } out: return (vacl_rc);}/***************************************************************************** * NAME: validate_dasd_used * * FUNCTION: Verify that, for each directory with a dasd limit set, the * cumulative amount of dasd used matches the value stored in the * inode. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int validate_dasd_used(){ int vdu_rc = FSCK_OK; uint32_t ino_idx; struct dinode *inoptr; struct fsck_inode_record *this_inorec; int aggregate_inode = 0; /* going for fileset inodes only */ int which_it = 0; /* in release 1 there is only fileset 0 */ int64_t dasd_used = 0; /* * We make a single pass on the inode records: * * if the inode record shows that the inode has a dasd limit, * verify that the dasd used amount stored in the inode matches * the amount calculated for the inode by fsck. */ vdu_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((vdu_rc == FSCK_OK) && (this_inorec != NULL) && (ino_idx < ROOT_I)) { /* not interesting until we get to the root inode */ vdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } /* end while */ while ((vdu_rc == FSCK_OK) && (this_inorec != NULL)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls)) { /* inode in use and not selected to release */ if (this_inorec->inode_type == directory_inode) { /* it's a directory */ vdu_rc = inode_get(aggregate_inode, which_it, ino_idx, &inoptr); if (vdu_rc != FSCK_OK) goto out; /* got the inode */ dasd_used = DASDUSED(&(inoptr->di_DASD)); if (dasd_used != this_inorec->cumm_blocks) { /* it isn't right! */ this_inorec->crrct_cumm_blks = 1; agg_recptr->corrections_needed = 1; agg_recptr->corrections_approved = 1; } } } vdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } out: return (vdu_rc);}/***************************************************************************** * NAME: validate_data * * FUNCTION: Determine whether the structures in, or rooted in, the specified * non-directory inode to describe data owned by the inode are * consistent and (as far as fsck can tell) correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int validate_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int vd_rc = FSCK_OK; int intermed_rc = FSCK_OK; dxd_t *dxd_ptr; xtpage_t *xtp_ptr; dxd_ptr = &(inoptr->di_dxd); /* the data root dxd */ msg_info_ptr->msg_dxdtyp = fsck_objcontents; /* * Symbolic link is a special case. If the value fits within the * inode, the dxd appears to be an empty xtree, but it's unused. * In this case, ignore the dxd. */ if (ISLNK(inoptr->di_mode) && (inoptr->di_size < IDATASIZE)) { /* Null terminator stored but not accounted for in di_size */ agg_recptr->this_inode.in_inode_data_length = inoptr->di_size + 1; goto out; } /* * examine the data field */ if (dxd_ptr->flag == 0) goto out; if ((dxd_ptr->flag == (DXD_INDEX | BT_ROOT | BT_LEAF)) || (dxd_ptr->flag == (DXD_INDEX | BT_ROOT | BT_INTERNAL))) { /* * to be valid, it has to be a B-tree node, * either root-leaf or root-internal */ /* * figure out how much space the root occupies in the inode * itself */ xtp_ptr = (xtpage_t *) (&inoptr->di_btroot); agg_recptr->this_inode.in_inode_data_length = (xtp_ptr->header.maxentry - 2) * sizeof (xad_t); /* * the dxd actually starts 32 bytes (== 2 * length of * an xad) before the boundary. * the 0th and 1st entries in the xad array are * really the header */ /* * validate the tree contents and record the extents it * describes until and unless the tree is found to be corrupt */ vd_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD_DUPCHECK); if (vd_rc <= FSCK_OK) goto out; /* nothing fatal */ if (inorecptr->selected_to_rls && inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATAIDX; } else if (inorecptr->ignore_alloc_blks) { /* the tree info can't be used */ if (inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATAIDX; } /* * reverse the notations made when recording the * extents for the tree. Again, stop when the point * of corruption is found since that's where the * recording process was stopped. */ intermed_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } if (!inorecptr->ignore_ea_blks) { intermed_rc = backout_EA(inoptr, inorecptr); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } if (!inorecptr->ignore_acl_blks) { intermed_rc = backout_ACL(inoptr, inorecptr); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } } } } } else { /* else not B+ Tree index */ /* * the data root is not valid...the info cannot be trusted */ if (inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATA; } else { inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; } fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); } out: return (vd_rc);}/***************************************************************************** * NAME: validate_dir_data * * FUNCTION: Determine whether the structures in, or rooted in, the * specified directory inode to describe data owned by the * inode are consistent and (as far as fsck can tell) * correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing the * current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int validate_dir_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int vdd_rc = FSCK_OK; int intermed_rc = FSCK_OK; int dtree_rc = FSCK_OK; dxd_t *dxd_ptr; int8_t save_ignore_alloc_blks; int8_t xt_ignore_alloc_blks = 0; dxd_ptr = &(inoptr->di_dxd); /* the data root dxd */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -