📄 logredo.c
字号:
aggsb_numpages = lengthPXD(&sb.s_logpxd) * logsup.bsize / LOGPSIZE; if (logsup.size != aggsb_numpages) { fsck_send_msg(lrdo_LOGSUPBADLOGSZ); return JFS_LOGSIZE_ERROR; } } /* *set lbperpage in vopen. */ vopen[vol].lbperpage = PSIZE >> vopen[vol].l2bsize; /* * was it cleanly umounted ? */ if (sb.s_state == FM_CLEAN) { vopen[vol].status = FM_CLEAN; vopen[vol].state = VOPEN_CLOSED; return (0); } /* * get status of volume */ vopen[vol].status = sb.s_state; vopen[vol].is_fsdirty = (sb.s_state & FM_DIRTY); /* *check log serial number */ if (sb.s_logserial != Log.serial) { fsck_send_msg(lrdo_FSSUPERBADLOGSER); vopen[vol].state = VOPEN_CLOSED; fsError(SERIALNO, vol, SUPER1_B); return (LOGSUPER_BADSERIAL); } /* initialize the disk and inode maps */ if ((rc = initMaps(vol)) != 0) { fsck_send_msg(lrdo_INITMAPSFAIL); fsError(MAPERR, vol, 0); return (rc); } vopen[vol].state = VOPEN_OPEN; return 0;}/* * NAME: updateSuper(vol) * * FUNCTION: updates primary aggregate/lv's superblock status and * writes it out. */int updateSuper(int vol){ /* device minor number of aggregate/lv */ int rc, status; struct superblock sb; /* read in superblock of the volume */ if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_READ)) != 0) { fsck_send_msg(lrdo_READFSSUPERFAIL); return (FSSUPER_READERROR2); } /* mark superblock state. write it out */ status = vopen[vol].status; if (status & (FM_DIRTY | FM_LOGREDO)) sb.s_state = status & ~FM_EXTENDFS; else sb.s_state = FM_CLEAN; if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_UPDATE)) != 0) { fsck_send_msg(lrdo_WRITEFSSUPERFAIL); } return (rc);}/* * NAME: rdwrSuper(fp, sb, rwflag) * * FUNCTION: read or write the superblock for the file system described * by the file descriptor of the opened aggregate/lv. * for read, if a read of primary superblock is failed, * try to read the secondary superblock. report error only * when both reads failed. * for write, any write failure should be reported. */int rdwrSuper(FILE *fp, struct superblock * sb, int32_t rwflag){ int rc; uint64_t super_offset; union { struct superblock super; char block[PSIZE]; } super; if (use_2ndary_agg_superblock) { super_offset = SUPER2_OFF; } else { super_offset = SUPER1_OFF; } /* * seek to the postion of the primary superblock. * since at this time we don't know the aggregate/lv * logical block size yet, we have to use the fixed * byte offset address super_offset to seek for. */ /* * read super block */ if (rwflag == PB_READ) { rc = ujfs_rw_diskblocks(fp, super_offset, (unsigned) SIZE_OF_SUPER, super.block, GET); if (rc != 0) { if (!use_2ndary_agg_superblock) { fsck_send_msg(lrdo_READFSPRIMSBFAIL); return (CANTREAD_PRIMFSSUPER); } else { fsck_send_msg(lrdo_READFS2NDSBFAIL); return (CANTREAD_2NDFSSUPER); } } *sb = super.super; ujfs_swap_superblock(sb); /* * write superblock */ } else { /* PB_UPDATE */ /* ? memset(super.block, 0, SIZE_OF_SUPER); */ super.super = *sb; ujfs_swap_superblock(&super.super); /* * write whichever superblock we're working with. * chkdsk will take care of replicating it. */ rc = ujfs_rw_diskblocks(fp, super_offset, (unsigned) SIZE_OF_SUPER, super.block, PUT); if (rc != 0) { if (!use_2ndary_agg_superblock) { fsck_send_msg(lrdo_WRITEFSPRIMSBFAIL); return (CANTWRITE_PRIMFSSUPER); } else { fsck_send_msg(lrdo_WRITEFS2NDSBFAIL); return (CANTWRITE_2NDFSSUPER); } } } return (0);}/* * NAME: bflush() * * FUNCTION: write out appropriate portion of buffer page if its modified. * Note that a dtree page may not be 4k, depending on the length * field specified in pxd. Write out only length that is needed. */int bflush(int32_t k, /* The index in bufhdr that describes buf */ struct bufpool *buf){ /* pointer to buffer pool page */ FILE *fp = NULL; int rc; int32_t vol; int32_t nbytes; int64_t blkno; /* nothing to do ? */ if (bufhdr[k].modify == 0) return (0); /* write it out */ vol = bufhdr[k].vol; fp = vopen[vol].fp; blkno = addressPXD(&bufhdr[k].pxd); nbytes = lengthPXD(&bufhdr[k].pxd) << vopen[vol].l2bsize; rc = ujfs_rw_diskblocks(fp, (uint64_t) (blkno << vopen[vol].l2bsize), (unsigned) nbytes, (char *) buf, PUT); if (rc != 0) { fsck_send_msg(lrdo_BUFFLUSHFAIL); return (BFLUSH_WRITEERROR); } bufhdr[k].modify = 0; return (0);}/* * NAME: findLog() * * FUNCTION: open the device to see if it's a valid filesystem * or journal. If it is a filesystem, determine whether * the log is inline or external. If external, find * the log device. * */int findLog(FILE *fp, int *in_use){ struct logsuper logsup; struct superblock sb; *in_use = 0; /* * try the LV as file system with in-line log */ if (rdwrSuper(fp, &sb, PB_READ)) { fsck_send_msg(lrdo_NOTAFSDEV); return NOT_FSDEV_ERROR; } /* * is the LV a file system ? */ if (memcmp(sb.s_magic, JFS_MAGIC, sizeof (sb.s_magic)) == 0) { /* * does file system contains its in-line log ? */ if ((sb.s_flag & JFS_INLINELOG) == JFS_INLINELOG) { Log.location = INLINELOG; Log.fp = fp; //Log.status = sb.s_state; Log.l2bsize = sb.s_l2bsize; Log.xaddr = addressPXD(&sb.s_logpxd) << sb.s_l2bsize; /* vopen[0] represents fs if inline log */ vopen[0].status = sb.s_state; vopen[0].fp = fp; return 0; } /* Save fp and uuid */ primary_vol.fp = fp; uuid_copy(primary_vol.uuid, sb.s_uuid); /* * External log * * First check device specified on * command line */ Log.xaddr = 0; if (log_device[0]) { Log.fp = NULL; if (LogOpenMode != O_RDONLY) { Log.fp = fopen_excl(log_device, "r+"); if (Log.fp == NULL) *in_use = 1; } if (Log.fp == NULL) { Log.fp = fopen(log_device, "r"); if (Log.fp == NULL) { printf("Invalid journal specified (%s)\n", log_device); goto by_uuid; } } ujfs_rw_diskblocks(Log.fp, LOGPNTOB(LOGSUPER_B), sizeof (struct logsuper), &logsup, GET); ujfs_swap_logsuper(&logsup); if ((logsup.magic != LOGMAGIC) || (uuid_compare(logsup.uuid, sb.s_loguuid))) { fclose(Log.fp); *in_use = 0; goto by_uuid; } Log.location = OUTLINELOG; return 0; } by_uuid: Log.fp = open_by_label(sb.s_loguuid, 0, 1, NULL, in_use); if (Log.fp != NULL) { Log.location |= OUTLINELOG; return 0; } return NOT_INLINELOG_ERROR; } /* * is this an external log? */ ujfs_rw_diskblocks(fp, LOGPNTOB(LOGSUPER_B), sizeof (struct logsuper), &logsup, GET); ujfs_swap_logsuper(&logsup); if (logsup.magic != LOGMAGIC) { fsck_send_msg(lrdo_NOTAFSDEV); return NOT_FSDEV_ERROR; } Log.fp = fp; Log.location = OUTLINELOG; return 0;}extern void exit(int);/* * NAME: fsError(type,vol,bn) * * FUNCTION: error handling code for the specified * aggregate/lv (filesystem). */int fsError(int type, /* error types */ int vol, /* the minor number of the aggregate/lv */ int64_t bn){ /* aggregate block No. */ fsck_send_msg(lrdo_ERRORONVOL, vol); retcode = -1; vopen[vol].status = FM_LOGREDO; switch (type) { case OPENERR: fsck_send_msg(lrdo_OPENFAILED); break; case MAPERR: fsck_send_msg(lrdo_CANTINITMAPS); break; case DBTYPE: fsck_send_msg(lrdo_BADDISKBLKNUM, (long long) bn); break; case INOTYPE: fsck_send_msg(lrdo_BADINODENUM, (long long) bn); break; case READERR: fsck_send_msg(lrdo_CANTREADBLK, (long long) bn); break; case SERIALNO: fsck_send_msg(lrdo_BADLOGSER); break; case IOERROR: fsck_send_msg(lrdo_IOERRREADINGBLK, (long long) bn); break; case LOGRCERR: fsck_send_msg(lrdo_BADUPDMAPREC, (long long) bn); break; } return (0);}/* * logError(type) * * error handling for log read errors. */int logError(int type, int logaddr){ int k; retcode = -1; logsup.state = LOGREADERR; switch (type) { case LOGEND: fsck_send_msg(lrdo_FINDLOGENDFAIL); break; case READERR: fsck_send_msg(lrdo_LOGREADFAIL, logaddr); break; case UNKNOWNR: fsck_send_msg(lrdo_UNRECOGTYPE, logaddr); break; case IOERROR: fsck_send_msg(lrdo_IOERRONLOG, logaddr); break; case LOGWRAP: fsck_send_msg(lrdo_LOGWRAP); } /* mark all open volumes in error */ for (k = 0; k < MAX_ACTIVE; k++) { if ((vopen[k].state == VOPEN_OPEN) && vopen[k].status != FM_CLEAN) vopen[k].status = FM_LOGREDO; } return (0);}/* * recoverExtendFS() * * function: recover crash while in extendfs() for inline log; * * note: fs superblock fields remains pre-extendfs state, * while that bmap file, fsck and inline log area may be in * unknown state; * * at entry, only log type/lv has been validated; * for inline log: vopen[0], fs fp = log fp; */static int recoverExtendFS(FILE *fp){ struct superblock *sbp; struct dinode *dip1, *dip2; struct dbmap *bgcp; xtpage_t *p; int64_t lmchild = 0, xaddr, xoff, barrier, t64, agsize; uint8_t lmxflag; int32_t i; char *dip, *bp; pxd_t temp_pxd; /* * read bmap global control page */ /* read superblock yet again */ sbp = (struct superblock *) &buffer[0]; if (rdwrSuper(fp, sbp, PB_READ)) goto errout; /* read primary block allocation map inode */ dip = (char *) &buffer[1]; if (ujfs_rw_diskblocks(fp, AITBL_OFF, PSIZE, dip, GET)) { fsck_send_msg(lrdo_EXTFSREADFSSUPERFAIL); goto errout; } /* locate the inode in the buffer page */ dip1 = (struct dinode *) dip; dip1 += BMAP_I; bp = (char *) &buffer[2]; /* utility buffer */ /* start from root in dinode */ p = (xtpage_t *) & dip1->di_btroot; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) goto rdbgcp; /* traverse down leftmost child node to leftmost leaf of xtree */ do { /* read in the leftmost child page */ t64 = addressXAD(&p->xad[XTENTRYSTART]) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKMAPINOFAIL); goto errout; } p = (xtpage_t *) bp; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) break; } while (1); rdbgcp: t64 = addressXAD(&p->xad[XTENTRYSTART]) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL1, (long long) t64); goto errout; } bgcp = (struct dbmap *) bp; /* * recover to pre- or post-extendfs state ?: */ if (__le64_to_cpu(bgcp->dn_mapsize) > (sbp->s_size >> sbp->s_l2bfactor)) { agsize = __le64_to_cpu(bgcp->dn_agsize); goto postx; } /* * recover pre-extendfs state */ /* * reset block allocation map inode (xtree root) */ /* read 2ndary block allocation map inode */ t64 = addressPXD(&sbp->s_ait2) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL2, (long long) t64); goto errout; } dip2 = (struct dinode *) bp; dip2 += BMAP_I; /* * Reset primary bam inode with 2ndary bam inode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -