📄 log_map.c
字号:
if (i) { mask = ((uint32_t) (ONES << i)) >> i; pmap[w] |= mask; w++; } /* init full invalid words */ for (; w < LPERDMAP; w++) pmap[w] = ONES; } return 0;}/*************************************************************** * NAME: bMapRead() * * FUNCTION: Read the requested block map page from the device * into the specified buffer. * * NOTES: * */int bMapRead(int vol, /* index in vopen array */ int32_t page_number, /* block map page offset to read */ void *page_buffer){ /* where to put the page read */ int bmr_rc = 0; /* * read in the map page */ bmr_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].bmap_wsp[page_number]. page_offset, PSIZE, page_buffer, GET); if (bmr_rc != 0) { fsck_send_msg(lrdo_RBMPREADDATFAIL); return (BMAP_READERROR7); } return (bmr_rc);}/*************************************************************** * NAME: bMapWrite() * * FUNCTION: Write the contents of the given buffer to the specified * block map page on the device * * NOTES: * */int bMapWrite(int vol, /* index in vopen array */ int32_t page_number, /* where to write the page */ void *page_buffer){ /* where get the data to write */ int bmw_rc = 0; /* * write out the map page */ bmw_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].bmap_wsp[page_number]. page_offset, PSIZE, page_buffer, PUT); if (bmw_rc != 0) { fsck_send_msg(lrdo_WRBMPBLKWRITEFAIL, (long long)vopen[vol].bmap_wsp[page_number].page_offset); return (BMAP_WRITEERROR2); } return (bmw_rc);}/*************************************************************** * NAME: dMapGet() * * FUNCTION: Calculate the page position (in the block map) of the * requested dmap page. Read it into the dmap buffer, * allocate a bit map record for it, copy the pmap from the * page read into the bit map record and then initialize the * wmap in the bit map record. * * NOTES: If we are unable to allocate storage, we'll reset some * stuff so that the storage already allocated to the block * map is released (for other use by logredo) and then * continue processing without further updates to the block * map. (In this case, when we return to fsck we'll pass * a return code which will ensure that full fsck will be * done. The full fsck includes rebuilding the block map, * so this provides the data protection of logredo even if not * the performance of logredo alone.) * */int dMapGet(int vol, /* index in vopen array */ int32_t dmap_num){ /* the ordinal dmap page wanted */ int dmg_rc = 0; int64_t page_needed; struct dmap_bitmaps *dmap_bitrec; struct dmap *dmap_pg; int32_t maplen; /* * figure out the map page needed */ page_needed = DMAPTOBMAPN(dmap_num); /* * read in the map page */ dmg_rc = bMapRead(vol, page_needed, (void *) vopen[vol].dmap_pbuf); if (dmg_rc != 0) { return (dmg_rc); } ujfs_swap_dmap(vopen[vol].dmap_pbuf); vopen[vol].dmap_pagenum = page_needed; /* * allocate and set up a bitmap workspace for this page */ dmg_rc = alloc_dmap_bitrec(&dmap_bitrec); if ((dmg_rc == 0) && !Insuff_memory_for_maps) { dmap_pg = vopen[vol].dmap_pbuf; maplen = sizeof (uint32_t) * LPERDMAP; memset((void *) &(dmap_bitrec->wmap), 0, maplen); memcpy((void *) &(dmap_bitrec->pmap), (void *) &(dmap_pg->pmap), maplen); vopen[vol].bmap_wsp[page_needed].dmap_bitmaps = dmap_bitrec; } return (dmg_rc);}/* * NAME: iMapInit() * * FUNCTION: Calculate the number of pages in the fileset Inode Map. * Allocate an array of records so there is one for each * page in the map. Initialize each array element with the * aggregate offset of the page it describes. * * Allocate a page buffer for IAGs. * * Read in the map control page. * * * NOTES: * Regarding extendfs, * allocate storage for a map, read it into memory, and * initialize workmap to zeros. recompute on the basis of * the file system size and allocation group sizes in the filesystem * superblock the number of allocation groups and the size of map. * (ie the size info in the map is not trusted). this is done to * recover from a crash in the middle of extending a filesystem. * depending on where the crash occurred, the extendfs will be * completed here, or backed-out. in backing out, the map * considered as files may be bigger than neceassry, but logically * this causes no problem: extendfs can be re-run, and the extra * data not accessed before then. */int iMapInit(int vol, /* index in vopen array */ struct dinode *dp){ /* disk inode of map */ int imi_rc; int32_t bytes_needed, map_pages; int32_t allocated_from_bmap = 0; int64_t nbytes, xaddr; char *ptr0 = NULL; int32_t i, j, pgidx; xtpage_t *p; /* xtree page */ pxd_t pxd; /* * figure out how many pages there are in the map, and * from that the size array we need, and from that the * number of bytes to allocate now. * * Note that we also allocate * a page so we fcan start on a page boundary * a page for the IMap control page * a page buffer for reading and writing IAGs * a page buffer for reading and writing IAGs * (when rebuilding the by-AG lists we need a 2nd buffer) */ vopen[vol].fsimap_lst.fileset = __le32_to_cpu(dp->di_number); vopen[vol].fsimap_lst.next = NULL; /* in rel 1, only one fileset */ vopen[vol].fsimap_lst.imap_page_count = __le64_to_cpu(dp->di_size) / PSIZE; bytes_needed = (4 * PSIZE) + (vopen[vol].fsimap_lst.imap_page_count * sizeof (struct imap_wsp)); /* allocate storage for imap. the size is always a multiple * of PSIZE so we don't have to round it up. * di_size is number of bytes */ imi_rc = alloc_storage((uint32_t) bytes_needed, (void **) &ptr0, &allocated_from_bmap); if ((imi_rc != 0) || (ptr0 == NULL)) { /* imap allocation failed */ fsck_send_msg(lrdo_ALLOC4IMAPFAIL, bytes_needed); return (ENOMEM2); } else if (ptr0 != NULL) { /* imap allocation successful */ if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4IMAP); } } /* end imap allocation successful */ /* * take it to a page boundary and parcel it out */ ptr0 = (char *) (((((size_t) ptr0) + PSIZE - 1) / PSIZE) * PSIZE); vopen[vol].fsimap_lst.fsimapctrl = (struct dinomap *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.iag_pbuf = (struct iag *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.iag_pbuf2 = (struct iag *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.imap_wsp = (struct imap_wsp *) ptr0; /* * set the record to say the buffer is currently empty */ vopen[vol].fsimap_lst.imap_pagenum = -1; /* * Initialize the IMap workspace array with aggregate offsets */ /* * from the xtroot, go down to the xtree leaves * which have the xad's for the map data */ if (rXtree(vol, dp, &p)) { fsck_send_msg(lrdo_RIMPREADXTFAIL); return (IMAP_READERROR1); } /* * Initialize the IMap workspace array with aggregate offsets */ pgidx = 0; /* * read in the leftmost leaf page of the * inode allocation map xtree */ if (rXtree(vol, dp, &p)) { fsck_send_msg(lrdo_RIMPREADXTFAIL); return (IMAP_READERROR2); } /* * in case of leaf root, init next sibling pointer so it will * appear as last non-root leaf page termination */ if (p->header.flag & BT_ROOT) p->header.next = 0; /* * the leaf pages contain the aggregate offsets we need */ PXDlength(&pxd, vopen[vol].lbperpage); do { /* * get extent descriptors from the current leaf */ for (i = XTENTRYSTART; i < __le16_to_cpu(p->header.nextindex); i++) { xaddr = addressXAD(&p->xad[i]) << vopen[vol].l2bsize; nbytes = lengthXAD(&p->xad[i]) << vopen[vol].l2bsize; map_pages = nbytes / PSIZE; /* * get page offsets from the current extent descriptor */ for (j = 0; j < map_pages; j++) { vopen[vol].fsimap_lst.imap_wsp[pgidx]. page_offset = xaddr + (j * PSIZE); pgidx++; } } /* * read in the next leaf (if any) */ xaddr = __le64_to_cpu(p->header.next); if (xaddr) { PXDaddress(&pxd, xaddr); if (bread(vol, pxd, (void **) &p, PB_READ)) { fsck_send_msg(lrdo_RIMPREADNXTLFFAIL); return (IMAP_READERROR3); } } } while (xaddr); /* * Now read in the map control page */ imi_rc = iMapRead(vol, 0, (void *) vopen[vol].fsimap_lst.fsimapctrl); if (imi_rc != 0) { return (imi_rc); } ujfs_swap_dinomap(vopen[vol].fsimap_lst.fsimapctrl); return (0);}/*************************************************************** * NAME: iMapRead() * * FUNCTION: Read the requested inode map page from the device * into the specified buffer. * * NOTES: * */int iMapRead(int vol, /* index in vopen array */ int32_t page_number, /* map page offset to read */ void *page_buffer){ /* where to put the page read */ int imr_rc = 0; /* * read in the map page */ imr_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].fsimap_lst.imap_wsp[page_number].page_offset, PSIZE, page_buffer, GET); if (imr_rc != 0) { fsck_send_msg(lrdo_RIMPREADDATFAIL); return (IMAP_READERROR4); } return (imr_rc);}/*************************************************************** * NAME: iMapWrite() * * FUNCTION: Write the contents of the given buffer to the specified * inode map page on the device * * NOTES: * */int iMapWrite(int vol, /* index in vopen array */ int32_t page_number, /* where to write the page */ void *page_buffer){ /* where get the data to write */ int imw_rc = 0; /* * write out the map page */ imw_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].fsimap_lst.imap_wsp[page_number].page_offset, PSIZE, page_buffer, PUT); if (imw_rc != 0) { fsck_send_msg(lrdo_WRIMPBLKWRITEFAIL, (long long)vopen[vol].bmap_wsp[page_number].page_offset); return (IMAP_WRITEERROR2); } return (imw_rc);}/*************************************************************** * NAME: iagGet() * * FUNCTION: Read the requested iag into the iag page buffer, allocate * a data record for it, copy the pmap and inoext array from * the page read into the data and then initialize the wmap * in the data record. * * NOTES: * */int iagGet(int vol, /* index in vopen array */ int32_t iag_num){ /* the iag number of the iag wanted */ int ig_rc = 0; int32_t bytes_needed; int32_t allocated_from_bmap = 0; struct iag_data *iag_datarec; struct iag *iag_pg; int32_t maplen, inoext_arrlen; /* * read in the map page */ ig_rc = iMapRead(vol, (iag_num + 1), (void *) vopen[vol].fsimap_lst.iag_pbuf); if (ig_rc != 0) { return (ig_rc); } ujfs_swap_iag(vopen[vol].fsimap_lst.iag_pbuf); vopen[vol].fsimap_lst.imap_pagenum = iag_num + 1; /* * allocate and set up a data workspace for this page */ bytes_needed = sizeof (struct iag_data); ig_rc = alloc_storage((uint32_t) bytes_needed, (void **) &iag_datarec, &allocated_from_bmap); if ((ig_rc != 0) || (iag_datarec == NULL)) { fsck_send_msg(lrdo_ALLOC4IMAPFAIL, bytes_needed); return (ENOMEM2); } if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4IMAP); } iag_pg = vopen[vol].fsimap_lst.iag_pbuf; maplen = sizeof (uint32_t) * LPERDMAP; inoext_arrlen = sizeof (pxd_t) * EXTSPERIAG; memset((void *) &(iag_datarec->wmap), 0, maplen); memcpy((void *) &(iag_datarec->pmap), (void *) &(iag_pg->pmap), maplen); memcpy((void *) &(iag_datarec->inoext), (void *) &(iag_pg->inoext), inoext_arrlen); vopen[vol].fsimap_lst.imap_wsp[(iag_num + 1)].imap_data = iag_datarec; return 0;}/* * NAME: updateMaps(vol) * * FUNCTION: finalize and write out both imap and bmap. * * NOTE: Imaps update must be before the bmap update * because we need to change bmap while rebuild the imaps. */int updateMaps(int32_t vol){ /* index in vopen array */ int rc; struct dinode *dip; pxd_t pxd1; /* * update fileset inode allocation map */ /* read in the fileset imap inode (i_number = 16) in a buffer: */ PXDaddress(&pxd1, (AITBL_OFF + (SIZE_OF_MAP_PAGE << 1)) >> vopen[vol].l2bsize); PXDlength(&pxd1, vopen[vol].lbperpage); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_UMPREADIMAPINOFAIL); return (IMAP_READERROR5); } /* locate the inode in the buffer page */ dip += FILESYSTEM_I & 0x07; /* finalize the imap and write it out */ if ((rc = writeImap(vol, vopen[vol].fsimap_lst, dip)) != 0) { fsck_send_msg(lrdo_UMPWRITEIMAPCTLFAIL); return (rc); } /* * if we were able to allocate enough storage for the BMap, * update file system block allocation map * * (Otherwise we'll let fsck be responsible for the BMap) */ if (!Insuff_memory_for_maps) { /* we do have a local BMap image */ /* read in the bmap inode (i_number = 2) in a buffer: */ PXDaddress(&pxd1, AITBL_OFF >> vopen[vol].l2bsize); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_UMPREADBMAPINOFAIL); return (BMAP_READERROR4); } /* locate the inode in the buffer page */ dip += BMAP_I; /* finalize the bmap and write it out */ if ((rc = writeBmap(vol, vopen[vol].bmap_ctl, dip)) != 0) { fsck_send_msg(lrdo_UMPWRITEBMAPCTLFAIL); } } /* end we do have a local BMap image */ return (rc);}/* * NAME: writeImap() * * FUNCTION: copy permanent map to work map. Rebuild control information * for each iag page. Then rebuild the imap control page. * We assume the iagnum is correct at the beginning of logredo. * */int writeImap(int vol, /* index in vopen array */ struct fsimap_lst fsimap, /* fileset imap workspace */ struct dinode *dp){ /* disk inode of imap */ struct dinomap *imap_ctl; int rc; int32_t k, iagpages, npages, next_iag;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -