📄 fsckpfs.c
字号:
* invalid data in an inode. Let the caller handle * the consequences. */ dnodg_rc = FSCK_BADREADTARGET; } else if ((dnode_start_byte >= agg_recptr->dnode_agg_offset) && (dnode_end_byte <= (agg_recptr->dnode_agg_offset + agg_recptr->dnode_buf_data_len))) { /* * the target dir node is already in * the buffer */ dtp = *addr_dtpage_ptr = (dtpage_t *) (agg_recptr->dnode_buf_ptr + dnode_start_byte - agg_recptr->dnode_agg_offset); /* swap if on big endian machine */ if (!(dtp->header.flag & BT_SWAPPED)) { ujfs_swap_dtpage_t(dtp, sb_ptr->s_flag); dtp->header.flag |= BT_SWAPPED; } } else { /* else we'll have to read it from the disk */ agg_recptr->dnode_agg_offset = dnode_start_byte; dnodg_rc = readwrite_device(agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, &(agg_recptr->dnode_buf_data_len), (void *) agg_recptr->dnode_buf_ptr, fsck_READ); if (dnodg_rc == FSCK_OK) { /* read appears successful */ if (agg_recptr->dnode_buf_data_len >= dnode_length) { /* * we may not have gotten all we asked for, * but we got enough to cover the dir node * we were after */ dtp = *addr_dtpage_ptr = (dtpage_t *) agg_recptr->dnode_buf_ptr; /* swap if on big endian machine */ ujfs_swap_dtpage_t(dtp, sb_ptr->s_flag); dtp->header.flag |= BT_SWAPPED; } else { /* * 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_DNODE, dnodg_rc, fsck_READ, (long long) agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, agg_recptr->dnode_buf_data_len); dnodg_rc = FSCK_FAILED_BADREAD_DNODE; } } 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_DNODE, dnodg_rc, fsck_READ, (long long) agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, agg_recptr->dnode_buf_data_len); dnodg_rc = FSCK_FAILED_READ_DNODE; } } return (dnodg_rc);}/***************************************************************************** * NAME: ea_get * * FUNCTION: Read the specified Extended Attributes data (ea) into * the specified buffer. * * PARAMETERS: * ea_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate of the ea to read * ea_byte_length - input - length, in bytes, of the ea to read * eabuf_ptr - input - the address (in dynamic storage) of the * buffer into which to read the ea * eabuf_length - input - pointer to a variable in which contains * the length of the buffer at eabuf_ptr * ea_data_length - input - pointer to a variable in which to return * the number of bytes actually read from the * device * ea_agg_offset - input - pointer to a variable in which to return * the offset, in bytes, into the aggregate * of the ea to read * * RETURNS: * success: FSCK_OK * failure: something else */int ea_get(int64_t ea_fsblk_offset, uint32_t ea_byte_length, char *eabuf_ptr, uint32_t * eabuf_length, uint32_t * ea_data_length, int64_t * ea_agg_offset){ int ea_rc = FSCK_OK; int64_t start_byte; start_byte = ea_fsblk_offset * sb_ptr->s_bsize; ea_rc = readwrite_device(start_byte, ea_byte_length, ea_data_length, (void *) eabuf_ptr, fsck_READ); /* swap if on big endian machine, currently unused */ if (ea_rc == FSCK_OK) { /* read appears successful */ *ea_agg_offset = start_byte; if ((*ea_data_length) < ea_byte_length) { /* we didn't get enough */ *ea_agg_offset = 0; *ea_data_length = 0; ea_rc = FSCK_BADEADESCRIPTOR; } } else { /* bad return code from read */ ea_rc = FSCK_CANTREADEA; } return (ea_rc);}/***************************************************************************** * NAME: fscklog_put_buffer * * FUNCTION: If the current fsck session has write access to the aggregate, * and if the in-aggregate fsck log is not full, write the * contents of the current fscklog buffer into the in-aggregate * fsck log. * * PARAMETERS: none * * NOTES: o Unlike most _put_ routines in this module, _buffer * actually writes to the device. This is done because the fsck * log contains information which provides crucial serviceability * should the fsck session be interrupted. * * o Errors here are recorded in the control page of the fsck * in-aggregate workspace but never affect other fsck processing. * * RETURNS: * success: FSCK_OK * failure: something else */int fscklog_put_buffer(){ int flpb_rc = FSCK_OK; int io_rc = FSCK_OK; uint32_t bytes_written = 0; uint32_t log_bytes_left; int32_t num_log_errors; struct fscklog_error *log_error_recptr; if ((!agg_recptr->fscklog_full) && (agg_recptr->processing_readwrite)) { /* have write access */ /* swap if on big endian machine in proper format */ io_rc = readwrite_device(agg_recptr->fscklog_agg_offset, agg_recptr->fscklog_buf_length, &bytes_written, (void *) agg_recptr->fscklog_buf_ptr, fsck_WRITE); if ((io_rc != FSCK_OK) || (bytes_written != (uint32_t) agg_recptr->fscklog_buf_length)) { /* * write failed or didn't write correct * number of bytes */ /* This prevents infinite recursion */ agg_recptr->fscklog_full = 1; if (agg_recptr->blkmp_ctlptr) { num_log_errors = agg_recptr->blkmp_ctlptr->hdr. num_logwrite_errors; if (num_log_errors < 120) { log_error_recptr = &(agg_recptr->blkmp_ctlptr->hdr. logerr[num_log_errors]); log_error_recptr->err_offset = agg_recptr->fscklog_agg_offset; log_error_recptr->bytes_written = bytes_written; log_error_recptr->io_retcode = io_rc; } agg_recptr->blkmp_ctlptr->hdr. num_logwrite_errors += 1; } /* * message to debugger * * N.B. This is NOT a fatal condition! */ fsck_send_msg(fsck_ERRONLOG, FSCK_BADWRITE_FSCKLOG, io_rc, fsck_WRITE, (long long) agg_recptr->fscklog_agg_offset, agg_recptr->fscklog_buf_length, bytes_written); } } /* * We want to reset the buffer no matter what. * It is useful to refill the buffer even if logging is not * active because it may provide diagnostic information in * a dump. */ agg_recptr->fscklog_agg_offset += agg_recptr->fscklog_buf_length; agg_recptr->fscklog_log_offset += agg_recptr->fscklog_buf_length; agg_recptr->fscklog_buf_data_len = 0; log_bytes_left = (agg_recptr->ondev_fscklog_byte_length / 2) - agg_recptr->fscklog_log_offset; if (log_bytes_left < agg_recptr->fscklog_buf_length) { /* * can't fit another buffer full * into the log */ if (!agg_recptr->initializing_fscklog) { /* this is a false * condition if doing log initialization */ agg_recptr->fscklog_full = -1; agg_recptr->blkmp_ctlptr->hdr.fscklog_full = -1; } } return (flpb_rc);}/***************************************************************************** * NAME: iag_get * * FUNCTION: Read the requested iag into and/or locate the requested iag * in the fsck iag buffer. * * PARAMETERS: * is_aggregate - input - 0 => the iag is owned by the fileset * !0 => the iag is owned by the aggregate * which_it - input - ordinal number of the aggregate inode * representing the inode table to which the * iag belongs. * which_ait - input - the aggregate inode table { fsck_primary | * fsck_secondary } containing the version of * which_it to use for this operation * iag_num - input - ordinal number of the iag needed * addr_iag_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the * requested iag. * * RETURNS: * success: FSCK_OK * failure: something else */int iag_get(int is_aggregate, int which_it, int which_ait, int32_t iag_num, struct iag **addr_iag_ptr){ int iagg_rc = FSCK_OK; int64_t imap_logical_block, extent_offset; int64_t offset_in_extent = 0; struct dinode *imap_inoptr; xad_t *xad_ptr; int8_t offset_found; int which_agg_inode = 0; *addr_iag_ptr = NULL; if ((agg_recptr->iag_buf_1st_inode == (iag_num << L2INOSPERIAG)) && (agg_recptr->iag_for_aggregate == is_aggregate) && (agg_recptr->iag_which_it == which_it)) { /* * the target iag is already in the buffer */ *addr_iag_ptr = (struct iag *) agg_recptr->iag_buf_ptr; goto iagg_exit; } /* need to get the iag */ /* perform any pending writes */ iagg_rc = iags_flush(); if (iagg_rc != FSCK_OK) goto iagg_exit; /* flush worked ok */ if (is_aggregate) { /* this is an IAG describing aggregate inodes */ if (iag_num < agg_recptr->agg_imap.num_iags) { /* in bounds */ which_agg_inode = AGGREGATE_I; iagg_rc = ait_special_read_ext1(which_ait); if (iagg_rc != FSCK_OK) { /* read ait failed */ report_readait_error(iagg_rc, FSCK_FAILED_CANTREADAITEXTH, which_ait); iagg_rc = FSCK_FAILED_CANTREADAITEXTH; } } else { /* invalid request */ iagg_rc = FSCK_IAGNOOOAGGBOUNDS; } } else { /* an IAG describing fileset inodes */ if (iag_num < agg_recptr->fset_imap.num_iags) { /* in bounds */ which_agg_inode = FILESYSTEM_I; iagg_rc = ait_special_read_ext1(which_ait); if (iagg_rc != FSCK_OK) { /* read ait failed */ report_readait_error(iagg_rc, FSCK_FAILED_CANTREADAITEXTK, which_ait); iagg_rc = FSCK_FAILED_CANTREADAITEXTK; } } else { /* invalid request */ iagg_rc = FSCK_IAGNOOOFSETBOUNDS; } } if (iagg_rc != FSCK_OK) goto iagg_exit; /* got the extent */ imap_inoptr = (struct dinode *)(agg_recptr->ino_buf_ptr + (which_agg_inode * sizeof (struct dinode))); imap_logical_block = IAGTOLBLK(iag_num, agg_recptr->log2_blksperpg); iagg_rc = xTree_search(imap_inoptr, imap_logical_block, &xad_ptr, &offset_found); if (iagg_rc != FSCK_OK) goto iagg_exit; /* nothing extraordinary happened */ if (!offset_found) { iagg_rc = FSCK_INTERNAL_ERROR_50; } else { /* we have the xad which describes the iag */ extent_offset = offsetXAD(xad_ptr); if (extent_offset != imap_logical_block) { offset_in_extent = imap_logical_block - extent_offset; } agg_recptr->iag_agg_offset = sb_ptr->s_bsize * (addressXAD(xad_ptr) + offset_in_extent); iagg_rc = readwrite_device(agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, &(agg_recptr->iag_buf_data_len), (void *) agg_recptr->iag_buf_ptr, fsck_READ); if (iagg_rc == FSCK_OK) { /* got the iag */ /* swap if on big endian machine */ ujfs_swap_iag((struct iag *)agg_recptr->iag_buf_ptr); agg_recptr->iag_buf_1st_inode = iag_num << L2INOSPERIAG; agg_recptr->iag_fsnum = imap_inoptr->di_fileset; agg_recptr->iag_for_aggregate = is_aggregate; agg_recptr->iag_which_it = which_it; *addr_iag_ptr = (struct iag *)agg_recptr->iag_buf_ptr; } else { /* * 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_IAG, iagg_rc, fsck_READ, (long long)agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, agg_recptr->iag_buf_data_len); iagg_rc = FSCK_FAILED_READ_IAG; } } iagg_exit: return (iagg_rc);}/***************************************************************************** * NAME: iag_get_first * * FUNCTION: Read the first iag in the specified inode table into and/or * locate the first iag in the specified inode table in the * fsck iag buffer. Set up for sequential access on the iag's * in this table. * * PARAMETERS: * is_aggregate - input - 0 => the iag is owned by the fileset * !0 => the iag is owned by the aggregate * which_it - input - ordinal number of the aggregate inode * representing the inode table to which the * iag belongs. * which_ait - input - the aggregate inode table { fsck_primary | * fsck_secondary } containing the version of * which_it to use for this operation * addr_iag_ptr - input - pointer to a variable in which to return * * RETURNS: * success: FSCK_OK * failure: something else */int iag_get_first(int is_aggregate, int it_number, int which_ait, struct iag **addr_iag_ptr){ int iaggf_rc = FSCK_OK; struct dinode *imap_inoptr; xad_t *xadptr; int it_tbl_is_agg_owned = -1; /* the table may not describe the * aggregate inodes, but the inode * describing the table is ALWAYS * an aggregate inode */ agg_recptr->fais.this_iagnum = 0; agg_recptr->fais.this_inoidx = 0; /* assume it's not a rootleaf */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -