📄 log_read.c
字号:
return (nextrep);}/* * NAME: setLogpage(pno, eor, pmax, buf) * * FUNCTION: Forms consistent log page and returns eor and pmax values. * * During the first release the following conditions are * assumed: * 1) No corrupted write during power failure * 2) No split write * 3) No out-of-order sector write * * If the header and trailer in the page are not equal, a * system crash happened during this page write. It * is reconciled as follows: * * 1) if h.page != t.page, the smaller value is taken and * the eor fields set to LOGPHDSIZE. * reason: This can happen when a old page is over-written * by a new page and the system crashed. So this page * should be considered not written. * 2) if h.eor != t.eor, the smaller value is taken. * reason: The last log page was rewritten for each * commit record. A system crash happened during the * page rewriting. Since we assume that no corrupted write * no split write and out-of-order sector write, the * previous successfuly writing is still good * 3) if no record ends on the page (eor = 8), still return it. * Let the caller determine whether a) a good long log record * ends on the next log page. or b) it is the first page of the * last long log record and system was crashed when its second * page is written. * * * RETURNS: 0 - ok * REFORMAT_ERROR(-3) - I/O error, reformat log * MAJOR_ERROR(-2) - other major error */int setLogpage(int32_t pno, /* page number of log */ int32_t *eor, /* log header eor to return */ int32_t *pmax, /* log header page number to return */ int32_t buf){ /* logp[] index number for page */ int rc; int32_t diff1, diff2; /* check that header and trailer are the same */ if ((diff1 = (__le32_to_cpu(logp[buf].h.page) - __le32_to_cpu(logp[buf].t.page))) != 0) { if (diff1 > 0) /* Both little-endian */ logp[buf].h.page = logp[buf].t.page; else /* Both little-endian */ logp[buf].t.page = logp[buf].h.page; logp[buf].h.eor = logp[buf].t.eor = __cpu_to_le16(LOGPHDRSIZE); /* empty page */ } if ((diff2 = (__le16_to_cpu(logp[buf].h.eor) - __le16_to_cpu(logp[buf].t.eor))) != 0) { if (diff2 > 0) /* Both little-endian */ logp[buf].h.eor = logp[buf].t.eor; else /* Both little-endian */ logp[buf].t.eor = logp[buf].h.eor; } /* if any difference write the page out */ if (diff1 || diff2) { rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(pno)), (unsigned long) LOGPSIZE, (char *) &logp[buf], PUT); if (rc != 0) { fsck_send_msg(lrdo_SLPWRITEFAIL, pno, rc); return (JLOG_WRITEERROR1); } } /* * At this point, it is still possible that logp[buf].h.eor * is LOGPHDRSIZE, but we return it anyway. The caller will make * decision. */ *eor = __le16_to_cpu(logp[buf].h.eor); *pmax = __le32_to_cpu(logp[buf].h.page); return (0);} /* * NAME: logRead(logaddr , ld, dataptr) * * FUNCTION: reads the log record addressed by logaddr and * returns the address of the preceding log record. * * PARAMETERS: logaddr - address of the end of log record to read * Note: log is read backward, so this is * the address starting to read * ld - pointer to a log record descriptor * dataptr - pointer to data buffer * * RETURNS: < 0 - there is an i/o error in reading * > 0 - the address of the end of the preceding log record */int logRead(int32_t logaddr, /* address of log record to read */ struct lrd *ld, /* pointer to a log record descriptor */ char *dataptr){ /* pointer to buffer. LOGPSIZE*2 long */ int buf, off, rc, nwords, pno; /* get page containing logaddr into log buffer pool */ pno = BTOLOGPN(logaddr); if (pno != loglastp) { loglastp = pno; lognumread += 1; if (lognumread > Log.size - 2) { logError(LOGWRAP, 0); fsck_send_msg(lrdo_LRLOGWRAP, lognumread); return (JLOG_LOGWRAP); } } buf = getLogpage(pno); if (buf < 0) { fsck_send_msg(lrdo_LRREADFAIL, pno, buf); return (buf); } /* read the descriptor */ off = logaddr & (LOGPSIZE - 1); /* offset just past desc. */ rc = moveWords(LOGRDSIZE / 4, (int32_t *) ld, &buf, &off); if (rc < 0) { fsck_send_msg(lrdo_LRMWFAIL1, rc); return (rc); } ujfs_swap_lrd(ld); /* * Legacy code used device number in ld->aggegate. This code only * supported a single volume attached to the journal */ if (ld->aggregate > MAX_ACTIVE) ld->aggregate = 0; /* read the data if there is any */ if (ld->length > 0) { if (ld->length > LOGPSIZE * 2) { rc = READLOGERROR; fsck_send_msg(lrdo_LRMWFAIL3, pno); return (rc); } /* if length is partial word, still read it */ nwords = (ld->length + 3) / 4; rc = moveWords(nwords, (int32_t *) dataptr, &buf, &off); if (rc < 0) { fsck_send_msg(lrdo_LRMWFAIL2, rc); return (rc); } } return (LOGPNTOB(logptr[buf]) + off);}/* * NAME: moveWords() * * FUNCTION: moves nwords from buffer pool to target. data * is moved in backwards direction starting at offset. * If partial log record is on the previous page, * or we have exhaust the current page (all bytes were read), * the previous page is read into the buffer pool. * On exit buf will point to this page in the buffer pool * and offset to where the move stopped. * * Note: the previous page is fetched whenever * the current page is exhausted (all bytes were read) * even if all the words required to satisfy this move * are on the current page. * * PARAMETERS: nwords - number of 4-byte words to move * target - address of target (begin address) * buf - index in buffer pool of current page * offset - initial offset in buffer pool page, this offset * includes the page head size * * RETURNS: = 0 - ok * < 0 - error returned from getLogpage */int moveWords(int32_t nwords, /* number of 4-byte words to move */ int32_t *target, /* address of target (begin address) */ int32_t *buf, /* index in buffer pool of curr page */ int32_t *offset){ /* initial offset in buffer pool page */ int n, j, words, pno; int *ptr; j = (*offset - LOGPHDRSIZE) / 4 - 1; /* index in log page data area of first word to move */ words = min(nwords, j + 1); /* words on this page to move */ ptr = target + nwords - 1; /* last word of target */ for (n = 0; n < words; n++) { *ptr = logp[*buf].data[j]; j = j - 1; ptr = ptr - 1; } *offset = *offset - 4 * words; /* * If partial log record is on the previous page, * or we have read all the log records in the current page, * get the previous page */ if (words != nwords /* we get less than nwords */ || j < 0) { /* or exhaust the page, so offset is just */ /* the page head, then j < 0 */ /* get previous page */ pno = logptr[*buf]; pno = pno - 1; /* if we hit beginning location of the log, go wrapped, read log record from the end location of the log */ if (pno == 1) pno = Log.size - 1; *buf = getLogpage(pno); if (*buf < 0) { fsck_send_msg(lrdo_MWREADFAIL, pno, (*buf)); return (*buf); } *offset = LOGPSIZE - LOGPTLRSIZE; /* index last word of data area */ j = LOGPSIZE / 4 - 4 - 1; /* move rest of nwords if any. this will never exhaust the page. */ for (n = 0; n < nwords - words; n++) { *ptr = logp[*buf].data[j]; j = j - 1; ptr = ptr - 1; } *offset = *offset - 4 * (nwords - words); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -