📄 initmap.c
字号:
control_page->dn_aglevel * L2LPERCTL); control_page->dn_agheigth = l2nl >> 1; control_page->dn_agwidth = 1 << (l2nl - (control_page->dn_agheigth << 1)); for (index = 5 - control_page->dn_agheigth, control_page->dn_agstart = 0, n = 1; index > 0; index--) { control_page->dn_agstart += n; n <<= 2; } /* control_page->dn_maxag is computed at finalization */ control_page->dn_agpref = 0;}/*-------------------------------------------------------------------- * NAME: calc_map_size() * * FUNCTION: Calculates the size of a block map and * initializes memory for dmap pages of map. * Later when we are ready to write the map to disk * we will initialize the rest of the map pages. * * N.B. map file is ALLOCATED as a single extent * of physical pages covering full control level (L2) * tree control pages for the dmap pages required: * the tree will be INITIALIZED to cover only the * the dmap pages required; * * PARAMETERS: * number_of_blocks - Number of blocks in aggregate * aggr_inodes - Array of aggregate inodes * aggr_block_size - Aggregate block size * ag_size - Will be filled in with AG size in blocks * inostamp - Inode stamp value to be used. * * RETURNS: 0 for success */int calc_map_size(int64_t number_of_blocks, struct dinode *aggr_inodes, int aggr_block_size, int *ag_size, unsigned inostamp){ int rc = 0; int64_t npages, ndmaps, nl0pages; int64_t nb_diskmap; int64_t size_of_map; int64_t location; /* * compute the number dmap pages required to cover number_of_blocks; * add one extra dmap page for extendfs(): this is added before * we figure out how many control pages are needed, so we get * the correct number of control pages. */ npages = ndmaps = ((number_of_blocks + BPERDMAP - 1) >> L2BPERDMAP) + 1; /* * Make sure the number of dmaps needed is within the supported range */ if ((((int64_t) ndmaps) << L2BPERDMAP) > MAXMAPSIZE) return (EINVAL); /* * compute number of (logical) control pages at each level of the map */ /* account for L0 pages to cover dmap pages */ nl0pages = (ndmaps + LPERCTL - 1) >> L2LPERCTL; npages += nl0pages; if (nl0pages > 1) { /* account for one L2 and actual L1 pages to cover L0 pages */ npages += 1 + ((nl0pages + LPERCTL - 1) >> L2LPERCTL); } else { /* account for one logical L2 and one logical L1 pages */ npages += 2; } /* account for global control page of map */ npages++; /* * init the block allocation map inode */ size_of_map = npages << L2PSIZE; nb_diskmap = size_of_map / aggr_block_size; location = BMAP_OFF / aggr_block_size; init_inode(&(aggr_inodes[BMAP_I]), AGGREGATE_I, /* di_fileset */ BMAP_I, /* di_number */ nb_diskmap, /* di_nblocks */ size_of_map, /* di_size */ location, IFJOURNAL | IFREG, /* di_mode */ max_extent_data, AITBL_OFF / aggr_block_size, aggr_block_size, inostamp); /* * Allocate dmap pages and initialize them for the aggregate blocks */ if ((rc = alloc_map(ndmaps)) != 0) return rc; initmap(number_of_blocks, ag_size, aggr_block_size); /* * reset last_allocated to ignore the fsck working space */ last_allocated = 0; return 0;}/*-------------------------------------------------------------------- * NAME: markit() * * FUNCTION: Mark specified block allocated/unallocated in block map * * PARAMETERS: * block - Map object to set or clear * flag - Indicates ALLOCATE or FREE of block. Indicates if block is * bad. * * RETURNS: NONE */int markit(int block, unsigned flag){ int page, rem, word, bit; struct dmap *p1; int agno; int64_t num_blocks_left, nb; /* * Keep track of the last allocated block to be filled into block map * inode. Don't update last allocated for bad blocks. */ if (block > last_allocated && !(flag & BADBLOCK)) { last_allocated = block; } /* * calculate page number in map, and word and bit number in word. */ page = block / BPERDMAP; rem = block - page * BPERDMAP; word = rem >> L2DBWORD; bit = rem - (word << L2DBWORD); if (page > sz_block_map_array) { fprintf(stderr, "Internal error: %s(%d): Trying to mark block which doesn't exist.\n", __FILE__, __LINE__); return (-1); } /* * Determine if this dmap page has been allocated yet */ if (block_map_array[page] == NULL) { num_blocks_left = control_page->dn_mapsize - (page * BPERDMAP); nb = MIN(BPERDMAP, num_blocks_left); block_map_array[page] = malloc(sizeof (struct dmap)); if (block_map_array[page] == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(block_map_array[page], 0, sizeof (struct dmap)); ujfs_idmap_page(block_map_array[page], nb); } p1 = block_map_array[page]; agno = block >> control_page->dn_agl2size; /* * now we process the first word. */ if (flag & ALLOC) { p1->pmap[word] |= (UZWORD >> bit); p1->wmap[word] |= (UZWORD >> bit); /* * Update the stats */ p1->nfree--; control_page->dn_nfree--; control_page->dn_agfree[agno]--; } else { p1->pmap[word] &= ~(UZWORD >> bit); p1->wmap[word] &= ~(UZWORD >> bit); /* * Update the stats */ p1->nfree++; control_page->dn_nfree++; control_page->dn_agfree[agno]++; } return (0);}/*-------------------------------------------------------------------- * NAME: write_block_map() * * FUNCTION: Update tree part of block map to match rest of map and * then write the block map to disk. * Also write the block map inode to disk. * * PARAMETERS: * dev_ptr - open port of device to write map to * size_of_map - size of map * aggr_block_size - size of an aggregate block in bytes * * RETURNS: 0 for success */int write_block_map(FILE *dev_ptr, int64_t number_of_blocks, int aggr_block_size){ int rc = 0; /* * At this point all of the dmaps have been initialized except for their * trees. Now we need to build the other levels of the map and adjust * the tree for each of the dmaps. */ cur_dmap_index = 0; control_page->dn_maxag = last_allocated / control_page->dn_agsize; rc = initbmap(dev_ptr, number_of_blocks); return rc;}/*-------------------------------------------------------------------- * NAME: dbAlloc * * FUNCTION: Allocate the specified number of blocks * * PARAMETERS: * xlen - Number of blocks to allocate * xaddr - On return, filled in with starting block number of allocated * blocks * * NOTES: * This function is only called when adding blocks to the Bad Block Inode * required a page for an xtree node. LVM Bad Block processing must * be in effect during this allocation. This will not be the case if format * is processing /L. So, at entry to this routine, we check to see whether * the LVM Bad Block processing is enabled and, if not, we enable it. * At exit from this routine the LVM Bad Block processing will be as it * was (i.e., enabled or disabled) on entry. * * RETURNS: 0 for success; Other indicates failure */static int dbAlloc(FILE *dev_ptr, int64_t xlen, int64_t * xaddr){ int rc = 0; int page, word; struct dmap *p1; int64_t last_block, index; unsigned mask, cmap; int bitno; int l2nb; int8_t leafw; /* * Start looking at last block allocated for a contiguous extent of xlen * blocks. Since we may have bad blocks intermixed we can't just * take blocks starting at the last block allocated. However, * last_allocated won't be updated with bad blocks, so it will be the * start of the real last place to start looking. Once found, mark them * allocated and return the starting address in xaddr */ l2nb = log2shift(xlen); for (page = last_allocated / BPERDMAP, word = (last_allocated & (BPERDMAP - 1)) >> L2DBWORD; page < sz_block_map_array; page++, word = 0) { /* * Determine if this dmap page has been allocated yet; if not we * can take the first blocks from it for our allocation since we * know all the blocks in it are free. (markit will handle * allocating the page for us, so we don't have to do that here.) */ if (block_map_array[page] == NULL) { *xaddr = page << L2BPERDMAP; last_block = *xaddr + xlen; for (index = *xaddr; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) { return rc; } return 0; } /* * We have a dmap page which has had allocations before, we need * to check for free blocks starting with <word> to the end of * this dmap page. If we don't find it in this page we will go * on to the next page. */ p1 = block_map_array[page]; for (; word < LPERDMAP; word++) { /* * Determine if the leaf describes sufficient free space. * Since we have not yet completed the block map * initialization we will have to compute this on the-fly. */ leafw = ujfs_maxbuddy((char *) &p1->wmap[word]); if (leafw < l2nb) continue; /* * We know this word has sufficient free space, find it * and allocate it */ *xaddr = (page << L2BPERDMAP) + (word << L2DBWORD); if (leafw < BUDMIN) { mask = ONES << (DBWORD - xlen); cmap = ~(p1->wmap[word]); /* scan the word for xlen free bits */ for (bitno = 0; mask != 0; bitno++, mask >>= 1) { if ((mask & cmap) == mask) break; } *xaddr += bitno; } /* Allocate the blocks */ last_block = *xaddr + xlen; for (index = *xaddr; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) { return (rc); } return 0; } } return 1;}/*-------------------------------------------------------------------- * NAME: xtSplitRoot * * FUNCTION: Split full root of xtree * * PARAMETERS: * dev_ptr - Device handle * ip - Inode of xtree * xroot - Root of xtree * offset - Offset of extent to add * nblocks - number of blocks for extent to add * blkno - starting block of extent to add * * RETURNS: 0 for success; Other indicates failure */static int xtSplitRoot(FILE *dev_ptr, struct dinode *ip, struct xtree_buf *xroot, int64_t offset, int nblocks, int64_t blkno){ xtpage_t *rootpage; xtpage_t *newpage; int64_t xaddr; int nextindex; xad_t *xad; int rc = 0; struct xtree_buf *newbuf; int xlen; /* Allocate and initialize buffer for new page to accomodate the split */ newbuf = malloc(sizeof (struct xtree_buf)); if (newbuf == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } newbuf->up = xroot; if (xroot->down == NULL) { badblock_pages = newbuf; } else { xroot->down->up = newbuf; } newbuf->down = xroot->down; xroot->down = newbuf; newpage = newbuf->page = malloc(PSIZE); if (newpage == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } /* Allocate disk blocks for new page */ xlen = 1 << control_page->dn_l2nbperpage; if ((rc = dbAlloc(dev_ptr, xlen, &xaddr))) return rc; rootpage = xroot->page; /* Initialize new page */ newpage->header.flag = (rootpage->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL; PXDlength(&(newpage->header.self), xlen); PXDaddress(&(newpage->header.self), xaddr); newpage->header.nextindex = XTENTRYSTART; newpage->header.maxentry = PSIZE >> L2XTSLOTSIZE; /* initialize sibling pointers */ newpage->header.next = 0; newpage->header.prev = 0; /* copy the in-line root page into new right page extent */ nextindex = rootpage->header.maxentry; memcpy(&newpage->xad[XTENTRYSTART], &rootpage->xad[XTENTRYSTART], (nextindex - XTENTRYSTART) << L2XTSLOTSIZE); /* insert the new entry into the new right/child page */ xad = &newpage->xad[nextindex]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); /* update page header */ newpage->header.nextindex = nextindex + 1; /* init root with the single entry for the new right page */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -