/* * reconfigure LV spaces * --------------------- * * validate new size, or, if not specified, determine new size
*/
/* * reconfigure inline log space:
*/ if ((sbi->mntflag & JFS_INLINELOG)) { if (newLogSize == 0) { /* * no size specified: default to 1/256 of aggregate * size; rounded up to a megabyte boundary;
*/
newLogSize = newLVSize >> 8;
t32 = (1 << (20 - sbi->l2bsize)) - 1;
newLogSize = (newLogSize + t32) & ~t32;
newLogSize =
min(newLogSize, MEGABYTE32 >> sbi->l2bsize);
} else { /* * convert the newLogSize to fs blocks. * * Since this is given in megabytes, it will always be * an even number of pages.
*/
newLogSize = (newLogSize * MEGABYTE) >> sbi->l2bsize;
}
} else
newLogSize = 0;
newLogAddress = newLVSize - newLogSize;
/* * reconfigure fsck work space: * * configure it to the end of the logical volume regardless of * whether file system extends to the end of the aggregate; * Need enough 4k pages to cover: * - 1 bit per block in aggregate rounded up to BPERDMAP boundary * - 1 extra page to handle control page and intermediate level pages * - 50 extra pages for the chkdsk service log
*/
t64 = ((newLVSize - newLogSize + BPERDMAP - 1) >> L2BPERDMAP)
<< L2BPERDMAP;
t32 = DIV_ROUND_UP(t64, BITSPERPAGE) + 1 + 50;
newFSCKSize = t32 << sbi->l2nbperpage;
newFSCKAddress = newLogAddress - newFSCKSize;
/* * compute new file system space;
*/
newFSSize = newLVSize - newLogSize - newFSCKSize;
/* file system cannot be shrunk */ if (newFSSize < bmp->db_mapsize) {
rc = -EINVAL; goto out;
}
/* * If we're expanding enough that the inline log does not overlap * the old one, we can format the new log before we quiesce the * filesystem.
*/ if ((sbi->mntflag & JFS_INLINELOG) && (newLogAddress > oldLVSize)) { if ((rc = lmLogFormat(log, newLogAddress, newLogSize))) goto out;
log_formatted = 1;
} /* * quiesce file system * * (prepare to move the inline log and to prevent map update) * * block any new transactions and wait for completion of * all wip transactions and flush modified pages s.t. * on-disk file system is in consistent state and * log is not required for recovery.
*/
txQuiesce(sb);
/* Reset size of direct inode */
sbi->direct_inode->i_size = bdev_nr_bytes(sb->s_bdev);
if (sbi->mntflag & JFS_INLINELOG) { /* * deactivate old inline log
*/
lmLogShutdown(log);
/* * mark on-disk super block for fs in transition; * * update on-disk superblock for the new space configuration * of inline log space and fsck work space descriptors: * N.B. FS descriptor is NOT updated; * * crash recovery: * logredo(): if FM_EXTENDFS, return to fsck() for cleanup; * fsck(): if FM_EXTENDFS, reformat inline log and fsck * workspace from superblock inline log descriptor and fsck * workspace descriptor;
*/
/* read in superblock */ if ((rc = readSuper(sb, &bh))) goto error_out;
j_sb = (struct jfs_superblock *)bh->b_data;
/* mark extendfs() in progress */
j_sb->s_state |= cpu_to_le32(FM_EXTENDFS);
j_sb->s_xsize = cpu_to_le64(newFSSize);
PXDaddress(&j_sb->s_xfsckpxd, newFSCKAddress);
PXDlength(&j_sb->s_xfsckpxd, newFSCKSize);
PXDaddress(&j_sb->s_xlogpxd, newLogAddress);
PXDlength(&j_sb->s_xlogpxd, newLogSize);
/* * format new inline log synchronously; * * crash recovery: if log move in progress, * reformat log and exit success;
*/ if (!log_formatted) if ((rc = lmLogFormat(log, newLogAddress, newLogSize))) goto error_out;
/* * extend block allocation map * --------------------------- * * extendfs() for new extension, retry after crash recovery; * * note: both logredo() and fsck() rebuild map from * the bitmap and configuration parameter from superblock * (disregarding all other control information in the map); * * superblock: * s_size: aggregate size in physical blocks;
*/ /* * compute the new block allocation map configuration * * map dinode: * di_size: map file size in byte; * di_nblocks: number of blocks allocated for map file; * di_mapsize: number of blocks in aggregate (covered by map); * map control page: * db_mapsize: number of blocks in aggregate (covered by map);
*/
newMapSize = newFSSize; /* number of data pages of new bmap file: * roundup new size to full dmap page boundary and * add 1 extra dmap page for next extendfs()
*/
t64 = (newMapSize - 1) + BPERDMAP;
newNpages = BLKTODMAPN(t64) + 1;
/* * extend map from current map (WITHOUT growing mapfile) * * map new extension with unmapped part of the last partial * dmap page, if applicable, and extra page(s) allocated * at end of bmap by mkfs() or previous extendfs();
*/
extendBmap: /* compute number of blocks requested to extend */
mapSize = bmp->db_mapsize;
XAddress = mapSize; /* eXtension Address */
XSize = newMapSize - mapSize; /* eXtension Size */
old_agsize = bmp->db_agsize; /* We need to know if this changes */
/* compute number of blocks that can be extended by current mapfile */
t64 = dbMapFileSizeToMapSize(ipbmap); if (mapSize > t64) {
printk(KERN_ERR "jfs_extendfs: mapSize (0x%Lx) > t64 (0x%Lx)\n",
(longlong) mapSize, (longlong) t64);
rc = -EIO; goto error_out;
}
nblocks = min(t64 - mapSize, XSize);
/* * update map pages for new extension: * * update/init dmap and bubble up the control hierarchy * incrementally fold up dmaps into upper levels; * update bmap control page;
*/ if ((rc = dbExtendFS(ipbmap, XAddress, nblocks))) goto error_out;
agsizechanged |= (bmp->db_agsize != old_agsize);
/* * the map now has extended to cover additional nblocks: * dn_mapsize = oldMapsize + nblocks;
*/ /* ipbmap->i_mapsize += nblocks; */
XSize -= nblocks;
/* * grow map file to cover remaining extension * and/or one extra dmap page for next extendfs(); * * allocate new map pages and its backing blocks, and * update map file xtree
*/ /* compute number of data pages of current bmap file */
nPages = ipbmap->i_size >> L2PSIZE;
/* need to grow map file ? */ if (nPages == newNpages) goto finalizeBmap;
/* * grow bmap file for the new map pages required: * * allocate growth at the start of newly extended region; * bmap file only grows sequentially, i.e., both data pages * and possibly xtree index pages may grow in append mode, * s.t. logredo() can reconstruct pre-extension state * by washing away bmap file of pages outside s_size boundary;
*/ /* * journal map file growth as if a regular file growth: * (note: bmap is created with di_mode = IFJOURNAL|IFREG); * * journaling of bmap file growth is not required since * logredo() do/can not use log records of bmap file growth * but it provides careful write semantics, pmap update, etc.;
*/ /* synchronous write of data pages: bmap data pages are * cached in meta-data cache, and not written out * by txCommit();
*/
rc = filemap_fdatawait(ipbmap->i_mapping); if (rc) goto error_out;
rc = filemap_write_and_wait(ipbmap->i_mapping); if (rc) goto error_out;
/* * map file has been grown now to cover extension to further out; * di_size = new map file size; * * if huge extension, the previous extension based on previous * map file size may not have been sufficient to cover whole extension * (it could have been used up for new map pages), * but the newly grown map file now covers lot bigger new free space * available for further extension of map;
*/ /* any more blocks to extend ? */ if (XSize) goto extendBmap;
/* * update inode allocation map * --------------------------- * * move iag lists from old to new iag; * agstart field is not updated for logredo() to reconstruct * iag lists if system crash occurs. * (computation of ag number from agstart based on agsize * will correctly identify the new ag);
*/ /* if new AG size the same as old AG size, done! */ if (agsizechanged) { if ((rc = diExtendFS(ipimap, ipbmap))) goto error_out;
/* * finalize * -------- * * extension is committed when on-disk super block is * updated with new descriptors: logredo will recover * crash before it to pre-extension state;
*/
/* sync log to skip log replay of bmap file growth transaction; */ /* lmLogSync(log, 1); */
/* * synchronous write bmap global control page; * for crash before completion of write * logredo() will recover to pre-extendfs state; * for crash after completion of write, * logredo() will recover post-extendfs state;
*/ if ((rc = dbSync(ipbmap))) goto error_out;
/* update inline log space descriptor */ if (sbi->mntflag & JFS_INLINELOG) {
PXDaddress(&(j_sb->s_logpxd), newLogAddress);
PXDlength(&(j_sb->s_logpxd), newLogSize);
}
/* record log's mount serial number */
j_sb->s_logserial = cpu_to_le32(log->serial);
/* update fsck work space descriptor */
PXDaddress(&(j_sb->s_fsckpxd), newFSCKAddress);
PXDlength(&(j_sb->s_fsckpxd), newFSCKSize);
j_sb->s_fscklog = 1; /* sb->s_fsckloglen remains the same */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.