📄 log_work.c
字号:
* device. */ end_of_transaction = -1; return (0);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doAfter(ld) * * FUNCTION: processing for LOG_REDOPAGE record types. * * IN GENERAL * ---------- * The redopage log rec has many sub-types defined in * ld->log.redopage.type, but in general, the data belonging * to the REDOPAGE log record is applied to the disk pages * described by the address in ld->log.redopage.pxd. * * Also, depending on the redopage.type, * - the block map (bmap) may be updated * - the applicable inode map (imap) may be updated * - a NoRedoFile filter may be established * - a NoRedoPage filter may be established * * IN PARTICULAR * ------------- * LOG_BTROOT | LOG_DTREE | LOG_NEW -- describes a dtree root * which has been reset * * The log record data is applied to dtroot slots. The * dtree root's freelist needs to be initialized. The * LOG_NEW flag indicates that a dtree root which was a * leaf is now an internal node. * Specifically: * - the dtroot was full and was copied into a new * dtree (non-root) node. * - after the log record data is applied to this * dtree root, only 1 slot will be in use -- it * will point to the new dtree node. * * One log record of this type describes a single dtree * root. * * LOG_BTROOT | LOG_DTREE --describes an updated dtree root * * The log record data is applied to dtroot slots. This * covers the case of dtree root initialization, since * dtInitRoot() writes all slots (including free slots) * for a dtree root node into the log record. * * One log record of this type describes a single dtree * root. * * LOG_DTREE -- describes an updated dtree (non-root) node * * The log record data is applied to the storage defined * by the pxd. * * One log record of this type describes a single dtree * root. * * LOG_DTREE | LOG_NEW -- describes a new dtree (non-root) node * * The log record data is applied to the storage defined * by the pxd. The node's freelist is initialized. The * block map is updated for the storage allocated for the * new node. * * One log record of this type describes a single dtree * (non-root) node. * * LOG_DTREE | LOG_EXTEND -- describes a (non-root) dtree node * which has been extended. * * The log record data is applied to the storage defined * by the pxd. The node's freelist is initialized. The * block map is updated for the storage allocated for the * extended node. * * One log record of this type describes a single dtree * (non-root) node. * * LOG_BTROOT | LOG_XTREE -- describes an updated xtree root * * The log record data is applied to the xtree root's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. * * One log record of this type describes a single xtree * root. * * LOG_XTREE | LOG_NEW -- describes a new xtree (non-root) node * * The log record data is applied to the xtree node's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. The block * map is also updated to show that the blocks occupied by * the xtree node itself are now in use. * * One log record of this type describes a single xtree * (non-root) node. * * LOG_XTREE -- describes an xtree (non-root) node which * which has been changed. * * The log record data is applied to the xtree node's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. * (Note that when a file is truncated, the slots describing * the now deleted blocks are not updated. File truncation * affects the slot containing the xtree header nextindex * field.) * * One log record of this type describes a single xtree * (non-root) node. * * LOG_INODE -- describes one (4096 byte) page of an inode * extent (that is, a page actually containing * inodes) which has been updated. * * The log record data is applied to the inode extent page, * updating from 1 to all of the inodes contained in the * page. (Note that this may include updates to inline * EA data.) * * ** for this log record, log.redopage.inode contains the * inode number of the inode map which owns the page. * That is, not the inode number of any inode being * changed by the contents of this log record. * The inode number of each inode being changed by this * log record can be found in the inode's after image * in the log record data. * * For each inode affected by the log record: * - If the portion of the inode affected by this * log data has not been updated by an earlier * log record in this session, the log data is * copied over the appropriate portion of the * inode. * - If the nlink count == 0, * o the inode map (imap) is updated to show the * inode is free * o a NoRedoFile filter is started for the inode * - Otherwise (nlink != 0), * o the inode map (imap) is updated to show the inode * is allocated. * * If at least 1 inode affected by the current log record * has nlink != 0, the block map is updated to show that * the block(s) containing the inode extent (of which this * page is a part) are allocated. * * (It is obvious that from this log record we don't have * enough information to consider marking the blocks * containing the inode extent free.) * * One log record of this type describes from 1 to all 8 * inodes contained in the page. * * LOG_DATA -- ** may be used in a future release ** * * This is for in-line data (i.e. symlink.) * (TBD) * */int doAfter(struct lrd *ld, /* pointer to log record descriptor */ int32_t logaddr){ int vol, rc = 0; int32_t hash; struct nodofile *nodoptr; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * if the filesystem was cleanly unmounted or if the last * thing that happened was a logredo failure, skip this * record. (Necessary for the case of logredo a log shared * by multiple filesystems. We want to process log records * for those filesystems which don't meet this criteria, but * skip log records for those which do.) */ vol = ld->aggregate; if (vopen[vol].status == FM_CLEAN || vopen[vol].status == FM_LOGREDO) return (0); /* * If the redopage.type != LOG_INODE, then if there is a * NoRedoFile filter in effect for the inode we can skip this * log record. * * N.B. When redopage.type == LOG_INODE, log.redopage.inode is * the owning imap's inode number. We'll check for NoRedoFile * filter(s) on the inode(s) actually affected by the log * record when we examine the log record data in updatePage(). */ if (!(ld->log.redopage.type & LOG_INODE)) { hash = (ld->aggregate + ld->log.redopage.inode) & nodofilehmask; for (nodoptr = nodofilehash[hash]; nodoptr != NULL; nodoptr = nodoptr->next) { if (ld->aggregate == nodoptr->aggregate && ld->log.redopage.inode == nodoptr->inode) return (0); } } /* * updatePage() takes care of applying the log data. * This includes: * - applying log data to the affected page * - updates to the inode map for inodes allocated/free * - updates to the block map for an allocated inode extent * - establishing NoRedoFile or NoRedoExtent filters * - updates to the block map for extents described in an * xtree root or node xadlist */ if ((rc = updatePage(ld, logaddr)) != 0) { fsck_send_msg(lrdo_DAFTUPDPGFAILED, logaddr, rc); return (rc); } /* * If this isn't a REDOPAGE log record, we're done */ if (ld->type != LOG_REDOPAGE) return (0); /* * update the block map for a new or extended dtree page and * for a new xtree page */ switch (ld->log.redopage.type) { case (LOG_DTREE | LOG_NEW): /* * the pxd describes the (non-root) dtree page */ case (LOG_DTREE | LOG_EXTEND): /* * The pxd describes the entire (non-root) dtree page, not * just the new extension, but it's always ok to mark allocated * something which is already marked that way. * * (And we don't really know how many of the trailing blocks * were newly added here anyway.) */ case (LOG_XTREE | LOG_NEW): /* * the pxd describes the (non-root) xtree page */ rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.redopage.pxd, 1, vol); if (rc) { fsck_send_msg(lrdo_DAFTMRKBMPFAILED, logaddr, rc); } break; } return (rc);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doCommit(ld) * * FUNCTION: Insert the transaction ID (tid) from the given commit * record into the commit array */int doCommit(struct lrd *ld){ /* pointer to record descriptor */ int k, hash; DBG_TRACE(("logredo:Docommit\n")) if (comfree == 0) return (JLOG_NOCOMFREE); k = comfree; comfree = com[k].next; hash = ld->logtid & comhmask; com[k].next = comhash[hash]; com[k].tid = ld->logtid; comhash[hash] = k; return (0);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doExtDtPg() * * FUNCTION: Rebuild the freelist for each dtpage which has been * extended in the current logredo session. * */int doExtDtPg(){ struct ExtDtPg *edpp; int dedp_rc = 0; int *buf; pxd_t a_pxd; while ((DtPgList != NULL) && (dedp_rc == 0)) { edpp = DtPgList; PXDaddress(&a_pxd, edpp->pg_off); PXDlength(&a_pxd, vopen[edpp->pg_vol].lbperpage); dedp_rc = bread(edpp->pg_vol, a_pxd, (void **) &buf, PB_UPDATE); if (dedp_rc) { fsck_send_msg(lrdo_DEDPBREADFAILED, (long long)edpp->pg_off, dedp_rc); dedp_rc = DTPAGE_READERROR1; } else { dedp_rc = dtpg_resetFreeList(edpp->pg_vol, buf); DtPgList = DtPgList->next; } } /* end while */ return (dedp_rc);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoFile() * * FUNCTION: Add a record for the specified inode to the * NoRedoFile array. */int doNoRedoFile(struct lrd *ld, /* pointer to record descriptor */ uint32_t inum){ /* the inode number for noredofile */ int rc = 0; struct nodofile *ndptr; int32_t hash; int32_t allocated_from_bmap = 0; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * start NoRedoFile filter for the specified inode by * adding a record to the NoRedoFile hash list. * */ hash = (ld->aggregate + inum) & nodofilehmask; if (Freenodofile == 0) {#ifdef _JFS_DEBUG printf("logredo:alloc (d)%d bytes for NoRedoFile filter\n", PSIZE);#endif fsck_send_msg(lrdo_ALLOC4NOREDOFL, PSIZE); rc = alloc_storage((uint32_t) PSIZE, (void **) &Nodofilep, &allocated_from_bmap); if ((rc != 0) || (Nodofilep == NULL)) { /* * NoRedoFile filter allocation failed */#ifdef _JFS_DEBUG printf("logredo:alloc (d)%lld bytes for NoRedoFile filter failed\n", PSIZE);#endif fsck_send_msg(lrdo_ALLOC4NOREDOFLFAIL, PSIZE); return (ENOMEM3); } else if (Nodofilep != NULL) { /* NoRedoFile filter allocation successful */ if (allocated_from_bmap) {#ifdef _JFS_DEBUG printf ("logredo:alloc (d)%lld bytes for NoRedoFile filter out of bmap allocation\n", PSIZE);#endif fsck_send_msg(lrdo_USINGBMAPALLOC4NRFL); } } /* end NoRedoFile filter allocation successful */ Freenodofile = PSIZE / sizeof (struct nodofile); } ndptr = Nodofilep++; numnodofile++; Freenodofile--; ndptr->next = nodofilehash[hash]; nodofilehash[hash] = ndptr; ndptr->aggregate = ld->aggregate; ndptr->inode = inum;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -