📄 log_work.c
字号:
return (0);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoPage() * * FUNCTION: Processing for LOG_NOREDOPAGE rec type. * * This routine starts a NoRedoPage filter for the * specified xtree or dtree node (may be root). * * This routine updates the bmap when the freed node * is NOT the root node. * (ld->log.noredopage.pxd = old page extent) * * NOTE: This routine only updates the block map when the * extent being freed describes a dtree page. * Block map updates for a freed xtree page are handled * when the UPDATEMAP log record is seen. * */int doNoRedoPage(struct lrd *ld){ /* pointer to log record descriptor */ int vol, rc = 0; int32_t hash; struct nodofile *nodoptr; pxd_t pxd1; struct doblk *db; int32_t inonum; uint8_t mask_8; /* * 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); /* * We may already have a NoRedoPage filter in effect. * If one is found on the NoRedoFile hash chain, goto update * map. * * N.B. The log.noredopage.inode in the log record is the * inode number of the applicable imap. We NEVER * NoRedoFile for an imap inode. */ hash = (ld->aggregate + ld->log.noredopage.inode) & nodofilehmask; for (nodoptr = nodofilehash[hash]; nodoptr != NULL; nodoptr = nodoptr->next) { if (ld->aggregate == nodoptr->aggregate && ld->log.noredopage.inode == nodoptr->inode) goto updmap; } /* * start NoRedoPage filter for LOG_NOREDOPAGE log rec. * */ pxd1 = ld->log.noredopage.pxd; /* * DTREE ROOT * * Do not process any further log records for * the root of the specified (directory) inode's dtree. */ if ((ld->log.noredopage.type & (LOG_BTROOT | LOG_DTREE)) == (LOG_BTROOT | LOG_DTREE)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDDTRTPGREDOFAIL, rc); return (rc); } /* * mark the appropriate slot in the noredopage for * no further updates to this (directory) inode's * dtree root. */ inonum = ld->log.redopage.inode & 0x07; db->db_dtroot[inonum] = 0x01ff; /* * This inode is identified as a dtroot. So mark * the appropriate slot in the noredopage for * NO updates to this inode as an xtroot. */ mask_8 = UZBIT_8 >> inonum; db->db_xtrt_lwm[inonum] = XTENTRYSTART; db->db_xtrt_hd |= mask_8; /* * XTREE ROOT * * Do not process any further log records for * the root of the specified inode's xtree. */ } else if ((ld->log.redopage.type & (LOG_BTROOT | LOG_XTREE)) == (LOG_BTROOT | LOG_XTREE)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDXTRTPGREDOFAIL, rc); return (rc); } /* * mark the appropriate slot in the noredopage for no * further updates to this inode's xtree root. */ inonum = ld->log.redopage.inode & 0x07; mask_8 = UZBIT_8 >> inonum; db->db_xtrt_lwm[inonum] = XTENTRYSTART; db->db_xtrt_hd |= mask_8; /* * This inode is identified as an xtree root. So * mark the appropriate slot in the noredopage for * NO updates to this inode's root as a dtree. */ db->db_dtroot[inonum] = 0x01ff; /* * DTREE, XTREE, or DATA NODE * * Do not process any further log records for * the specified page. */ } else if (ld->log.redopage.type & (LOG_XTREE | LOG_DTREE | LOG_DATA)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDXTPGPGREDOFAIL, rc); return (rc); } db->type = LOG_NONE; /* * UNRECOGNIZED TYPE * * We don't ever expect to get here! */ } else { fsck_send_msg(lrdo_DNRPUNKNOWNTYPE); } /* * If this is a (non-root) dtree page update the bmap. */ updmap: if (ld->log.noredopage.type == LOG_DTREE) { rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.noredopage.pxd, 0, vol); if (rc != 0) { return (rc); } } return (0);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoInoExt() * * FUNCTION: Processing for LOG_NOREDOINOEXT rec type. * * This routine starts a NoRedoPage filter for each * page in the inode extent being released. * * This routine may updates the bmap and the imap. * * NOTE: The noredoinoext.pxd describes a 4 (4096-byte) page * inode extent. * * * NOTE: This log record was written when an inode extent was * released. * * At this point, there are 3 possibilities: * * o the extent could have been reallocated for an inode * extent (possibly even for the same inode number range. * If this is true, then there is already a NoRedoExtent * filter in effect. * * o the extent could now be allocated for user data or for * JFS metadata. If this is true, then further updates * to the blocks in the extent would violate data * integrity. Therefore, we establish a NoRedoExtent * filter (i.e., a NoRedoPage filter for each of the * 4 pages in the extent). * * o the extent could be unallocated. That is, none of the * blocks in the extent pages are in use. If this is * true, then further updates to the blocks in the extent * are a waste of processing time. Therefore, we establish * a NoRedoExtent filter (i.e., a NoRedoPage filter for * each of the 4 pages in the extent). * */int doNoRedoInoExt(struct lrd *ld){ /* pointer to log record descriptor */ int pg_idx, vol, rc = 0; pxd_t pxd1; struct doblk *db; int32_t iagnum, iagext_idx; struct iag_data *imp; /* * 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); /* * Establish the 4 NoRedoPage filters which together * form the NoRedoExtent filter. */ pxd1 = ld->log.noredoinoext.pxd; for (pg_idx = 0; pg_idx < 4; pg_idx++) { /* * find the noredo record for this page. * (or create one if not found) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRIFNDNOREDORECFAIL, rc); return (rc); } /* * mark for no inode updates to the page, no matter what * format it might appear to have */ db->type = LOG_NONE; /* * set up for the next page in the extent */ PXDaddress(&pxd1, (addressPXD(&pxd1) + vopen[vol].lbperpage) ); } /* end for */ /* * Now go update the block map if appropriate. * * Note: * If any of these blocks has been allocated LATER * (in time) than this extent release then we don't * want to mark them unallocated, but if not then * we must mark them unallocated. Since we process * log records in LIFO order, we have already * processed the log record(s) (if any) describing * reallocation of the block(s). * * The markBmap routine only marks the block map * for blocks whose status has not already been * set by markBmap in the current logredo session. * */ rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.noredoinoext.pxd, 0, vol); if (rc != 0) { return (rc); } /* * Now, if no extent has been reallocated for * the inodes in the range which the extent being * released describes, then the IAG needs to be * updated to show that this extent is not * allocated. * * NOTE: It is not necessary to adjust the IAG * Free Extent List, the IAG Free Inodes List, * or the Free IAG List because they will be * rebuilt from scratch before the filesystem * is remounted (either near the end of logredo * processing or by fsck after logredo returns * control to it with rc != 0) * * NOTE: The wmap of the IAG tells whether logredo * has already encountered a log record for * one of these inodes. This would mean * activity for the inode(s) LATER IN TIME * than the current transaction. If no such * record has been seen, then the IAG[extno] * needs to be cleared. */ iagnum = ld->log.noredoinoext.iagnum; imp = vopen[vol].fsimap_lst.imap_wsp[(iagnum + 1)].imap_data; if (imp == NULL) { /* first touch to this IAG */ rc = iagGet(vol, iagnum); if (rc != 0) { return (rc); } imp = vopen[vol].fsimap_lst.imap_wsp[(iagnum + 1)].imap_data; } /* end first touch to this IAG */ iagext_idx = ld->log.noredoinoext.inoext_idx; if (imp->wmap[iagext_idx] == 0) { /* no later activity for * the inodes in the range for this * inode extent. */ /* all of them are now in a determined state */ imp->wmap[iagext_idx] = 0xFFFFFFFF; /* and that state is 'not allocated' */ imp->pmap[iagext_idx] = 0x00000000; PXDlength(&(imp->inoext[iagext_idx]), 0); PXDaddress(&(imp->inoext[iagext_idx]), 0); } /* end no activity for the inodes in the range for ... */ return (0);}/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doUpdateMap(ld) * * FUNCTION: processing for LOG_UPDATEMAP record types. * * IN GENERAL * ---------- * The updatemap log record has many sub-types defined in * ld->log.updatemap.type, but in general, the log record * data describes file system block extent(s) for which * the block map (bmap) needs to be marked. * * IN PARTICULAR * ------------- * LOG_ALLOCPXD -- is written when an outline EA is allocated * * The log record data is a single PXD describing the * filesystem blocks to be marked allocated in the block map. * * LOG_ALLOCPXDLIST -- is not used in release 1 of JFS * * LOG_ALLOCXAD -- is not used in release 1 of JFS * * LOG_ALLOCXADLIST -- is not used in release 1 of JFS * * LOG_FREEPXD -- is written when a file is truncated and * a portion of the extent described by a * PXD is released * -- is written when an outline EA is freed * * The log record data is a single PXD describing the * filesystem blocks to be marked free in the block map. * * LOG_FREEPXDLIST -- is written when a file is compressed * -- is written when a file grows and the tail * cannot be extended in-place. **see note * * The log record data is a list of PXD's describing the * extents to be marked free in the block map. * * LOG_FREEXAD -- is not used in release 1 of JFS * * LOG_FREEXADLIST -- is written when a file is truncated * * The log record data is a list of XAD's describing the * extents to be marked free in the block map.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -