📄 fsckwsp.c
字号:
* PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * is_EA - input - !0 => the extent contains an inode's EA * 0 => the extent contains something else * msg_info_ptr - input - information needed to issue messages for this * extent. If NULL, no messages will be issued * ino_recptr - input - pointer to the fsck inode record describing the * inode to which this extent is allocated * * RETURNS: * success: FSCK_OK * failure: something else */int extent_record_dupchk(int64_t first_block, int64_t last_block, int8_t range_adj, int8_t is_EA, int8_t is_ACL, struct fsck_ino_msg_info *msg_info_ptr, struct fsck_inode_record *ino_recptr){ int erd_rc = FSCK_OK; int dups_detected = 0; struct dupall_blkrec *this_blkrec; if (range_adj) { /* the xad described an invalid range */ fsck_send_msg(fsck_BADBLKNO, fsck_ref_msg(msg_info_ptr->msg_dxdtyp), fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * Look for duplicate blocks already detected for this extent */ while (first_block <= last_block) { this_blkrec = dupall_find_blkrec(first_block, last_block); if (!this_blkrec) break; /* * If this record goes beyond the extent, we need to split it. */ if ((this_blkrec->first_blk < first_block) || (this_blkrec->last_blk > last_block)) { erd_rc = blkall_split_blkrec(this_blkrec, first_block, last_block); if (erd_rc) return erd_rc; /* * Check if the split caused the current record to * precede the extent we are processing */ if (this_blkrec->first_blk < first_block) continue; } /* * Take care of the blocks preceding this record (if any) */ if (first_block < this_blkrec->first_blk) { erd_rc = blkall_increment_owners(first_block, this_blkrec->first_blk - 1, msg_info_ptr); if (erd_rc < 0) return erd_rc; else if (erd_rc) dups_detected = 1; } this_blkrec->owner_count++; first_block = this_blkrec->last_blk + 1; } /* * Take care of any remaining blocks */ if (first_block <= last_block) { erd_rc = blkall_increment_owners(first_block, last_block, msg_info_ptr); if (erd_rc < 0) return erd_rc; else if (erd_rc) dups_detected = 1; } if (dups_detected && msg_info_ptr) { /* claims at least 1 multiply allocated block */ ino_recptr->involved_in_dups = 1; fsck_send_msg(fsck_DUPBLKREFS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); if (!(inode_is_metadata(ino_recptr))) { agg_recptr->corrections_needed = 1; if (is_EA) ino_recptr->clr_ea_fld = 1; else if (is_ACL) ino_recptr->clr_acl_fld = 1; else ino_recptr->selected_to_rls = 1; } } return (FSCK_OK);}/***************************************************************************** * NAME: extent_record * * FUNCTION: Record that each of the blocks in the given extent is allocated * to some inode. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * * NOTES: Originally, this was intended to be a streamlined version of * extent_record_dupchk, called only when the extent was known to * not be multilply allocated. However, it really wasn't any more * efficient, so its simpler to just call extent_record_dupchk here. * * RETURNS: * success: FSCK_OK * failure: something else */int extent_record(int64_t first_block, int64_t last_block){ return extent_record_dupchk(first_block, last_block, 0, 0, 0, 0, 0);}/***************************************************************************** * NAME: extent_unrecord * * FUNCTION: Decrement, in the fsck workspace block record, the owner count * for each block in the given extent. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * * NOTES: Under certain circumstances, it is necessary to back out the record * of an inode's ownership the recording of some extent already verified * valid. * * This function could be accomplished using other routines which * include extent validation code, but, for performance reasons, * this streamlined routine exists to minimize processing time. * * Examples of these circumstances include: * o Storage allocated for an inode's EA is valid, but the B+Tree * rooted in the inode is structurally corrupt. Then the portions * of the tree which were recorded before the corruption was detected * were backed out using routines which include validation code, and * finally this routine is called to 'unrecord' the storage allocated * for the EA. * * o The B+Tree rooted in an inode was verified structurally correct, * but the di_nblocks in the inode was found to be inconsistent with * the tree. In this case we assume the tree to be corrupt and * back it out of the fsck workspace block map immediately. This * routine would be used for that purpose since the tree has already * been verified structurally correct. * * o An inode has been found to be valid, but claims ownership of at * least one block claimed by another inode. At least one of the * inodes is actually damaged. The user has given permission to * delete this inode, and so we need to decrement the number of * owners for each block allocated to this inode. This routine * would be used for that purpose since the tree has already been * verified structurally correct. * * * RETURNS: * success: FSCK_OK * failure: something else */int extent_unrecord(int64_t first_block, int64_t last_block){ int eu_rc = FSCK_OK; struct dupall_blkrec *this_blkrec; while (first_block <= last_block) { this_blkrec = dupall_find_blkrec(first_block, last_block); if (!this_blkrec) break; /* * If this record goes beyond the extent, we need to split it. */ if ((this_blkrec->first_blk < first_block) || (this_blkrec->last_blk > last_block)) { eu_rc = blkall_split_blkrec(this_blkrec, first_block, last_block); if (eu_rc) return eu_rc; /* * Check if the split caused the current record to * precede the extent we are processing */ if (this_blkrec->first_blk < first_block) continue; } /* * Take care of the blocks preceding this record (if any) */ if (first_block < this_blkrec->first_blk) { eu_rc = blkall_mark_free(first_block, this_blkrec->first_blk - 1); if (eu_rc) return eu_rc; } this_blkrec->owner_count--; if (this_blkrec->owner_count == 1) { /* No longer a duplicate */ if (!this_blkrec->first_ref_resolved) agg_recptr->unresolved_1stref_count--; agg_recptr->dup_block_count--; dupall_extract_blkrec(this_blkrec); } first_block = this_blkrec->last_blk + 1; } /* * Take care of any remaining blocks */ if (first_block <= last_block) eu_rc = blkall_mark_free(first_block, last_block); return (eu_rc);}/**************************************************************************** * NAME: fsblk_count_avail * * FUNCTION: Count the number of contiguous aggregate blocks which are * available, according to the fsck workspace block map, starting * with the given (available) aggregate block. * * PARAMETERS: * wspbits - input - pointer to a page in the fsck workspace block map * wordidx - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * some particular aggregate block. * at routine entry: the block represented is the available * block with which counting should start * at routine exit: the block represented is the 1st block * AFTER the last block counted * bitidx - input - the ordinal number, in the word identified by wordidx, * of the bit representing some particular aggregate block. * at routine entry: the block represented is the available * block with which counting should start * at routine exit: the block represented is the 1st block * AFTER the last block counted * num_wanted - input - number of blocks wanted. (i.e., when to stop counting * even if the run of contiguous, available blocks has * not ended. * num_avail - input - number of contiguous, available blocks counted starting * with the block described by wspbits, wordidx, and * bitidx when the routine was entered. * * RETURNS: * success: FSCK_OK * failure: something else */int fsblk_count_avail(uint32_t * wspbits, int32_t * wordidx, int32_t * bitidx, int32_t num_wanted, int32_t * num_avail){ int fbca_rc = FSCK_OK; int done_counting = 0; uint32_t bitmask; *num_avail = 0; while (((*wordidx) < LPERDMAP) && (!done_counting)) { bitmask = 0x80000000u; bitmask = bitmask >> (*bitidx); while (((*bitidx) < DBWORD) && (!done_counting)) { if (wspbits[*wordidx] & bitmask) { /* this one's not available */ done_counting = -1; } else { /* this one's available */ (*num_avail)++; if ((*num_avail) == num_wanted) { done_counting = -1; } else { bitmask = bitmask >> 1; } (*bitidx)++; } } /* end while bitidx */ if (!done_counting) { *bitidx = 0; *wordidx += 1; } } return (fbca_rc);}/**************************************************************************** * NAME: fsblk_next_avail * * FUNCTION: Find the next available aggregate block, according to the * fsck workspace block map, starting with the given block. * * PARAMETERS: * wspbits - input - pointer to a page in the fsck workspace block map * startword - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * the aggregate block at which to start searching * startbit - input - the ordinal number, in the word identified by wordidx, * of the bit representing the aggregate block at which * to start searching * foundword - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * the available aggregate block found, if any * foundbit - input - the ordinal number, in the word identified by wordidx, * of the bit representing the available aggregate block, * if any * block_found - input - pointer to a variable in which the search results are * returned. !0 => an available block was found in the * given page at/after the specified start * 0 => no available block was found in the * given page at/after the specified start * * RETURNS: * success: FSCK_OK * failure: something else */int fsblk_next_avail(uint32_t * wspbits, int32_t startword, int32_t startbit, int32_t * foundword, int32_t * foundbit, int *block_found){ int fbna_rc = FSCK_OK; int32_t wordidx, bitidx, firstbit; uint32_t bitmask; uint32_t mask_all_on = 0xFFFFFFFFu; *block_found = 0; firstbit = startbit; for (wordidx = startword; ((wordidx < LPERDMAP) && (!(*block_found))); wordidx++) { if (wspbits[wordidx] != mask_all_on) { /* a zero in this map word */ bitmask = 0x80000000u; bitmask = bitmask >> firstbit; for (bitidx = firstbit; ((bitidx < DBWORD) && (!(*block_found))); bitidx++) { if (!(wspbits[wordidx] & bitmask)) { /* it's available */ *foundword = wordidx; *foundbit = bitidx; *block_found = -1; } else { /* it's in use */ bitmask = bitmask >> 1; } } } firstbit = 0; } return (fbna_rc);}/**************************************************************************** * NAME: fsck_alloc_fsblks * * FUNCTION: Allocate storage in the aggregate. * * PARAMETERS: * blocks_wanted - input - the number of contiguous blocks of storage * wanted * blocks - input - pointer to a variable in which the ordinal * number of the first block allocated will be * returned (or 0 if the storage cannot be * allocated) * * NOTES: o This routine is only called when fsck has write access to the * aggregate. * * o This routine can not be called before the end of Phase 1 (that is, * not before all block allocations existing in the aggregate have * been recorded in the fsck workspace block map). * * o The optimum time to call this routine is after all inode repairs * have been performed (a step performed in Phase 6) since aggregates * blocks may be made available by releasing inodes and/or clearing * extents allocated for EAs. * * o This routine can not be called after the beginning of Phase 8 (that * is, not after fsck begins to rebuild the aggregate block map from * the information in the fsck workspace block map). * * o Currently, this routine is only called * - during inode reconnect processing (the last step in Phase 6) to * create new internal nodes for the directory to which the inode(s) * is(are) reconnected. * - during replication of the Aggregate Inode Map (Phase 7) when * building the tree for the fileset AIM inode. * * RETURNS: * success: FSCK_OK * failure: something else */int fsck_alloc_fsblks(int32_t blocks_wanted, int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -