📄 fsckbmap.c
字号:
/* * Copyright (c) International Business Machines Corp., 2000-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* defines and includes common among the fsck.jfs modules */#include "xfsckint.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck block map info structure pointer * * defined in xchkdsk.c */extern struct fsck_bmap_record *bmap_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */extern char *verbose_msg_ptr;extern char *Vol_Label; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * defined in xchkdsk.c */extern HFILE Dev_IOPort;extern uint32_t Dev_blksize;/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */struct fsck_stree_proc_parms { dmtree_t *buf_tree; int8_t *buf_stree; int8_t *wsp_stree; int32_t nleafs; int32_t l2nleafs; int32_t leafidx; int8_t budmin; int page_level; uint32_t page_ordno; int8_t *lfval_error; int8_t *intval_error;};int ctlpage_rebuild(int8_t);int ctlpage_verify(int8_t);int dmap_pwmap_rebuild(uint32_t *);int dmap_pmap_verify(uint32_t *);int dmap_tree_rebuild(int8_t *);int dmap_tree_verify(int8_t *);int dmappg_rebuild(int8_t *);int dmappg_verify(int8_t *);int init_bmap_info(void);int Ln_tree_rebuild(int, int64_t, struct dmapctl **, int8_t *);int Ln_tree_verify(int, int64_t, struct dmapctl **, int8_t *);int stree_rebuild(struct fsck_stree_proc_parms *, int8_t *);int stree_verify(struct fsck_stree_proc_parms *, int8_t *);int verify_blkall_summary_msgs(void);/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV *//***************************************************************************** * NAME: ctlpage_rebuild * * FUNCTION: Rebuild the control page of the filesystem block map. * * PARAMETERS: * max_buddy - input - the data value in the root of the highest * Lx page in the map. * * RETURNS: * success: FSCK_OK * failure: something else */int ctlpage_rebuild(int8_t max_buddy){ int bcr_rc = FSCK_OK; int32_t highest_active_AG = 0, num_active_AGs = 0, num_inactive_AGs; int64_t avg_free, actAG_free, inactAG_free; int32_t l2nl, n, agidx, index, aglevel, agheight, agwidth, agstart; bcr_rc = mapctl_get(bmap_recptr->bmpctl_agg_fsblk_offset, (void **) &(bmap_recptr->bmpctl_bufptr)); if (bcr_rc == FSCK_OK) { /* swap if on big endian machine */ ujfs_swap_dbmap((struct dbmap *) bmap_recptr->bmpctl_bufptr); bmap_recptr->bmpctl_bufptr->dn_mapsize = bmap_recptr->total_blocks; bmap_recptr->bmpctl_bufptr->dn_nfree = bmap_recptr->free_blocks; bmap_recptr->bmpctl_bufptr->dn_l2nbperpage = agg_recptr->log2_blksperpg; bmap_recptr->bmpctl_bufptr->dn_numag = agg_recptr->num_ag; bmap_recptr->bmpctl_bufptr->dn_maxlevel = BMAPSZTOLEV(agg_recptr->sb_agg_fsblk_length); /* check out the active AGs */ for (agidx = 0; (agidx < MAXAG); agidx++) { if (bmap_recptr->AGActive[agidx]) { highest_active_AG = agidx; num_active_AGs++; } } /* end check out the active AGs */ bmap_recptr->bmpctl_bufptr->dn_maxag = highest_active_AG; num_inactive_AGs = agg_recptr->num_ag - num_active_AGs; inactAG_free = num_inactive_AGs * sb_ptr->s_agsize; actAG_free = bmap_recptr->free_blocks - inactAG_free; avg_free = actAG_free / num_active_AGs; if ((bmap_recptr->bmpctl_bufptr->dn_agpref > highest_active_AG) || (bmap_recptr->bmpctl_bufptr->dn_agfree[bmap_recptr-> bmpctl_bufptr->dn_agpref] < avg_free)) { /* preferred AG is not valid */ if (avg_free == 0) { bmap_recptr->bmpctl_bufptr->dn_agpref = 0; } else { bmap_recptr->bmpctl_bufptr->dn_agpref = -1; for (agidx = 0; ((agidx < MAXAG) && (bmap_recptr->bmpctl_bufptr-> dn_agpref < 0)); agidx++) { if (bmap_recptr->AGFree_tbl[agidx] >= avg_free) { bmap_recptr->bmpctl_bufptr-> dn_agpref = agidx; } } } } aglevel = BMAPSZTOLEV(sb_ptr->s_agsize); l2nl = agg_recptr->log2_blksperag - (L2BPERDMAP + aglevel * L2LPERCTL); agheight = l2nl >> 1; agwidth = 1 << (l2nl - (agheight << 1)); for (index = 5 - agheight, agstart = 0, n = 1; index > 0; index--) { agstart += n; n <<= 2; } bmap_recptr->bmpctl_bufptr->dn_aglevel = aglevel; bmap_recptr->bmpctl_bufptr->dn_agheigth = agheight; bmap_recptr->bmpctl_bufptr->dn_agwidth = agwidth; bmap_recptr->bmpctl_bufptr->dn_agstart = agstart; bmap_recptr->bmpctl_bufptr->dn_agl2size = agg_recptr->log2_blksperag; bmap_recptr->bmpctl_bufptr->dn_agsize = sb_ptr->s_agsize; bmap_recptr->bmpctl_bufptr->dn_maxfreebud = max_buddy; for (agidx = 0; (agidx < MAXAG); agidx++) { /* rebuild the free list */ bmap_recptr->bmpctl_bufptr->dn_agfree[agidx] = bmap_recptr->AGFree_tbl[agidx]; } /* swap if on big endian machine */ ujfs_swap_dbmap(bmap_recptr->bmpctl_bufptr); /* * write the updated control page back onto the device */ bcr_rc = mapctl_put((void *) bmap_recptr->bmpctl_bufptr); } return (bcr_rc);}/***************************************************************************** * NAME: ctlpage_verify * * FUNCTION: Verify the control page of the filesystem block map. * * PARAMETERS: * max_buddy - input - the data value which should be in the root * of the highest Lx page in the map. * * RETURNS: * success: FSCK_OK * failure: something else */int ctlpage_verify(int8_t max_buddy){ int bcv_rc = FSCK_OK; unsigned agidx; int32_t max_level = 0; int32_t highest_active_AG = 0; int32_t l2nl, n, index, aglevel, agheight, agwidth, agstart; bcv_rc = mapctl_get(bmap_recptr->bmpctl_agg_fsblk_offset, (void **) &(bmap_recptr->bmpctl_bufptr)); if (bcv_rc == FSCK_OK) { /* got the control page in the buffer */ /* swap if on big endian machine */ ujfs_swap_dbmap((struct dbmap *) bmap_recptr->bmpctl_bufptr); if (bmap_recptr->bmpctl_bufptr->dn_mapsize != bmap_recptr->total_blocks) { /* bad number of blocks in the aggregate */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCASB); } if (bmap_recptr->bmpctl_bufptr->dn_nfree != bmap_recptr->free_blocks) { /* bad number of free blocks in the aggregate */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCNF); } if (bmap_recptr->bmpctl_bufptr->dn_l2nbperpage != agg_recptr->log2_blksperpg) { /* bad log2( blocks per page ) */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCL2BPP); } if (bmap_recptr->bmpctl_bufptr->dn_numag != agg_recptr->num_ag) { /* bad number of alloc groups */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCNAG); } max_level = BMAPSZTOLEV(agg_recptr->sb_agg_fsblk_length); if (bmap_recptr->bmpctl_bufptr->dn_maxlevel != max_level) { /* bad maximum block map level */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCMXLVL); } for (agidx = 0; (agidx < MAXAG); agidx++) { /* check out the active AGs */ if (bmap_recptr->AGActive[agidx]) { highest_active_AG = agidx; } } /* * format does not include blocks allocated to the bad block inode * when it determines the dn_maxag. Subsequent activity may or * may not have altered dn_maxag based on blocks allocated to the * bad block inode. All we know for sure is that dn_maxag shouldn't * be larger than appropriate for the highest allocated block. */ if (bmap_recptr->bmpctl_bufptr->dn_maxag > highest_active_AG) { /* bad highest active alloc group */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCMAAG); } if (bmap_recptr->bmpctl_bufptr->dn_agpref > highest_active_AG) { /* bad preferred alloc group */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCPAG); } aglevel = BMAPSZTOLEV(sb_ptr->s_agsize); l2nl = agg_recptr->log2_blksperag - (L2BPERDMAP + aglevel * L2LPERCTL); agheight = l2nl >> 1; agwidth = 1 << (l2nl - (agheight << 1)); for (index = 5 - agheight, agstart = 0, n = 1; index > 0; index--) { agstart += n; n <<= 2; } /* end for index */ if (bmap_recptr->bmpctl_bufptr->dn_aglevel != aglevel) { /* bad level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLAG); } if (bmap_recptr->bmpctl_bufptr->dn_agheigth != agheight) { /* bad dmapctl height holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLH); } if (bmap_recptr->bmpctl_bufptr->dn_agwidth != agwidth) { /* bad width at level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLW); } if (bmap_recptr->bmpctl_bufptr->dn_agstart != agstart) { /* bad start idx at level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCSTI); } if (bmap_recptr->bmpctl_bufptr->dn_agl2size != agg_recptr->log2_blksperag) { /* bad log2(fsblks per AG) */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCL2BPAG); } if (bmap_recptr->bmpctl_bufptr->dn_agsize != sb_ptr->s_agsize) { /* bad fsblks per AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCBPAG); } if (bmap_recptr->bmpctl_bufptr->dn_maxfreebud != max_buddy) { /* bad max free buddy system */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCBMXB); } for (agidx = 0; (agidx < MAXAG); agidx++) { /* verify the free list */ if (bmap_recptr->bmpctl_bufptr->dn_agfree[agidx] != bmap_recptr->AGFree_tbl[agidx]) { /* bad free blocks in the AG */ bmap_recptr->ctl_fctl_error = -1; fsck_send_msg(fsck_BMAPCAGNF, agidx); } } } return (bcv_rc);}/***************************************************************************** * NAME: dmap_pwmap_rebuild * * FUNCTION: Rebuild the pmap in the current block map dmap page. * * PARAMETERS: * pmap_freeblks - input - pointer to a variable in which the number * of free blocks described by the dmap page * will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */int dmap_pwmap_rebuild(uint32_t * pmap_freeblks){ int bdpr_rc = FSCK_OK; uint32_t bitmask; int64_t wsp_pagenum; uint32_t wsp_byteoffset; struct fsck_blk_map_page *wsp_page; uint32_t *wsp_bits = NULL; int32_t map_wordidx, word_bitidx; int8_t max_buddy; /* * locate the section of the workspace bit map which corresponds * to this dmap's pmap */ bdpr_rc = blkmap_find_bit(bmap_recptr->dmap_1stblk, &wsp_pagenum, &wsp_byteoffset, &bitmask); if (bdpr_rc == FSCK_OK) { bdpr_rc = blkmap_get_page(wsp_pagenum, &wsp_page); if (bdpr_rc == FSCK_OK) { wsp_bits = (uint32_t *) ((char *) wsp_page + wsp_byteoffset); } } *pmap_freeblks = 0; if (bdpr_rc == FSCK_OK) { for (map_wordidx = 0; (map_wordidx < LPERDMAP); map_wordidx++) { max_buddy = ujfs_maxbuddy((char *) &(wsp_bits[map_wordidx])); bmap_recptr->dmap_wsp_sleafs[map_wordidx] = max_buddy; bmap_recptr->dmap_bufptr->wmap[map_wordidx] = wsp_bits[map_wordidx]; /* * copy the word from workspace to buffer, * into both the working map and the permanent map. */ bmap_recptr->dmap_bufptr->pmap[map_wordidx] = wsp_bits[map_wordidx]; /* * count the free blocks described by the word */ bitmask = 0x80000000u; for (word_bitidx = 0; (word_bitidx < DBWORD); word_bitidx++) { if (!(wsp_bits[map_wordidx] & bitmask)) { /* it's free */ (*pmap_freeblks)++; agg_recptr->free_blocks_in_aggregate++; } else { /* it's allocated */ agg_recptr->blocks_used_in_aggregate++; } /* end else it's allocated */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -