📄 fsckxtre.c
字号:
last_key = -1; for (xadidx = XTENTRYSTART; ((xadidx < xtpg_ptr->header.nextindex) && (xpie_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)); xadidx++) { xad_ptr = &(xtpg_ptr->xad[xadidx]); if ((xad_ptr->flag & flag_mask)) { /* bad flag value */ ino_recptr->ignore_alloc_blks = 1; goto out; } this_key = offsetXAD(xad_ptr); if (this_key <= last_key) { /* these keys MUST ascend */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 7); } goto out; } /* key looks ok from here */ last_key = this_key; ext_addr = addressXAD(xad_ptr); ext_length = lengthXAD(xad_ptr); xpie_rc = process_extent(ino_recptr, ext_length, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &ext_ok, desired_action); if ((xpie_rc != FSCK_OK) || !ext_ok) goto out; /* extent is good */ if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += adjusted_length; agg_recptr->this_inode.all_blks += adjusted_length; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= adjusted_length; agg_recptr->this_inode.all_blks -= adjusted_length; } xpie_rc = treeQ_get_elem(&new_Qelptr); if (xpie_rc != FSCK_OK) goto out; /* got a queue element */ new_Qelptr->node_level = Q_elptr->node_level + 1; new_Qelptr->node_addr = ext_addr; PXDaddress(&(new_Qelptr->node_pxd), ext_addr); PXDlength(&(new_Qelptr->node_pxd), ext_length); new_Qelptr->node_first_offset = this_key; xpie_rc = treeQ_enqueue(new_Qelptr); } out: return (xpie_rc);}/***************************************************************************** * NAME: xTree_process_leaf_extents * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtpg_ptr - input - pointer to the leaf node in an fsck buffer * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * Q_elptr - input - address of an fsck Q element pointer * describing the leaf * msg_info_ptr - input - pointer to data needed for messages about the * inode in which the xTree is rooted * dense_file - input - !0 => the xTree describes a dense file * 0 => the xTree describes a file which may * be sparse * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */int xTree_process_leaf_extents(xtpage_t * xtpg_ptr, struct fsck_inode_record *ino_recptr, struct treeQelem *Q_elptr, struct fsck_ino_msg_info *msg_info_ptr, int8_t dense_file, int desired_action){ int xple_rc = FSCK_OK; int64_t last_key, this_key; uint32_t xadidx; uint32_t ext_length, adjusted_length; int64_t ext_addr; int8_t ext_ok; int8_t is_EA = 0; int8_t is_ACL = 0; xad_t *xad_ptr; uint32_t ext_pages; uint8_t flag_mask; flag_mask = ~(XAD_NEW | XAD_EXTENDED | XAD_COMPRESSED | XAD_NOTRECORDED | XAD_COW); last_key = -1; for (xadidx = XTENTRYSTART; ((xadidx < xtpg_ptr->header.nextindex) && (xple_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)); xadidx++) { xad_ptr = &(xtpg_ptr->xad[xadidx]); if ((xad_ptr->flag & flag_mask)) { /* bad flag value */ ino_recptr->ignore_alloc_blks = 1; } this_key = offsetXAD(xad_ptr); if ((last_key != -1) && (!ino_recptr->ignore_alloc_blks)) { /* not the first key */ if (this_key <= last_key) { /* these keys MUST ascend */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 8); } goto out; } /* the keys do ascend */ if ((dense_file) && (this_key != (last_key + 1))) { /* a dense file with a gap! */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADINOINTERNGAP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, msg_info_ptr->msg_inonum); } goto out; } } ext_addr = addressXAD(xad_ptr); ext_length = lengthXAD(xad_ptr); last_key = this_key + ext_length - 1; agg_recptr->this_inode.data_size = (last_key + 1) * sb_ptr->s_bsize; /* * all extents (except the very last one for the inode) must * be in full (4096 byte) pages. */ ext_pages = ext_length >> agg_recptr->log2_blksperpg; if ((ext_length != (ext_pages << agg_recptr->log2_blksperpg)) && (!(ino_recptr->badblk_inode))) { /* * this one is an odd size and isn't * owned by the bad block inode */ if (xadidx == (xtpg_ptr->header.nextindex - 1)) { /* * this is the last extent for the node * and might be the last for the inode */ Q_elptr->last_ext_uneven = -1; } else { /* not the last extent for the xtpage */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg (fsck_BADINOODDINTRNEXT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, (long long) this_key, ext_length); } goto out; } } xple_rc = process_extent(ino_recptr, ext_length, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &ext_ok, desired_action); if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += adjusted_length; agg_recptr->this_inode.all_blks += adjusted_length; agg_recptr->this_inode.data_blks += adjusted_length; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= adjusted_length; agg_recptr->this_inode.all_blks -= adjusted_length; agg_recptr->this_inode.data_blks -= adjusted_length; } } out: return (xple_rc);}/***************************************************************************** * NAME: xTree_processing * * FUNCTION: Validate the structure of the xTree rooted in the given inode * and perform the desired_action on the nodes in the xTree. * Stop processing the xTree if and when any symptom of corruption * is detected. * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree is * rooted * inoidx - input - ordinal number of the inode * inorecptr - input - pointer to the fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed for messages about * the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY | * FSCK_FSIM_RECORD_DUPCHECK | * FSCK_FSIM_UNRECORD | FSCK_FSIM_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */int xTree_processing(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action){ int xp_rc = FSCK_OK; int8_t old_ignore_alloc_blks = 0; int ixpxd_unequal = 0; int is_root = -1; int not_fsim_tree = -1; struct fsck_Xtree_info xtinfo; struct fsck_Xtree_info *xtiptr; xtiptr = &xtinfo; xtiptr->this_Qel = NULL; xtiptr->next_Qel = NULL; xtiptr->last_level = -1; /* -1 so the root will be recognized * as 1st node in level 0 */ xtiptr->dense_file = 0; xtiptr->leaf_seen = 0; if (!(inoptr->di_mode & ISPARSE)) { xtiptr->dense_file = -1; } switch (desired_action) { case (FSCK_FSIM_RECORD_DUPCHECK): not_fsim_tree = 0; desired_action = FSCK_RECORD_DUPCHECK; break; case (FSCK_FSIM_UNRECORD): not_fsim_tree = 0; desired_action = FSCK_UNRECORD; break; case (FSCK_FSIM_QUERY): not_fsim_tree = 0; desired_action = FSCK_QUERY; break; default: break; } if (ISDIR(inoptr->di_mode)) xtiptr->xtp_ptr = (xtpage_t *) & (inoptr->di_dirtable); else xtiptr->xtp_ptr = (xtpage_t *) & (inoptr->di_btroot); if ((!ISDIR(inoptr->di_mode) && (xtiptr->xtp_ptr->header.maxentry != XTROOTINITSLOT) && (xtiptr->xtp_ptr->header.maxentry != XTROOTMAXSLOT)) || (ISDIR(inoptr->di_mode) && (xtiptr->xtp_ptr->header.maxentry != XTROOTINITSLOT_DIR))) { /* bad maxentry field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "45", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* end not reported yet */ goto out; } if (xtiptr->xtp_ptr->header.nextindex > xtiptr->xtp_ptr->header.maxentry) { /* bad nextindex field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "46", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } goto out; } if (xtiptr->xtp_ptr->header.nextindex <= XTENTRYSTART) goto out; /* data length > 0 */ if (desired_action != FSCK_RECORD_DUPCHECK) { /* not the first pass */ /* * The first time through we stopped processing allocated * blocks if and when we discovered the tree to be corrupt. * On a 2nd pass we want to stop at the same place. */ if (inorecptr->ignore_alloc_blks) { /* the bit is on */ old_ignore_alloc_blks = -1; inorecptr->ignore_alloc_blks = 0; } } xtiptr->this_key = offsetXAD(&(xtiptr->xtp_ptr->xad[XTENTRYSTART])); if (xtiptr->dense_file && (xtiptr->this_key != ((int64_t) 0))) { /* a dense file with a gap at the front */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOFRONTGAP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } goto release; } xp_rc = treeQ_get_elem(&xtiptr->this_Qel); if (xp_rc != FSCK_OK) goto out; xtiptr->this_Qel->node_level = 0; if (xtiptr->xtp_ptr->header.flag & BT_LEAF) { /* root leaf */ if (not_fsim_tree) { /* not the FileSet Inode Map tree */ xp_rc = xTree_process_leaf_extents (xtiptr->xtp_ptr, inorecptr, xtiptr->this_Qel, msg_info_ptr, xtiptr->dense_file, desired_action); } xtiptr->xad_ptr = &(xtiptr-> xtp_ptr->xad[xtiptr->xtp_ptr->header.nextindex - 1]); agg_recptr->this_inode.data_size = (int64_t) (offsetXAD(xtiptr->xad_ptr) + lengthXAD(xtiptr->xad_ptr)) * sb_ptr->s_bsize; /* * By definition, a root-leaf is the last leaf * for the inode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -