📄 fsckimap.c
字号:
* chain. If it's really something more serious it * will come up again when we go through all allocated * iag's sequentially. */ if (intermed_rc != FSCK_OK) { wsp_agrec->frino_list_bad = -1; break; } /* got the iag */ if (iagiptr->iagptr->inofreeback != prev_iagno) /* bad back chain */ wsp_agrec->frino_list_bad = -1; else { /* back chain is correct */ prev_iagno = this_iagno; this_iagno = iagiptr->iagptr->inofreefwd; wsp_agrec->frino_list_len++; } } if (wsp_agrec->frino_list_bad) { /* found a problem */ agg_recptr->ag_dirty = 1; *errors_detected = -1; fsck_send_msg(fsck_BADAGFILIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx, "1"); } else wsp_agrec->frino_list_last = prev_iagno; } return (FSCK_OK);}/**************************************************************** * NAME: agfrino_lists_validation * * FUNCTION: Compare the results of the Allocation Group free inode lists * scan with the results of validating the iags. If the number * of iags seen on a list during the list scan does not equal * the number of iags which appear to be on the list (i.e., which * have non-initialized values for forward and back pointers) * as seen during iag validation, then the list is not structurally * consistent. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * agtbl - input - pointer to the fsck workspace allocation * group table for the specified inode * table * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * NOTES: o This routine is only called in the read-only path. * * o This routine is NOT called if any structural errors have * already been detected in the list. * * RETURNS: * success: FSCK_OK * failure: something else */int agfrino_lists_validation(int is_aggregate, int which_it, struct fsck_ag_record *agtbl, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr){ uint32_t agidx; struct fsck_ag_record *wsp_agrec; for (agidx = 0; agidx < MAXAG; agidx++) { wsp_agrec = &(agtbl[agidx]); if (!wsp_agrec->frino_list_bad) { /* the list itself looked ok */ if (wsp_agrec->frino_list_len > 0) { /* * fsck observed fewer iag's which belong on * this list than it counted when it scanned * the list. (fsck has already issued * messages about these iag's) */ *errors_detected = -1; agg_recptr->ag_dirty = 1; } else if (wsp_agrec->frino_list_len < 0) { /* * fsck observed more iag's which belong on * this list and which appear to be on the list * than it counted when it scanned the list. * So the chain has somehow lost some of its * links. */ *errors_detected = -1; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADAGFILIST1, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx); } } } return (FSCK_OK);}/**************************************************************** * NAME: AIM_check * * FUNCTION: Verify that the Secondary Aggregate Inode Map is correct * and that it is a logical equivalent to the Primary Aggregate * Inode Map. * * PARAMETERS: * secondary_btroot - input - pointer to the root of the B+ Tree * root in of the secondary aggregate * inode table inode in an fsck buffer. * temp_bufptr - input - pointer to a temporary I/O buffer, * large enough for an inode extent. * inconsistency_detected - input - pointer to a variable in which * to return !0 if errors are detected * 0 if no errors are detected * * * NOTES: o This routine reads the Primary Aggregate Inode Map into the * the first page of the fsck temporary inode buffer and reads * the Secondary Aggregate Inode Map into the 3rd page of the * fsck temporary inode buffer. * * o In release 1, there is always exactly 1 iag in the Aggregate * Inode Map and so the inode which represents the map always has * a root-leaf B+ tree rooted in it. * * RETURNS: * success: FSCK_OK * failure: something else */int AIM_check(xtpage_t * secondary_btroot, char *temp_bufptr, int *inconsistency_detected){ int intermed_rc = FSCK_OK; char *primary_bufptr = NULL, *secondary_bufptr = NULL; struct dinomap *primary_ctlptr, *secondary_ctlptr; struct iag *primary_iagptr; struct iag *secondary_iagptr; uint8_t expected_flag; int64_t sb_aim2_addr, btrt_aim2_addr; uint32_t sb_aim2_length, btrt_aim2_length; int64_t byte_offset; uint32_t bytes_wanted, bytes_read; expected_flag = (BT_ROOT | BT_LEAF | DXD_INDEX); sb_aim2_addr = addressPXD(&(sb_ptr->s_aim2)); sb_aim2_length = lengthPXD(&(sb_ptr->s_aim2)); btrt_aim2_addr = addressXAD(&(secondary_btroot->xad[XTENTRYSTART])); btrt_aim2_length = lengthXAD(&(secondary_btroot->xad[XTENTRYSTART])); if ((secondary_btroot->header.flag != expected_flag) || (secondary_btroot->header.nextindex != (XTENTRYSTART + 1)) || (sb_aim2_addr != btrt_aim2_addr) || (sb_aim2_length != btrt_aim2_length)) goto inconsistency_found; /* descriptors match */ primary_bufptr = temp_bufptr; secondary_bufptr = (char *) (temp_bufptr + (2 * BYTESPERPAGE)); byte_offset = AIMAP_OFF; bytes_wanted = sb_aim2_length * sb_ptr->s_bsize; intermed_rc = readwrite_device(byte_offset, bytes_wanted, &bytes_read, (void *) primary_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_read)) goto inconsistency_found; /* primary AIM is in the buffer */ byte_offset = sb_aim2_addr * sb_ptr->s_bsize; bytes_wanted = sb_aim2_length * sb_ptr->s_bsize; intermed_rc = readwrite_device(byte_offset, bytes_wanted, &bytes_read, (void *) secondary_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_read)) goto inconsistency_found; /* endian - swap not needed as these 2 structs are read * from disk and checked for inconsistencies. * the AIMaps are in the temp buffer */ primary_ctlptr = (struct dinomap *) primary_bufptr; secondary_ctlptr = (struct dinomap *) secondary_bufptr; if ((primary_ctlptr->in_freeiag != secondary_ctlptr->in_freeiag) || (primary_ctlptr->in_nextiag != secondary_ctlptr->in_nextiag) || (primary_ctlptr->in_numinos != secondary_ctlptr->in_numinos) || (primary_ctlptr->in_numfree != secondary_ctlptr->in_numfree) || (primary_ctlptr->in_nbperiext != secondary_ctlptr->in_nbperiext) || (primary_ctlptr->in_l2nbperiext != secondary_ctlptr->in_l2nbperiext)) goto inconsistency_found; if (memcmp((void *) &(primary_ctlptr->in_agctl[0]), (void *) &(secondary_ctlptr->in_agctl[0]), (sizeof (struct iagctl) * MAXAG))) goto inconsistency_found; /* * the AIMaps are in the temp buffer and * the control pages are consistent */ primary_iagptr = (struct iag *) (primary_bufptr + BYTESPERPAGE); secondary_iagptr = (struct iag *) (secondary_bufptr + BYTESPERPAGE); if ((primary_iagptr->agstart != secondary_iagptr->agstart) || (primary_iagptr->iagnum != secondary_iagptr->iagnum) || (primary_iagptr->inofreefwd != secondary_iagptr->inofreefwd) || (primary_iagptr->inofreeback != secondary_iagptr->inofreeback) || (primary_iagptr->extfreefwd != secondary_iagptr->extfreefwd) || (primary_iagptr->extfreeback != secondary_iagptr->extfreeback) || (primary_iagptr->iagfree != secondary_iagptr->iagfree) || (primary_iagptr->nfreeinos != secondary_iagptr->nfreeinos) || (primary_iagptr->nfreeexts != secondary_iagptr->nfreeexts)) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->inosmap[0]), (void *) &(secondary_iagptr->inosmap[0]), (sizeof (int32_t) * SMAPSZ))) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->extsmap[0]), (void *) &(secondary_iagptr->extsmap[0]), (sizeof (int32_t) * SMAPSZ))) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->pmap[0]), (void *) &(secondary_iagptr->pmap[0]), (sizeof (int32_t) * EXTSPERIAG))) goto inconsistency_found; if (memcmp((void *) &(secondary_iagptr->inoext[0]), (void *) &(sb_ptr->s_ait2), sizeof (pxd_t))) goto inconsistency_found; return (FSCK_OK);inconsistency_found: /* * future recover capability is compromised * * Note that we're in read-only mode or we wouldn't be checking * this (because when we have write access we always rebuild it) */ fsck_send_msg(fsck_INCONSIST2NDRY, "1"); *inconsistency_detected = 1; return (FSCK_OK);}/**************************************************************** * NAME: AIM_replication * * FUNCTION: Rebuild specified target Aggregate Inode Map so that it is * a logical equivalent to the specified source Aggregate Inode * Map. * * PARAMETERS: * source_is_primary - input - !0 => replicate from primary to secondary * 0 => replicate from secondary to primary * target_btroot - input - pointer to the B+ Tree root in the * aggregate inode allocation table (either * primary or secondary) inode which is * the target of the replication. * temp_bufptr - input - pointer to a temporary I/O buffer, * large enough for an inode extent. * replication_failure - input - pointer to a variable in which to return * !0 if errors occurred during replication * 0 if the replication was successful * * NOTES: o This routine considers the buffer for the Primary Aggregate * Inode Map to begin at the beginning of the fsck temporary * inode buffer. This routine considers the buffer for the * Secondary Aggregate Inode Map to begin at the 3rd page * of the fsck temporary inode buffer. * * o This routine reads the source Aggregate Inode Map (either * primary or secondary) into its buffer (see note above) and * rebuilds the target Aggregate Inode Map (either secondary * or primary) in its buffer. * * o In release 1, there is always exactly 1 iag in the Aggregate * Inode Map and so the inode which represents the map always has * a root-leaf B+ tree rooted in it. * * RETURNS: * success: FSCK_OK * failure: something else */int AIM_replication(int8_t source_is_primary, xtpage_t * target_btroot, char *temp_bufptr, int8_t * replication_failure){ int aimr_rc = FSCK_OK; int intermed_rc = FSCK_OK; char *target_bufptr, *source_bufptr; struct iag *target_iagptr; int64_t source_byte_offset = 0, target_byte_offset = 0; uint32_t bytes_wanted, bytes_transferred; target_btroot->header.flag = (BT_ROOT | BT_LEAF | DXD_INDEX); target_btroot->header.nextindex = XTENTRYSTART + 1; source_bufptr = temp_bufptr; target_bufptr = (char *) (temp_bufptr + (2 * BYTESPERPAGE)); target_iagptr = (struct iag *) (target_bufptr + BYTESPERPAGE); if (source_is_primary) { source_byte_offset = AIMAP_OFF; target_byte_offset = addressPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; XADaddress(&(target_btroot->xad[XTENTRYSTART]), addressPXD(&(sb_ptr->s_aim2))); XADlength(&(target_btroot->xad[XTENTRYSTART]), lengthPXD(&(sb_ptr->s_aim2))); } else { source_byte_offset = addressPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; target_byte_offset = AIMAP_OFF; XADaddress(&(target_btroot->xad[XTENTRYSTART]), (AIMAP_OFF / sb_ptr->s_bsize)); XADlength(&(target_btroot->xad[XTENTRYSTART]), lengthPXD(&sb_ptr->s_aim2)); } bytes_wanted = lengthPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; intermed_rc = readwrite_device(source_byte_offset, bytes_wanted, &bytes_transferred, (void *) source_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_transferred)) { aimr_rc = FSCK_FAILED_CANTREADAIMNOW; /* * message to the user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to the debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_CANTREADAIMNOW, intermed_rc, fsck_READ, (long long) source_byte_offset, bytes_wanted, bytes_transferred); goto aimr_exit; } /* the source AIMap is in the temp buffer */ /* * copy the source over the target, then adjust the field(s) which * should be different. */ memcpy((void *) target_bufptr, (void *) source_bufptr, bytes_wanted); memcpy((void *) &(target_iagptr->inoext[0]), (void *) &(sb_ptr->s_ait2), sizeof (pxd_t)); if (!source_is_primary) { XADaddress(&(target_iagptr->inoext[0]), (AITBL_OFF / sb_ptr->s_bsize)); } /* endian - don't need to swap either read or write in this routine. * Basically, source struct is read from disk, copied to target, * changes made, and written back. * * now write the redundant AIMap to the device */ aimr_rc = readwrite_device(target_byte_offset, bytes_wanted, &bytes_transferred, (void *) target_bufptr, fsck_WRITE); agg_recptr->ag_modified = 1; if ((aimr_rc != FSCK_OK) || (bytes_wanted != bytes_transferred)) { /* some or all didn't make it to the device. */ agg_recptr->ait_aim_update_failed = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -