📄 fsckwsp.c
字号:
/* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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 */#include <config.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <errno.h>/* defines and includes common among the fsck.jfs modules */#include "xfsckint.h"#include "devices.h"#include "message.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 and pointer * * defined in xchkdsk.c */extern struct fsck_bmap_record *bmap_recptr;/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */extern struct tm *fsck_DateTime;extern char *Vol_Label;extern UniChar uni_LSFN_NAME[];extern UniChar uni_lsfn_name[];/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Unicode path strings information. * * values are assigned when the fsck aggregate record is initialized. * accessed via addresses in the fack aggregate record. */extern UniChar uni_LSFN_NAME[11];extern UniChar uni_lsfn_name[11];/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */int alloc_wsp_extent(uint32_t, int);void dupall_extract_blkrec(struct dupall_blkrec *);struct dupall_blkrec *dupall_find_blkrec(int64_t, int64_t);struct dupall_blkrec *dupall_get_blkrec(void);int dupall_insert_blkrec(int64_t, int64_t, struct dupall_blkrec **);int establish_wsp_block_map(void);int extent_1stref_chk(int64_t, int64_t, int8_t, int8_t, struct fsck_ino_msg_info *, struct fsck_inode_record *);int extent_record_dupchk(int64_t, int64_t, int8_t, int8_t, int8_t, struct fsck_ino_msg_info *, struct fsck_inode_record *);int fsblk_count_avail(uint32_t *, int32_t *, int32_t *, int32_t, int32_t *);int fsblk_next_avail(uint32_t *, int32_t, int32_t, int32_t *, int32_t *, int *);int inorec_agg_search(uint32_t, struct fsck_inode_record **);int inorec_agg_search_insert(uint32_t, struct fsck_inode_record **);int inorec_fs_search(uint32_t, struct fsck_inode_record **);int inorec_fs_search_insert(uint32_t, struct fsck_inode_record **);void locate_inode(uint32_t, int32_t *, int32_t *, int32_t *);/* * The following are used for reporting storage related errors */extern int wsp_dynstg_action;extern int wsp_dynstg_object;/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV *//**************************************************************************** * NAME: alloc_vlarge_buffer * * FUNCTION: Allocate the very large multi-use buffer * * * PARAMETERS: none * * NOTES: This must be called before logredo since the purpose * is to ensure a buffer which has been obtained via * malloc(), whether we're called from the command line * or during autocheck. * * RETURNS: * success: FSCK_OK * failure: something else */int alloc_vlarge_buffer(){ int avb_rc = FSCK_OK; if ((agg_recptr->vlarge_buf_ptr = (char *) malloc(VLARGE_BUFSIZE)) != NULL) { agg_recptr->vlarge_buf_length = VLARGE_BUFSIZE; agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; } else { avb_rc = ENOMEM; fsck_send_msg(MSG_OSO_INSUFF_MEMORY); } return (avb_rc);}/**************************************************************************** * NAME: alloc_wrksp * * FUNCTION: Allocates and initializes (to guarantee the storage is backed) * dynamic storage for the caller. * * PARAMETERS: * length - input - the number of bytes of storage which are needed * dynstg_object - input - a constant (see xfsck.h) identifying the purpose * for which the storage is needed (Used in error * message if the request cannot be satisfied. * addr_wrksp_ptr - input - the address of a variable in which this routine * will return the address of the dynamic storage * allocated for the caller * * RETURNS: * success: FSCK_OK * failure: something else */int alloc_wrksp(uint32_t length, int dynstg_object, int for_logredo, void **addr_wrksp_ptr){ int awsp_rc = FSCK_OK; char *wsp_ptr = NULL; struct wsp_ext_rec *this_fer; uint32_t bytes_avail; uint32_t min_length; *addr_wrksp_ptr = NULL; /* round up to an 8 byte boundary */ min_length = ((length + 7) / 8) * 8; while ((wsp_ptr == NULL) && (awsp_rc == FSCK_OK)) { this_fer = agg_recptr->wsp_extent_list; while ((this_fer != NULL) && (wsp_ptr == NULL) && (awsp_rc == FSCK_OK)) { if ((for_logredo) && !(this_fer->for_logredo)) { /* * requestor is logredo and * fer describes an allocation not for logredo */ this_fer = this_fer->next; } else { /* this fer describes an eligible allocation */ bytes_avail = this_fer->extent_length - this_fer->last_byte_used; if (bytes_avail >= min_length) { /* there's enough here */ wsp_ptr = this_fer->extent_addr + this_fer->last_byte_used + 1; this_fer->last_byte_used += min_length; } else { /* try the next fer */ this_fer = this_fer->next; } } } if ((awsp_rc == FSCK_OK) && (wsp_ptr == NULL)) { /* * nothing fatal but we didn't find the * storage yet */ /* * will allocate some number of memory segments * and put the fer describing it on the beginning * of the list. */ awsp_rc = alloc_wsp_extent(min_length, for_logredo); } } if (awsp_rc == FSCK_OK) { /* we allocated virtual storage */ /* * now initialize the storage */ memset((void *) wsp_ptr, 0, length); /* set the return value */ *addr_wrksp_ptr = (void *) wsp_ptr; } return (awsp_rc);}/**************************************************************************** * NAME: alloc_wsp_extent * * FUNCTION: Extend the workspace * * For optimum use of storage, we'll allocate a whole segment. * Then the alloc_wrksp routine portions it out as needed. * * PARAMETERS: * minimum_length - input - minimum number of bytes of contiguous storage * needed * * RETURNS: * success: FSCK_OK * failure: something else */int alloc_wsp_extent(uint32_t minimum_length, int for_logredo){ int awe_rc = FSCK_OK; struct wsp_ext_rec *new_fer; int32_t extent_length = MEMSEGSIZE; char *extent_addr = NULL; int8_t from_high_memory = 0; /* * the user has specified the minimum needed. We must allocate * at least 16 more than that because we're going to use 16 bytes * at the beginning to keep track of it. */ while (extent_length < (minimum_length + 16)) { extent_length += MEMSEGSIZE; } wsp_dynstg_object = dynstg_iobufs; wsp_dynstg_action = dynstg_allocation; extent_addr = (char *) malloc(extent_length); if (extent_addr == NULL) { /* allocation failure */ awe_rc = FSCK_FAILED_DYNSTG_EXHAUST4; if (!for_logredo) { fsck_send_msg(fsck_EXHDYNSTG, wsp_dynstg_action, dynstg_wspext); } } else { /* got the dynamic storage */ /* * use the first 16 bytes of it to keep track of it */ new_fer = (struct wsp_ext_rec *) extent_addr; new_fer->extent_length = extent_length; new_fer->for_logredo = for_logredo; new_fer->from_high_memory = from_high_memory; new_fer->extent_addr = extent_addr; new_fer->last_byte_used = sizeof (struct wsp_ext_rec) - 1; new_fer->next = agg_recptr->wsp_extent_list; agg_recptr->wsp_extent_list = new_fer; } return (awe_rc);}/**************************************************************************** * NAME: blkall_mark_free * * FUNCTION: Adjust the fsck workspace to show the indicated blocks are no * longer used. * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * last_block - input - ordinal number of the last filesystem block * whose owner count is to be adjusted. * * RETURNS: * success: FSCK_OK * failure: something else * * NOTE: * This could be written to be more efficient, but it's a big * improvement over how it used to be. */int blkall_mark_free(int64_t first_block, int64_t last_block){ int64_t blk_num; int ddo_rc = FSCK_OK; int64_t page_num; int64_t last_page_num = -1; uint32_t word_offset; uint32_t bit_mask; struct fsck_blk_map_page *this_page; uint32_t *this_word; for (blk_num = first_block; blk_num <= last_block; blk_num++) { blkmap_find_bit(blk_num, &page_num, &word_offset, &bit_mask); if (page_num != last_page_num) { if (last_page_num != -1) blkmap_put_page(last_page_num); ddo_rc = blkmap_get_page(page_num, &this_page); if (ddo_rc) return ddo_rc; last_page_num = page_num; } this_word = (uint32_t *) ((char *) this_page + word_offset); /* mark it not allocated */ (*this_word) &= ~bit_mask; } if (last_page_num != -1) blkmap_put_page(last_page_num); return (FSCK_OK);}/**************************************************************************** * NAME: blkall_increment_owners * * FUNCTION: Adjust the fsck workspace to show one more owner for the * indicated block. * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * last_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * msg_info_ptr - input - information needed to issue messages for this * extent. If NULL, no messages will be issued * * RETURNS: * success: 0, or 1 if multiply-allocated blocks found * failure: something less than 0 */int blkall_increment_owners(int64_t first_block, int64_t last_block, struct fsck_ino_msg_info *msg_info_ptr){ int dio_rc; int64_t blk_num; int64_t page_num; int64_t last_page_num = -1; uint32_t word_offset; uint32_t bit_mask; struct fsck_blk_map_page *this_page; uint32_t *this_word; int is_a_dup = 0; int64_t first_in_dup_range = 0; int32_t size_of_dup_range = 0; for (blk_num = first_block; blk_num <= last_block; blk_num++) { blkmap_find_bit(blk_num, &page_num, &word_offset, &bit_mask); if (page_num != last_page_num) { if (last_page_num != -1) blkmap_put_page(last_page_num); dio_rc = blkmap_get_page(page_num, &this_page); if (dio_rc) return dio_rc; last_page_num = page_num; } this_word = (uint32_t *) ((char *) this_page + word_offset); if (((*this_word) & bit_mask) != bit_mask) { /* * not allocated yet */ /* mark it allocated */ (*this_word) |= bit_mask; /* Record previously found duplicate range */ if (size_of_dup_range) { if (msg_info_ptr) fsck_send_msg(fsck_DUPBLKREF, size_of_dup_range, (long long) first_in_dup_range, fsck_ref_msg(msg_info_ptr->msg_inotyp),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -