diff options
author | Theodore Ts'o <tytso@mit.edu> | 1997-06-14 07:28:44 +0000 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 1997-06-14 07:28:44 +0000 |
commit | 05e112a11b6508c2b12d5d4ee0c322171db9b538 (patch) | |
tree | 97565bb8c8b2eb1b846ae6266346f1df5204ac68 /resize | |
parent | 36f21439f5d8b2233d13e042833d4d921a5c2c40 (diff) | |
download | e2fsprogs-05e112a11b6508c2b12d5d4ee0c322171db9b538.tar.gz |
ChangeLog, Makefile.in, version.h:
Allow people to set the version.h to something like 1.10-PLUS.
.del-inodemap.c~24510e64, main.c, resize2fs.c, resize2fs.h:
More interim work. All is functioning except progress meter.
Diffstat (limited to 'resize')
-rw-r--r-- | resize/inodemap.c | 24 | ||||
-rw-r--r-- | resize/main.c | 24 | ||||
-rw-r--r-- | resize/resize2fs.c | 146 | ||||
-rw-r--r-- | resize/resize2fs.h | 14 |
4 files changed, 146 insertions, 62 deletions
diff --git a/resize/inodemap.c b/resize/inodemap.c index 9dc3db25..8f419e6c 100644 --- a/resize/inodemap.c +++ b/resize/inodemap.c @@ -136,23 +136,29 @@ static ino_t inode_map_translate(inode_map imap, ino_t old) return 0; } +struct istruct { + inode_map imap; + int flags; +}; + int check_and_change_inodes(ino_t dir, int entry, struct ext2_dir_entry *dirent, int offset, int blocksize, char *buf, void *private) { - inode_map imap = private; + struct istruct *is = private; ino_t new; if (!dirent->inode) return 0; - new = inode_map_translate(imap, dirent->inode); + new = inode_map_translate(is->imap, dirent->inode); if (!new) return 0; - - printf("Inode translate (dir=%ld, name=%.*s, %ld->%ld)\n", - dir, dirent->name_len, dirent->name, dirent->inode, new); + if (is->flags & RESIZE_DEBUG_INODEMAP) + printf("Inode translate (dir=%ld, name=%.*s, %ld->%ld)\n", + dir, dirent->name_len, dirent->name, + dirent->inode, new); dirent->inode = new; @@ -167,6 +173,7 @@ errcode_t ext2fs_inode_move(ext2_resize_t rfs) inode_map imap; errcode_t retval; int group; + struct istruct is; if (rfs->old_fs->group_desc_count <= rfs->new_fs->group_desc_count) @@ -222,7 +229,8 @@ errcode_t ext2fs_inode_move(ext2_resize_t rfs) if (LINUX_S_ISDIR(inode.i_mode)) rfs->new_fs->group_desc[group].bg_used_dirs_count++; - printf("inode %ld->%ld\n", ino, new); + if (rfs->flags & RESIZE_DEBUG_INODEMAP) + printf("Inode moved %ld->%ld\n", ino, new); add_inode_map_entry(imap, ino, new); } @@ -230,8 +238,10 @@ errcode_t ext2fs_inode_move(ext2_resize_t rfs) * Now, we iterate over all of the directories to update the * inode references */ + is.imap = imap; + is.flags = rfs->flags; retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 0, 0, - check_and_change_inodes, imap); + check_and_change_inodes, &is); if (retval) return retval; diff --git a/resize/main.c b/resize/main.c index 9a53e740..3d3c589f 100644 --- a/resize/main.c +++ b/resize/main.c @@ -26,6 +26,7 @@ void main (int argc, char ** argv) errcode_t retval; ext2_filsys fs; int c; + int flags = 0; blk_t new_size; io_manager io_ptr; @@ -35,11 +36,17 @@ void main (int argc, char ** argv) if (argc && *argv) program_name = *argv; - while ((c = getopt (argc, argv, "h")) != EOF) { + while ((c = getopt (argc, argv, "d:hp")) != EOF) { switch (c) { case 'h': usage(program_name); break; + case 'd': + flags |= atoi(optarg); + break; + case 'p': + flags |= RESIZE_PERCENT_COMPLETE; + break; default: usage (program_name); } @@ -49,12 +56,13 @@ void main (int argc, char ** argv) device_name = argv[optind++]; new_size = atoi(argv[optind++]); initialize_ext2_error_table(); -#if 1 - io_ptr = unix_io_manager; -#else - io_ptr = test_io_manager; - test_io_backing_manager = unix_io_manager; -#endif + + if (flags & RESIZE_DEBUG_IO) { + io_ptr = test_io_manager; + test_io_backing_manager = unix_io_manager; + } else + io_ptr = unix_io_manager; + retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, io_ptr, &fs); if (retval) { @@ -70,7 +78,7 @@ void main (int argc, char ** argv) ext2fs_close (fs); exit (1); } - retval = resize_fs(fs, new_size); + retval = resize_fs(fs, new_size, flags); if (retval) { com_err(program_name, retval, "while trying to resize %s", device_name); diff --git a/resize/resize2fs.c b/resize/resize2fs.c index 805a64c5..b90c0759 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -8,6 +8,18 @@ * %End-Header% */ +/* + * Resizing a filesystem consists of the following phases: + * + * 1. Adjust superblock and (*) write out new parts of the inode + * table + * 2. Determine blocks which need to be relocated. + * 3. (*) Relocate blocks which must be moved, adjusting entries + * in the filesystem in the process. + * 4. (*) Move inodes which must be moved (only when shrinking a + * filesystem) + * 5. (*) Move the inode tables, if necessary. + */ #include "resize2fs.h" /* @@ -23,7 +35,6 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size) blk_t blk, group_block; unsigned long i, j; struct ext2_group_desc *new; - char *buf; int old_numblocks, numblocks, adjblocks; fs = rfs->new_fs; @@ -139,10 +150,10 @@ retry: */ if (rfs->old_fs->group_desc_count >= fs->group_desc_count) return 0; - buf = malloc(fs->blocksize); - if (!buf) + rfs->itable_buf = malloc(fs->blocksize * fs->inode_blocks_per_group); + if (!rfs->itable_buf) return ENOMEM; - memset(buf, 0, fs->blocksize); + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group); group_block = fs->super->s_first_data_block + rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group; for (i = rfs->old_fs->group_desc_count; @@ -181,13 +192,16 @@ retry: if (retval) return retval; - for (blk=fs->group_desc[i].bg_inode_table, j=0; - j < fs->inode_blocks_per_group; - blk++, j++) { - retval = io_channel_write_blk(fs->io, blk, 1, buf); - if (retval) - return retval; - } + /* + * Write out the new inode table + */ + retval = io_channel_write_blk(fs->io, + fs->group_desc[i].bg_inode_table, + fs->inode_blocks_per_group, + rfs->itable_buf); + if (retval) + return retval; + group_block += fs->super->s_blocks_per_group; } return 0; @@ -288,9 +302,9 @@ static errcode_t determine_relocations(ext2_resize_t rfs) if (blk >= (fs->group_desc[i].bg_inode_table + fs->inode_blocks_per_group)) continue; - fs->group_desc[i].bg_inode_table = 0; blk = fs->group_desc[i].bg_inode_table + fs->inode_blocks_per_group - 1; + fs->group_desc[i].bg_inode_table = 0; } if (fs->group_desc[i].bg_inode_table && fs->group_desc[i].bg_inode_bitmap && @@ -381,61 +395,94 @@ static errcode_t determine_relocations(ext2_resize_t rfs) */ errcode_t move_itables(ext2_resize_t rfs) { - int i, max; + int i, n, num, max, size, diff; ext2_filsys fs = rfs->new_fs; - char *buf; + char *cp; blk_t old, new; errcode_t retval, err; - printf("Hide the women and children --- " - "commencing inode table moves!!\n"); - max = fs->group_desc_count; if (max > rfs->old_fs->group_desc_count) max = rfs->old_fs->group_desc_count; - buf = malloc(fs->blocksize * fs->inode_blocks_per_group); - if (!buf) - return ENOMEM; + size = fs->blocksize * fs->inode_blocks_per_group; + if (!rfs->itable_buf) { + rfs->itable_buf = malloc(size); + if (!rfs->itable_buf) + return ENOMEM; + } for (i=0; i < max; i++) { old = rfs->old_fs->group_desc[i].bg_inode_table; new = fs->group_desc[i].bg_inode_table; + diff = new - old; - printf("Group %d block %ld->%ld\n", i, old, new); + if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) + printf("Itable move group %d block " + "%ld->%ld (diff %d)\n", + i, old, new, diff); - if (old == new) + if (!diff) continue; retval = io_channel_read_blk(fs->io, old, - fs->inode_blocks_per_group, buf); + fs->inode_blocks_per_group, + rfs->itable_buf); if (retval) goto backout; + /* + * The end of the inode table segment often contains + * all zeros. Find out if we have several blocks of + * zeros so we can optimize the write. + */ + for (cp = rfs->itable_buf+size, n=0; n < size; n++, cp--) + if (*cp) + break; + n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); + if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) + printf("%d blocks of zeros...\n", n); + num = fs->inode_blocks_per_group; + if (n > diff) + num -= n; + retval = io_channel_write_blk(fs->io, new, - fs->inode_blocks_per_group, buf); + num, rfs->itable_buf); if (retval) { io_channel_write_blk(fs->io, old, - fs->inode_blocks_per_group, buf); + num, rfs->itable_buf); goto backout; } + if (n > diff) { + retval = io_channel_write_blk(fs->io, + old + fs->inode_blocks_per_group, + diff, rfs->itable_buf - fs->blocksize * diff); + if (retval) + goto backout; + } + io_channel_flush(fs->io); } ext2fs_flush(rfs->new_fs); - printf("Inode table move finished.\n"); + if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) + printf("Inode table move finished.\n"); return 0; backout: - printf("Error: %s; now backing out!\n", error_message(retval)); + if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) + printf("Error: %s; now backing out!\n", error_message(retval)); while (--i >= 0) { - printf("Group %d block %ld->%ld\n", i, new, old); + if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) + printf("Group %d block %ld->%ld\n", i, new, old); old = rfs->old_fs->group_desc[i].bg_inode_table; new = fs->group_desc[i].bg_inode_table; err = io_channel_read_blk(fs->io, new, - fs->inode_blocks_per_group, buf); + fs->inode_blocks_per_group, + rfs->itable_buf); if (err) continue; err = io_channel_write_blk(fs->io, old, - fs->inode_blocks_per_group, buf); + fs->inode_blocks_per_group, + rfs->itable_buf); } return retval; } @@ -503,10 +550,11 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) /* * This is the top-level routine which does the dirty deed.... */ -errcode_t resize_fs(ext2_filsys fs, blk_t new_size) +errcode_t resize_fs(ext2_filsys fs, blk_t new_size, int flags) { ext2_resize_t rfs; errcode_t retval; + int bmove_flags; retval = ext2fs_read_bitmaps(fs); if (retval) @@ -521,6 +569,8 @@ errcode_t resize_fs(ext2_filsys fs, blk_t new_size) memset(rfs, 0, sizeof(struct ext2_resize_struct)); rfs->old_fs = fs; + rfs->flags = flags; + rfs->itable_buf = 0; retval = ext2fs_dup_handle(fs, &rfs->new_fs); if (retval) goto errout; @@ -533,49 +583,53 @@ errcode_t resize_fs(ext2_filsys fs, blk_t new_size) if (retval) goto errout; - printf("Number of free blocks: %d, Needed: %d\n", - fs->super->s_free_blocks_count, rfs->needed_blocks); + if (rfs->flags & RESIZE_DEBUG_BMOVE) + printf("Number of free blocks: %d, Needed: %d\n", + fs->super->s_free_blocks_count, rfs->needed_blocks); if (rfs->needed_blocks > fs->super->s_free_blocks_count) { retval = ENOSPC; goto errout; } - - printf("\nOld superblock:\n"); - list_super(rfs->old_fs->super); - printf("\n\nNew superblock:\n"); - list_super(rfs->new_fs->super); - printf("\n"); + bmove_flags = EXT2_BMOVE_GET_DBLIST; + if (rfs->flags & RESIZE_DEBUG_BMOVE) + bmove_flags |= EXT2_BMOVE_DEBUG; retval = ext2fs_move_blocks(rfs->old_fs, rfs->reserve_blocks, - rfs->new_fs->block_map, - EXT2_BMOVE_GET_DBLIST); + rfs->new_fs->block_map, bmove_flags); if (retval) - return retval; + goto errout; retval = ext2fs_inode_move(rfs); if (retval) - return retval; + goto errout; retval = move_itables(rfs); if (retval) - return retval; + goto errout; retval = ext2fs_calculate_summary_stats(rfs->new_fs); if (retval) - return retval; + goto errout; retval = ext2fs_close(rfs->new_fs); if (retval) - return retval; + goto errout; + + rfs->flags = flags; ext2fs_free(rfs->old_fs); + if (rfs->itable_buf) + free(rfs->itable_buf); + free(rfs); return 0; errout: if (rfs->new_fs) ext2fs_free(rfs->new_fs); + if (rfs->itable_buf) + free(rfs->itable_buf); free(rfs); return retval; } diff --git a/resize/resize2fs.h b/resize/resize2fs.h index cc500041..28297f69 100644 --- a/resize/resize2fs.h +++ b/resize/resize2fs.h @@ -32,6 +32,16 @@ #endif /* + * Flags for the resizer; most are debugging flags only + */ +#define RESIZE_DEBUG_IO 0x0001 +#define RESIZE_DEBUG_BMOVE 0x0002 +#define RESIZE_DEBUG_INODEMAP 0x0004 +#define RESIZE_DEBUG_ITABLEMOVE 0x0008 + +#define RESIZE_PERCENT_COMPLETE 0x0100 + +/* * The core state structure for the ext2 resizer */ @@ -41,9 +51,11 @@ struct ext2_resize_struct { ext2_brel block_relocate; ext2fs_block_bitmap reserve_blocks; int needed_blocks; + int flags; + char *itable_buf; }; typedef struct ext2_resize_struct *ext2_resize_t; /* prototypes */ -extern errcode_t resize_fs(ext2_filsys fs, blk_t new_size); +extern errcode_t resize_fs(ext2_filsys fs, blk_t new_size, int flags); |