X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=resize%2Fmain.c;h=e4b44354d121476cff6e0540dd53af4742b2759d;hb=5b5bd2c251d1f999eddebb4d35fc1fba6004562a;hp=0cdda32e63505f0b07d26ded7f771034d934896f;hpb=199ddaaa445e14fca8113b0db85e2576267071c9;p=tools%2Fe2fsprogs.git diff --git a/resize/main.c b/resize/main.c index 0cdda32..e4b4435 100644 --- a/resize/main.c +++ b/resize/main.c @@ -5,7 +5,7 @@ * PowerQuest, Inc. * * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o - * + * * %Begin-Header% * This file may be redistributed under the terms of the GNU Public * License. @@ -15,6 +15,7 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#include "config.h" #ifdef HAVE_GETOPT_H #include #else @@ -22,6 +23,9 @@ extern char *optarg; extern int optind; #endif #include +#ifdef HAVE_STDLIB_H +#include +#endif #include #include #include @@ -32,7 +36,8 @@ extern int optind; #include "../version.h" -char *program_name, *device_name, *io_options; +char *program_name; +static char *device_name, *io_options; static void usage (char *prog) { @@ -98,7 +103,7 @@ static void determine_fs_stride(ext2_filsys fs) { unsigned int group; unsigned long long sum; - unsigned int has_sb, prev_has_sb, num; + unsigned int has_sb, prev_has_sb = 0, num; int i_stride, b_stride; if (fs->stride) @@ -108,11 +113,11 @@ static void determine_fs_stride(ext2_filsys fs) has_sb = ext2fs_bg_has_super(fs, group); if (group == 0 || has_sb != prev_has_sb) goto next; - b_stride = fs->group_desc[group].bg_block_bitmap - - fs->group_desc[group-1].bg_block_bitmap - + b_stride = ext2fs_block_bitmap_loc(fs, group) - + ext2fs_block_bitmap_loc(fs, group - 1) - fs->super->s_blocks_per_group; - i_stride = fs->group_desc[group].bg_inode_bitmap - - fs->group_desc[group-1].bg_inode_bitmap - + i_stride = ext2fs_inode_bitmap_loc(fs, group) - + ext2fs_inode_bitmap_loc(fs, group - 1) - fs->super->s_blocks_per_group; if (b_stride != i_stride || b_stride < 0) @@ -121,7 +126,7 @@ static void determine_fs_stride(ext2_filsys fs) /* printf("group %d has stride %d\n", group, b_stride); */ sum += b_stride; num++; - + next: prev_has_sb = has_sb; } @@ -143,6 +148,18 @@ static void determine_fs_stride(ext2_filsys fs) #endif } +static void bigalloc_check(ext2_filsys fs, int force) +{ + if (!force && EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { + fprintf(stderr, "%s", _("\nResizing bigalloc file systems has " + "not been fully tested. Proceed at\n" + "your own risk! Use the force option " + "if you want to go ahead anyway.\n\n")); + exit(1); + } +} + int main (int argc, char ** argv) { errcode_t retval; @@ -155,16 +172,13 @@ int main (int argc, char ** argv) int force_min_size = 0; int print_min_size = 0; int fd, ret; - blk_t new_size = 0; - blk_t max_size = 0; + blk64_t new_size = 0; + blk64_t max_size = 0; + blk64_t min_size = 0; io_manager io_ptr; char *new_size_str = 0; int use_stride = -1; -#ifdef HAVE_FSTAT64 - struct stat64 st_buf; -#else - struct stat st_buf; -#endif + ext2fs_struct_stat st_buf; __s64 new_file_size; unsigned int sys_page_size = 4096; long sysval; @@ -176,6 +190,7 @@ int main (int argc, char ** argv) setlocale(LC_CTYPE, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); + set_com_err_gettext(gettext); #endif add_error_table(&et_ext2_error_table); @@ -223,7 +238,7 @@ int main (int argc, char ** argv) new_size_str = argv[optind++]; if (optind < argc) usage(program_name); - + io_options = strchr(device_name, '?'); if (io_options) *io_options++ = 0; @@ -238,7 +253,7 @@ int main (int argc, char ** argv) if (!mtpt) return ENOMEM; mtpt[len-1] = 0; - retval = ext2fs_check_mount_point(device_name, &mount_flags, + retval = ext2fs_check_mount_point(device_name, &mount_flags, mtpt, len); if (retval) { com_err("ext2fs_check_mount_point", retval, @@ -252,33 +267,25 @@ int main (int argc, char ** argv) len = 2 * len; } -#ifdef HAVE_OPEN64 - fd = open64(device_name, O_RDWR); -#else - fd = open(device_name, O_RDWR); -#endif + fd = ext2fs_open_file(device_name, O_RDWR, 0); if (fd < 0) { com_err("open", errno, _("while opening %s"), device_name); exit(1); } -#ifdef HAVE_FSTAT64 - ret = fstat64(fd, &st_buf); -#else - ret = fstat(fd, &st_buf); -#endif + ret = ext2fs_fstat(fd, &st_buf); if (ret < 0) { - com_err("open", errno, + com_err("open", errno, _("while getting stat information for %s"), device_name); exit(1); } - + if (flush) { retval = ext2fs_sync_device(fd, 1); if (retval) { - com_err(argv[0], retval, + com_err(argv[0], retval, _("while trying to flush %s"), device_name); exit(1); @@ -290,22 +297,39 @@ int main (int argc, char ** argv) fd = -1; } - if (flags & RESIZE_DEBUG_IO) { +#ifdef CONFIG_TESTIO_DEBUG + if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { io_ptr = test_io_manager; test_io_backing_manager = unix_io_manager; - } else + } else +#endif io_ptr = unix_io_manager; if (!(mount_flags & EXT2_MF_MOUNTED)) io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE; - retval = ext2fs_open2(device_name, io_options, io_flags, + + io_flags |= EXT2_FLAG_64BITS; + + retval = ext2fs_open2(device_name, io_options, io_flags, 0, 0, io_ptr, &fs); if (retval) { - com_err (program_name, retval, _("while trying to open %s"), - device_name); - printf (_("Couldn't find valid filesystem superblock.\n")); + com_err(program_name, retval, _("while trying to open %s"), + device_name); + printf("%s", _("Couldn't find valid filesystem superblock.\n")); exit (1); } + + if (!(mount_flags & EXT2_MF_MOUNTED)) { + if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) || + (fs->super->s_state & EXT2_ERROR_FS) || + ((fs->super->s_state & EXT2_VALID_FS) == 0))) { + fprintf(stderr, + _("Please run 'e2fsck -f %s' first.\n\n"), + device_name); + exit(1); + } + } + /* * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). @@ -315,10 +339,12 @@ int main (int argc, char ** argv) "(%s)", device_name); exit(1); } - + + min_size = calculate_minimum_resize_size(fs, flags); + if (print_min_size) { - printf("Estimated minimum size of the filesystem: %lu\n", - calculate_minimum_resize_size(fs)); + printf(_("Estimated minimum size of the filesystem: %llu\n"), + min_size); exit(0); } @@ -339,28 +365,50 @@ int main (int argc, char ** argv) * defaults and for making sure the new filesystem doesn't * exceed the partition size. */ - retval = ext2fs_get_device_size(device_name, fs->blocksize, - &max_size); + retval = ext2fs_get_device_size2(device_name, fs->blocksize, + &max_size); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while trying to determine filesystem size")); exit(1); } if (force_min_size) - new_size = calculate_minimum_resize_size(fs); + new_size = min_size; else if (new_size_str) { - new_size = parse_num_blocks(new_size_str, - fs->super->s_log_block_size); + new_size = parse_num_blocks2(new_size_str, + fs->super->s_log_block_size); + if (new_size == 0) { + com_err(program_name, 0, + _("Invalid new size: %s\n"), new_size_str); + exit(1); + } } else { new_size = max_size; /* Round down to an even multiple of a pagesize */ if (sys_page_size > fs->blocksize) new_size &= ~((sys_page_size / fs->blocksize)-1); } + if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super, + EXT4_FEATURE_INCOMPAT_64BIT)) { + /* Take 16T down to 2^32-1 blocks */ + if (new_size == (1ULL << 32)) + new_size--; + else if (new_size > (1ULL << 32)) { + com_err(program_name, 0, "%s", + _("New size too large to be " + "expressed in 32 bits\n")); + exit(1); + } + } + if (!force && new_size < min_size) { + com_err(program_name, 0, + _("New size smaller than minimum (%llu)\n"), min_size); + exit(1); + } if (use_stride >= 0) { if (use_stride >= (int) fs->super->s_blocks_per_group) { - com_err(program_name, 0, + com_err(program_name, 0, "%s", _("Invalid stride length")); exit(1); } @@ -368,14 +416,14 @@ int main (int argc, char ** argv) ext2fs_mark_super_dirty(fs); } else determine_fs_stride(fs); - + /* * If we are resizing a plain file, and it's not big enough, * automatically extend it in a sparse fashion by writing the * last requested block. */ new_file_size = ((__u64) new_size) * fs->blocksize; - if ((__u64) new_file_size > + if ((__u64) new_file_size > (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1) fd = -1; if ((new_file_size > st_buf.st_size) && @@ -386,51 +434,56 @@ int main (int argc, char ** argv) } if (!force && (new_size > max_size)) { fprintf(stderr, _("The containing partition (or device)" - " is only %u (%dk) blocks.\nYou requested a new size" - " of %u blocks.\n\n"), max_size, + " is only %llu (%dk) blocks.\nYou requested a new size" + " of %llu blocks.\n\n"), max_size, fs->blocksize / 1024, new_size); exit(1); } - if (new_size == fs->super->s_blocks_count) { - fprintf(stderr, _("The filesystem is already %u blocks " + if (new_size == ext2fs_blocks_count(fs->super)) { + fprintf(stderr, _("The filesystem is already %llu blocks " "long. Nothing to do!\n\n"), new_size); exit(0); } if (mount_flags & EXT2_MF_MOUNTED) { + bigalloc_check(fs, force); retval = online_resize_fs(fs, mtpt, &new_size, flags); } else { - if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) || - (fs->super->s_state & EXT2_ERROR_FS) || - ((fs->super->s_state & EXT2_VALID_FS) == 0))) { - fprintf(stderr, - _("Please run 'e2fsck -f %s' first.\n\n"), - device_name); - exit(1); - } - printf("Resizing the filesystem on %s to %u (%dk) blocks.\n", + bigalloc_check(fs, force); + printf(_("Resizing the filesystem on " + "%s to %llu (%dk) blocks.\n"), device_name, new_size, fs->blocksize / 1024); retval = resize_fs(fs, &new_size, flags, ((flags & RESIZE_PERCENT_COMPLETE) ? resize_progress_func : 0)); } + free(mtpt); if (retval) { com_err(program_name, retval, _("while trying to resize %s"), device_name); - ext2fs_close (fs); + fprintf(stderr, + _("Please run 'e2fsck -fy %s' to fix the filesystem\n" + "after the aborted resize operation.\n"), + device_name); + ext2fs_close_free(&fs); exit(1); } - printf(_("The filesystem on %s is now %u blocks long.\n\n"), + printf(_("The filesystem on %s is now %llu blocks long.\n\n"), device_name, new_size); if ((st_buf.st_size > new_file_size) && (fd > 0)) { #ifdef HAVE_FTRUNCATE64 - ftruncate64(fd, new_file_size); + retval = ftruncate64(fd, new_file_size); #else + retval = 0; /* Only truncate if new_file_size doesn't overflow off_t */ if (((off_t) new_file_size) == new_file_size) - ftruncate(fd, (off_t) new_file_size); + retval = ftruncate(fd, (off_t) new_file_size); #endif + if (retval) + com_err(program_name, retval, + _("while trying to truncate %s"), + device_name); } if (fd > 0) close(fd);