📄 logredo.c
字号:
* store away the indicator of which aggregate superblock * to use */ use_2ndary_agg_superblock = use_2nd_aggSuper; /* * loop until we get enough memory to read vmount struct */ mntinfo = (char *) &bufsize; bufsize = sizeof (int); /* * validate that the log is not currently in use; */ rc = findLog(fp, &in_use); if (rc < 0) { fsck_send_msg(lrdo_DEVOPNREADERROR); return (rc); } /* recover from extendfs() ? */ if (Log.location & INLINELOG && (vopen[0].status & FM_EXTENDFS)) { fsck_send_msg(lrdo_REXTNDBEGIN); rc = recoverExtendFS(fp); fsck_send_msg(lrdo_REXTNDDONE); return rc; } /* * validate log superblock * * aggregate block size is for log file as well. */ rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned) sizeof (struct logsuper), (char *) &logsup, GET); if (rc != 0) { fsck_send_msg(lrdo_CANTREADLOGSUP); rc = LOGSUPER_READ_ERROR; goto error_out; } ujfs_swap_logsuper(&logsup); if (logsup.magic != LOGMAGIC) { fsck_send_msg(lrdo_LOGSUPBADMGC); rc = NOT_LOG_FILE_ERROR; goto error_out; } if (logsup.version > LOGVERSION) { fsck_send_msg(lrdo_LOGSUPBADVER); rc = JFS_VERSION_ERROR; goto error_out; } if (Log.location & OUTLINELOG) { struct stat st; if ((rc = fstat(fileno(Log.fp), &st))) goto error_out; Log.devnum = st.st_rdev; if (in_use) { fsck_send_msg(lrdo_LOGINUSE); return LOG_IN_USE; } } if (logsup.state == LOGREDONE) { fsck_send_msg(lrdo_ALREADYREDONE); if (Log.location & INLINELOG) if ((rc = updateSuper(0)) != 0) { fsck_send_msg(lrdo_CANTUPDLOGSUP); return (rc); } return (0); } Log.size = logsup.size; Log.serial = logsup.serial; /* * find the end of log */ logend = findEndOfLog(); if (logend < 0) { fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_LOGENDBAD1); logError(LOGEND, 0); ujfs_swap_logsuper(&logsup); rc = ujfs_rw_diskblocks(Log.fp, (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned long) LOGPSIZE, (char *) &logsup, PUT); rc = logend; goto error_out; } /* * allocate/initialize logredo runtime data structures and * initialize each file system associated with the log based on * the contents of its superblock */ if ((rc = logredoInit()) != 0) { fsck_send_msg(lrdo_INITFAILED, rc, errno); goto error_out; } highest_lr_byte = logsup.size * LOGPSIZE - LOGRDSIZE; if ((logend < lowest_lr_byte) || (logend > highest_lr_byte)) { fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_LOGENDBAD2); rc = INVALID_LOGEND; goto error_out; } /* * replay log * * read log backwards and process records as we go. * reading stops at place specified by first SYNCPT we * encounter. */ nlogrecords = lastaddr = 0; nextaddr = logend; do { logaddr = nextaddr; nextaddr = logRead(logaddr, &ld, afterdata); DBG_TRACE(("Logaddr=%x\nNextaddr=%x\n", logaddr, nextaddr)) nlogrecords += 1; /* * * Validate the nextaddr as much as possible * */ if (nextaddr < 0) { fsck_send_msg(lrdo_NEXTADDRINVALID); rc = nextaddr; goto error_out; } if ((nextaddr < lowest_lr_byte) || (nextaddr > highest_lr_byte)) { fsck_send_msg(lrdo_NEXTADDROUTRANGE, nextaddr); rc = INVALID_NEXTADDR; goto error_out; } if (nextaddr == logaddr) { fsck_send_msg(lrdo_NEXTADDRSAME, nextaddr); rc = NEXTADDR_SAME; goto error_out; } if (nextaddr > logaddr) { if (log_has_wrapped) { fsck_send_msg(lrdo_LOGWRAPPED); rc = LOG_WRAPPED_TWICE; goto error_out; } else { log_has_wrapped = -1; } } /* * * The addresses seem ok. Process the current record. * */ switch (ld.type) { case LOG_COMMIT: rc = doCommit(&ld); if (rc) { fsck_send_msg(lrdo_BADCOMMIT, logaddr); goto error_out; } break; case LOG_MOUNT: fsck_send_msg(lrdo_MOUNTRECORD, logaddr); rc = doMount(&ld); if (rc) { fsck_send_msg(lrdo_BADMOUNT, logaddr); goto error_out; } break; case LOG_SYNCPT: fsck_send_msg(lrdo_SYNCRECORD, logaddr); rc = 0; if (lastaddr == 0) { syncrecord = logaddr; lastaddr = (ld.log.syncpt.sync == 0) ? logaddr : ld.log.syncpt.sync; } break; case LOG_REDOPAGE: DBG_TRACE(("jfs_logredo:Case Log_redoPage")) rc = doAfter(&ld, logaddr); if (rc) { fsck_send_msg(lrdo_BADREDOPAGE, logaddr); goto error_out; } break; case LOG_NOREDOPAGE: DBG_TRACE(("jfs_logredo:Case Log_noredopage")) rc = doNoRedoPage(&ld); if (rc) { fsck_send_msg(lrdo_BADNOREDOPAGE, logaddr); goto error_out; } break; case LOG_NOREDOINOEXT: DBG_TRACE(("jfs_logredo:Case Log_noredoinoext")) rc = doNoRedoInoExt(&ld); if (rc) { fsck_send_msg(lrdo_BADNOREDOINOEXT, logaddr); goto error_out; } break; case LOG_UPDATEMAP: rc = doUpdateMap(&ld); if (rc) { fsck_send_msg(lrdo_BADUPDATEMAP, logaddr); goto error_out; } break; default: fsck_send_msg(lrdo_UNKNOWNTYPE, logaddr); rc = UNRECOG_LOGRECTYP; goto error_out; break; } if (rc < 0) { fsck_send_msg(lrdo_ERRORNEEDREFORMAT); goto error_out; } if (rc != 0) { fsck_send_msg(lrdo_ERRORCANTCONTIN); goto error_out; } /* * If the transaction just completed was the last * for the current transaction, then flush the * buffers. */ if (end_of_transaction != 0) { for (k = 1; k < NBUFPOOL; k++) { if ((rc = bflush(k, &buffer[k - 1])) != 0) goto error_out; } end_of_transaction = 0; } } while (logaddr != lastaddr); /* * If any 'dtpage extend' records were processed, then we need * to go back and rebuild their freelists. This cannot be done * when the 'dtpage extend' record is processed, since there may * be records processed later which affect the previous (shorter) * version of the dtpage. Only after all these records are processed * can we safely and accurately rebuild the freelist. */ if (numExtDtPg != 0) { rc = doExtDtPg(); } /* * flush data page buffer cache */ for (k = 1; k < NBUFPOOL; k++) { if ((rc = bflush(k, &buffer[k - 1])) != 0) break; } /* * finalize file systems * * update allocation map and superblock of file systems * of volumes which are open if they were modified here. * i.e. if they were not previously unmounted cleanly. */ for (k = 0; k < MAX_ACTIVE; k++) { if (vopen[k].state != VOPEN_OPEN) continue; if ((rc = updateMaps(k)) != 0) { fsck_send_msg(lrdo_ERRORCANTUPDMAPS); goto error_out; } /* Make sure all changes are committed to disk before we * mark the superblock clean */ ujfs_flush_dev(vopen[k].fp); if ((rc = updateSuper(k)) != 0) { fsck_send_msg(lrdo_ERRORCANTUPDFSSUPER); goto error_out; } /* sync superblock before journal is finalized */ ujfs_flush_dev(vopen[k].fp); } /* * finalize log. * * clear active list. * If this is a fully replayed log then it can be moved to earlier * versions of the operating system. Therefore switch the magic * number to the earliest level. */ if (logsup.state != LOGREADERR) { for (k = 0; k < MAX_ACTIVE; k++) uuid_clear(logsup.active[k]); logsup.end = logend; logsup.state = LOGREDONE; logsup.magic = LOGMAGIC; } ujfs_swap_logsuper(&logsup); rc = ujfs_rw_diskblocks(Log.fp, (Log.xaddr + LOGPNTOB(LOGSUPER_B)), LOGPSIZE, (char *) &logsup, PUT); /* * now log some info for the curious */ fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_RPTSYNCNUM, syncrecord); fsck_send_msg(lrdo_RPTSYNCADDR, lastaddr); fsck_send_msg(lrdo_RPTNUMLOGREC, nlogrecords); fsck_send_msg(lrdo_RPTNUMDOBLK, numdoblk); fsck_send_msg(lrdo_RPTNUMNODOBLK, numnodofile); error_out: if (rc > 0) { rc = rc * (-1); } /* * If everything went ok except that we didn't have * enough memory to deal with the block map, tell chkdsk * to be sure to do a full check and repair, but that a log * format is not necessary */ if ((rc == 0) && Insuff_memory_for_maps) { rc = ENOMEM25; } return (rc);}/* * NAME: doMount(ld) * * FUNCTION: a log mount record is the first-in-time record which is * put in the log so it is the last we want to process in * logredo. so we mark volume as cleanly unmounted in vopen * array. the mount record is imperative when the volume * is a newly made filesystem. */int doMount(struct lrd *ld){ /* pointer to record descriptor */ int vol, status; vol = ld->aggregate; status = vopen[vol].status; DBG_TRACE(("Logredo:domount: status=%d\n", status)) if (!(status & (FM_LOGREDO | FM_DIRTY))) vopen[vol].status = FM_CLEAN; return (0);}/* * NAME: openVol(vol) * * FUNCTION: open the aggregate/volume specified. * check if it was cleanly unmounted. also check log * serial number. initialize disk and inode mpas. */int openVol(int vol){ /* device minor number of aggregate/lv */ int rc, l2agsize, agsize; int64_t fssize; /* number of aggr blks in the aggregate/lv */ struct superblock sb; int aggsb_numpages; if (Log.location & OUTLINELOG) { /* First check if this is the already opened volume */ if (!uuid_compare(vopen[vol].uuid, primary_vol.uuid)) vopen[vol].fp = primary_vol.fp; else { vopen[vol].fp = open_by_label(vopen[vol].uuid, 0, 0, NULL, NULL); if (vopen[vol].fp == NULL) return ENOENT; } } /* read superblock of the aggregate/volume */ if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_READ)) != 0) { fsck_send_msg(lrdo_CANTREADFSSUPER); fsError(READERR, vol, SUPER1_B); vopen[vol].state = VOPEN_CLOSED; return (FSSUPER_READERROR1); } /* check magic number and initialize version specific * values in the vopen struct for this vol. */ if (strncmp(sb.s_magic, JFS_MAGIC, (unsigned) strlen(JFS_MAGIC))) { fsck_send_msg(lrdo_FSSUPERBADMAGIC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADMAGIC); } if (sb.s_version > JFS_VERSION) { fsck_send_msg(lrdo_FSSUPERBADMAGIC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADVERSION); } if (Log.location & OUTLINELOG && (sb.s_flag & (JFS_INLINELOG == JFS_INLINELOG))) { fsck_send_msg(lrdo_FSSUPERBADLOGLOC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADLOGLOC); } vopen[vol].lblksize = sb.s_bsize; vopen[vol].l2bsize = sb.s_l2bsize; vopen[vol].l2bfactor = sb.s_l2bfactor; fssize = sb.s_size >> sb.s_l2bfactor; vopen[vol].fssize = fssize; vopen[vol].agsize = sb.s_agsize; /* LOG2NUM will alter agsize, so use local var (Then why don't we fix LOG2NUM?) */ agsize = vopen[vol].agsize; LOG2NUM(agsize, l2agsize); vopen[vol].numag = fssize >> l2agsize; if (fssize & (vopen[vol].agsize - 1)) vopen[vol].numag += 1; vopen[vol].l2agsize = l2agsize; if (Log.location & INLINELOG) { /* * Now that the aggregate superblock has been read, do some * more validation of the log superblock */ if (logsup.bsize != vopen[vol].lblksize) { fsck_send_msg(lrdo_LOGSUPBADBLKSZ); return JFS_BLKSIZE_ERROR; } if (logsup.l2bsize != vopen[vol].l2bsize) { fsck_send_msg(lrdo_LOGSUPBADL2BLKSZ); return JFS_L2BLKSIZE_ERROR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -