📄 fsckpfs.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 <fcntl.h>#include <string.h>#include <unistd.h>/* defines and includes common among the fsck.jfs modules */#include "xfsckint.h"#include "xchkdsk.h"#include "jfs_byteorder.h"#include "devices.h"#include "utilsubs.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;/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */extern char *Vol_Label;/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */int imapleaf_get(int64_t, xtpage_t **);int open_device_read(const char *);int open_device_rw(const char *);uint32_t checksum(uint8_t *, uint32_t);/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV *//***************************************************************************** * NAME: ait_node_get * * FUNCTION: Read the specified AIT xTree node into the specified buffer * * PARAMETERS: * node_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate, of the xTree node wanted * xtpage_ptr - input - pointer an fsck buffer into which the * xTree node should be read. * * RETURNS: * success: FSCK_OK * failure: something else */int ait_node_get(int64_t node_fsblk_offset, xtpage_t * xtpage_ptr){ int anodg_rc = FSCK_OK; int64_t node_start_byte; uint32_t bytes_read; node_start_byte = node_fsblk_offset * sb_ptr->s_bsize; if ((agg_recptr->ondev_wsp_fsblk_offset != 0) && (node_fsblk_offset > agg_recptr->ondev_wsp_fsblk_offset)) { /* the offset is beyond the range valid for fileset objects */ /* * This case is not caused by an I/O error, but by * invalid data in an inode. Let the caller handle * the consequences. */ anodg_rc = FSCK_BADREADTARGET2; } else { anodg_rc = readwrite_device(node_start_byte, XTPAGE_SIZE, &(bytes_read), (void *) xtpage_ptr, fsck_READ); if (anodg_rc == FSCK_OK) { /* read appears successful */ if (bytes_read < XTPAGE_SIZE) { /* didn't get the minimum number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_NODE1, anodg_rc, fsck_READ, (long long) node_start_byte, XTPAGE_SIZE, bytes_read); anodg_rc = FSCK_FAILED_BADREAD_NODE1; } else { /* swap if on big endian machine */ ujfs_swap_xtpage_t(xtpage_ptr); } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_NODE, anodg_rc, fsck_READ, (long long) node_start_byte, XTPAGE_SIZE, bytes_read); anodg_rc = FSCK_FAILED_READ_NODE; } } return (anodg_rc);}/***************************************************************************** * NAME: ait_node_put * * FUNCTION: Write the specified buffer into the specified AIT xTree node * * PARAMETERS: * node_fsblk_offset - input - offset, in aggregate blocks, to which * the buffer is to be written * xtpage_ptr - input - pointer to the buffer to write * * RETURNS: * success: FSCK_OK * failure: something else */int ait_node_put(int64_t node_fsblk_offset, xtpage_t * xtpage_ptr){ int anodp_rc = FSCK_OK; int64_t node_start_byte; uint32_t bytes_written; node_start_byte = node_fsblk_offset * sb_ptr->s_bsize; ujfs_swap_xtpage_t(xtpage_ptr); anodp_rc = readwrite_device(node_start_byte, PSIZE, &bytes_written, (void *) xtpage_ptr, fsck_WRITE); ujfs_swap_xtpage_t(xtpage_ptr); if (anodp_rc == FSCK_OK) { if (bytes_written != PSIZE) { /* didn't write correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 2); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_BADWRITE_FBLKMP, anodp_rc, fsck_WRITE, (long long) node_start_byte, PSIZE, bytes_written); anodp_rc = FSCK_BADWRITE_FBLKMP; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 3); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_BADWRITE_FBLKMP, anodp_rc, fsck_WRITE, (long long) node_start_byte, PSIZE, bytes_written); anodp_rc = FSCK_BADWRITE_FBLKMP; } /* end else the write was not successful */ return (anodp_rc);}/***************************************************************************** * NAME: ait_special_read_ext1 * * FUNCTION: Reads the first extent of either the Primary or Secondary * Aggregate Inode Table into the fsck inode buffer. * * PARAMETERS: * which_ait - input - { fsck_primary | fsck_secondary } * * NOTES: This routine is used during the early stages of fsck processing * when the normal mechanisms for reading inodes have not yet been * established. * * This routine may also be used later in fsck processing as a fast * read routine for the inodes in the first extent of the AIT. * * RETURNS: * success: FSCK_OK * failure: something else */int ait_special_read_ext1(int which_ait){ int aree_rc = FSCK_OK; int intermed_rc = FSCK_OK; int64_t offset_1stext; aree_rc = inodes_flush(); /* * calculate the byte offset of the first extent */ if ((which_ait == fsck_primary)) { offset_1stext = AITBL_OFF; } else { /* must be secondary */ offset_1stext = addressPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; } if (agg_recptr->ino_buf_agg_offset != offset_1stext) { /* we don't already have the one we want */ intermed_rc = readwrite_device(offset_1stext, INODE_IO_BUFSIZE, &(agg_recptr->ino_buf_data_len), (void *) agg_recptr->ino_buf_ptr, fsck_READ); if (intermed_rc != FSCK_OK) { /* didn't get anything */ aree_rc = FSCK_CANTREADAITEXT1; fsck_send_msg(fsck_CANTREADAITEXT1, fsck_ref_msg(which_ait)); } else { /* got something */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) agg_recptr-> ino_buf_ptr, GET, sb_ptr->s_flag); agg_recptr->ino_for_aggregate = -1; agg_recptr->ino_which_it = which_ait; agg_recptr->ino_buf_1st_ino = 0; agg_recptr->ino_fsnum = 0; agg_recptr->ino_buf_agg_offset = offset_1stext; PXDaddress(&(agg_recptr->ino_ixpxd), offset_1stext / sb_ptr->s_bsize); PXDlength(&(agg_recptr->ino_ixpxd), INODE_EXTENT_SIZE / sb_ptr->s_bsize); if (agg_recptr->ino_buf_data_len < INODE_EXTENT_SIZE) { /* didn't get enough */ aree_rc = FSCK_CANTREADAITEXT1; fsck_send_msg(fsck_CANTREADEAITEXT1, fsck_ref_msg(which_ait)); } } } return (aree_rc);}/***************************************************************************** * NAME: blkmap_find_bit * * FUNCTION: Calculate the position, in the fsck workspace block map, * of the bit representing the given aggregate block. * * PARAMETERS: * blk_number - input - ordinal number of the aggregate block whose * bit is to be located * page_number - input - pointer to a variable in which to return * the ordinal number of the page, in the fsck * workspace block map, containing the bit * for the given block * byte_offset - input - pointer to a variable in which to return * the ordinal number of the byte, in page_number * page, containing the bit for the given block * mask_ptr - input - pointer to a variable in which to return * a mask to apply to the byte at byte_offset * in order to reference the bit for the given * block * * RETURNS: * success: FSCK_OK * failure: something else */int blkmap_find_bit(int64_t blk_number, int64_t * page_number, uint32_t * byte_offset, uint32_t * mask_ptr){ int bfb_rc = FSCK_OK; uint64_t remainder; uint32_t bit_position; *page_number = blk_number >> log2BITSPERPAGE; remainder = blk_number - ((*page_number) << log2BITSPERPAGE); *byte_offset = (remainder >> log2BITSPERDWORD) * BYTESPERDWORD; bit_position = remainder - ((*byte_offset) << log2BITSPERBYTE); *mask_ptr = 0x80000000u >> bit_position; return (bfb_rc);}/***************************************************************************** * NAME: blkmap_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current block map buffer has been updated since * the most recent read operation, write the buffer contents to * the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int blkmap_flush(){ int bmpf_rc = FSCK_OK; uint32_t bytes_written; struct fsck_blk_map_page *fsck_bmpt_ptr; if (agg_recptr->blkmp_buf_write) { /* buffer has been updated since most recent write */ /* swap if on big endian machine */ fsck_bmpt_ptr = agg_recptr->blkmp_buf_ptr; swap_multiple(ujfs_swap_fsck_blk_map_page, fsck_bmpt_ptr, 4); bmpf_rc = readwrite_device(agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, &bytes_written, (void *) agg_recptr->blkmp_buf_ptr, fsck_WRITE); fsck_bmpt_ptr = agg_recptr->blkmp_buf_ptr; swap_multiple(ujfs_swap_fsck_blk_map_page, fsck_bmpt_ptr, 4); if (bmpf_rc == FSCK_OK) { if (bytes_written == agg_recptr->blkmp_buf_data_len) { /* buffer has been written * to the device and won't need to be * written again unless/until the * buffer contents have been altered. */ agg_recptr->blkmp_buf_write = 0; } else { /* didn't write correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 2); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_FBMAP_BADFLUSH, bmpf_rc, fsck_WRITE, (long long) agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, bytes_written); bmpf_rc = FSCK_FAILED_FBMAP_BADFLUSH; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 3); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_FBMAP_FLUSH, bmpf_rc, fsck_WRITE, (long long) agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, bytes_written); bmpf_rc = FSCK_FAILED_FBMAP_FLUSH; } } return (bmpf_rc);}/***************************************************************************** * NAME: blkmap_get_ctl_page * * FUNCTION: If the current fsck session has write access to the aggregate, * write the contents of the given buffer over the current fsck * fsck workspace block map control page on the device. * * PARAMETERS: * blk_ctlptr - input - pointer to the buffer into the current fsck * workspace block map control page should be read. * * RETURNS: * success: FSCK_OK * failure: something else */int blkmap_get_ctl_page(struct fsck_blk_map_hdr *blk_ctlptr){ int bmgcp_rc = FSCK_OK; uint32_t bytes_read;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -