linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Jan Kara <jack@suse.com>
Cc: linux-ext4@vger.kernel.org, Ted Tso <tytso@mit.edu>
Subject: Re: [PATCH 10/19] tune2fs: Implement setting and disabling of 64-bit feature
Date: Fri, 7 Aug 2015 08:42:23 -0700	[thread overview]
Message-ID: <20150807154223.GE10037@birch.djwong.org> (raw)
In-Reply-To: <20150807153247.GA24988@birch.djwong.org>

On Fri, Aug 07, 2015 at 08:32:47AM -0700, Darrick J. Wong wrote:
> On Fri, Aug 07, 2015 at 12:51:20PM +0200, Jan Kara wrote:
> > Currently resize2fs is used to toggle 64-bit feature. However tune2fs
> > should logically handle that as toggling any other feature. Since we
> > have now factored out block moving code from resize2fs it is relatively
> > easy to implement toggling of the feature within tune2fs.
> > 
> > For now we leave the same functionality also in resize2fs for testing.
> > Later we can make resize2fs call tune2fs for backward compatibility.
> 
> There hasn't been a release of e2fsprogs with 64bit conversion support in
> resize2fs, so you can fix the conversion tests to use tune2fs and remove the
> -b/-B switches from resize2fs entirely.

Oh, I didn't notice that you /do/ remove the resize2fs part later on in the
patch set.  Sorry for the noise about that.

I think there are still tests that need to be fixed up.

--D

> 
> --D
> 
> > 
> > Signed-off-by: Jan Kara <jack@suse.com>
> > ---
> >  misc/tune2fs.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
> >  1 file changed, 345 insertions(+), 22 deletions(-)
> > 
> > diff --git a/misc/tune2fs.c b/misc/tune2fs.c
> > index d2e8b20f64e2..d6bfad3374d1 100644
> > --- a/misc/tune2fs.c
> > +++ b/misc/tune2fs.c
> > @@ -447,10 +447,327 @@ static void request_fsck_afterwards(ext2_filsys fs)
> >  		printf("%s", _("(and reboot afterwards!)\n"));
> >  }
> >  
> > -static void convert_64bit(ext2_filsys fs, int direction)
> > +static errcode_t fix_resize_inode(ext2_filsys fs)
> >  {
> > -	if (!direction)
> > -		return;
> > +	errcode_t retval;
> > +
> > +	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE))
> > +		return 0;
> > +
> > +	retval = ext2fs_wipe_resize_inode(fs);
> > +	if (retval)
> > +		return retval;
> > +
> > +	return ext2fs_create_resize_inode(fs);
> > +}
> > +
> > +/*
> > + * Make blocks that are needed for new group metadata unused and write there
> > + * new group descriptors
> > + */
> > +static errcode_t move_bg_metadata(ext2_filsys fs, ext2_filsys new_fs)
> > +{
> > +	dgrp_t i;
> > +	blk64_t b, c, d, old_desc_blocks, new_desc_blocks, j;
> > +	ext2fs_block_bitmap old_map = NULL, new_map = NULL;
> > +	int old, new;
> > +	errcode_t retval;
> > +	int cluster_ratio;
> > +	int need_new_block = 0;
> > +
> > +	retval = ext2fs_allocate_block_bitmap(fs, "old map", &old_map);
> > +	if (retval)
> > +		goto out;
> > +
> > +	retval = ext2fs_allocate_block_bitmap(fs, "new map", &new_map);
> > +	if (retval)
> > +		goto out;
> > +
> > +	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
> > +				      EXT2_FEATURE_INCOMPAT_META_BG)) {
> > +		old_desc_blocks = fs->super->s_first_meta_bg;
> > +		new_desc_blocks = new_fs->super->s_first_meta_bg;
> > +	} else {
> > +		old_desc_blocks = fs->desc_blocks +
> > +				  fs->super->s_reserved_gdt_blocks;
> > +		new_desc_blocks = new_fs->desc_blocks +
> > +				  new_fs->super->s_reserved_gdt_blocks;
> > +	}
> > +
> > +	/* Construct bitmaps of super/descriptor blocks in old and new fs */
> > +	for (i = 0; i < fs->group_desc_count; i++) {
> > +		retval = ext2fs_super_and_bgd_loc2(fs, i, &b, &c, &d, NULL);
> > +		if (retval)
> > +			goto out;
> > +		if (b)
> > +			ext2fs_mark_block_bitmap2(old_map, b);
> > +		for (j = 0; c != 0 && j < old_desc_blocks; j++)
> > +			ext2fs_mark_block_bitmap2(old_map, c + j);
> > +		if (d)
> > +			ext2fs_mark_block_bitmap2(old_map, d);
> > +
> > +		retval = ext2fs_super_and_bgd_loc2(new_fs, i, &b, &c, &d, NULL);
> > +		if (retval)
> > +			goto out;
> > +		if (b)
> > +			ext2fs_mark_block_bitmap2(new_map, b);
> > +		for (j = 0; c != 0 && j < new_desc_blocks; j++)
> > +			ext2fs_mark_block_bitmap2(new_map, c + j);
> > +		if (d)
> > +			ext2fs_mark_block_bitmap2(new_map, d);
> > +	}
> > +
> > +	cluster_ratio = EXT2FS_CLUSTER_RATIO(new_fs);
> > +
> > +	/* Find changes in block allocations for bg metadata */
> > +	for (b = EXT2FS_B2C(fs, fs->super->s_first_data_block);
> > +	     b < ext2fs_blocks_count(new_fs->super);
> > +	     b += cluster_ratio) {
> > +		old = ext2fs_test_block_bitmap2(old_map, b);
> > +		new = ext2fs_test_block_bitmap2(new_map, b);
> > +
> > +		if (old && !new) {
> > +			/* mark old_map, unmark new_map */
> > +			if (cluster_ratio == 1)
> > +				ext2fs_block_alloc_stats2(new_fs, b, -1);
> > +		} else if (!old && new)
> > +			need_new_block = 1; /* unmark old_map, mark new_map */
> > +		else {
> > +			ext2fs_unmark_block_bitmap2(old_map, b);
> > +			ext2fs_unmark_block_bitmap2(new_map, b);
> > +		}
> > +	}
> > +
> > +	/*
> > +	 * new_map now shows blocks that have been newly allocated.
> > +	 * old_map now shows blocks that have been newly freed.
> > +	 */
> > +
> > +	if (need_new_block) {
> > +		/*
> > +		 * Now relocate metadata & data conflicting with new descriptor
> > +		 * blocks
> > +		 */
> > +		retval = ext2fs_move_blocks(new_fs, new_map, old_map);
> > +		if (retval)
> > +			goto out;
> > +
> > +		/* Now mark blocks for new group descriptors as used */
> > +		for (b = 0; b < ext2fs_blocks_count(new_fs->super);
> > +		     b += cluster_ratio) {
> > +			if (ext2fs_test_block_bitmap2(new_map, b) &&
> > +			    !ext2fs_test_block_bitmap2(new_fs->block_map, b))
> > +				ext2fs_block_alloc_stats2(new_fs, b, +1);
> > +		}
> > +	}
> > +
> > +	if (cluster_ratio > 1) {
> > +		/* Free unused clusters */
> > +		for (b = 0; b < ext2fs_blocks_count(new_fs->super);
> > +		     b += cluster_ratio)
> > +			if (ext2fs_test_block_bitmap2(old_map, b))
> > +				ext2fs_block_alloc_stats2(new_fs, b, -1);
> > +	}
> > +
> > +	/* Now update resize inode */
> > +	retval = fix_resize_inode(new_fs);
> > +out:
> > +	if (old_map)
> > +		ext2fs_free_block_bitmap(old_map);
> > +	if (new_map)
> > +		ext2fs_free_block_bitmap(new_map);
> > +	return retval;
> > +}
> > +
> > +
> > +/* Toggle 64bit mode */
> > +static errcode_t resize_group_descriptors(ext2_filsys *fs_p, int direction)
> > +{
> > +	void *o, *n, *new_group_desc;
> > +	dgrp_t i;
> > +	int copy_size;
> > +	errcode_t retval;
> > +	ext2_filsys new_fs = NULL;
> > +	ext2_filsys fs = *fs_p;
> > +
> > +	retval = ext2fs_dup_handle(fs, &new_fs);
> > +	if (retval)
> > +		return retval;
> > +
> > +	if (direction < 0) {
> > +		new_fs->super->s_feature_incompat &=
> > +					~EXT4_FEATURE_INCOMPAT_64BIT;
> > +		new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE;
> > +	} else {
> > +		new_fs->super->s_feature_incompat |=
> > +					EXT4_FEATURE_INCOMPAT_64BIT;
> > +		new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
> > +	}
> > +
> > +	o = new_fs->group_desc;
> > +	new_fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
> > +			EXT2_DESC_PER_BLOCK(new_fs->super));
> > +	retval = ext2fs_get_arrayzero(new_fs->desc_blocks,
> > +				      fs->blocksize, &new_group_desc);
> > +	if (retval)
> > +		goto out;
> > +
> > +	n = new_group_desc;
> > +
> > +	if (EXT2_DESC_SIZE(fs->super) <= EXT2_DESC_SIZE(new_fs->super))
> > +		copy_size = EXT2_DESC_SIZE(fs->super);
> > +	else
> > +		copy_size = EXT2_DESC_SIZE(new_fs->super);
> > +	for (i = 0; i < fs->group_desc_count; i++) {
> > +		memcpy(n, o, copy_size);
> > +		n += EXT2_DESC_SIZE(new_fs->super);
> > +		o += EXT2_DESC_SIZE(fs->super);
> > +	}
> > +
> > +	ext2fs_free_mem(&new_fs->group_desc);
> > +	new_fs->group_desc = new_group_desc;
> > +
> > +	for (i = 0; i < fs->group_desc_count; i++)
> > +		ext2fs_group_desc_csum_set(new_fs, i);
> > +
> > +	/*
> > +	 * Update number of reserved blocks so that we need to alloc / free as
> > +	 * few blocks as possible
> > +	 */
> > +	if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
> > +	    (fs->desc_blocks != new_fs->desc_blocks)) {
> > +		int new;
> > +
> > +		new = ((int) new_fs->super->s_reserved_gdt_blocks) +
> > +			(fs->desc_blocks - new_fs->desc_blocks);
> > +		if (new < 0)
> > +			new = 0;
> > +		if (new > (int) fs->blocksize / 4)
> > +			new = fs->blocksize / 4;
> > +		new_fs->super->s_reserved_gdt_blocks = new;
> > +	}
> > +
> > +	retval = move_bg_metadata(fs, new_fs);
> > +
> > +	/* Return the modified filesystem */
> > +	new_fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
> > +	ext2fs_mark_super_dirty(new_fs);
> > +	ext2fs_free(fs);
> > +	*fs_p = new_fs;
> > +	new_fs = NULL;
> > +out:
> > +	if (new_fs)
> > +		ext2fs_free(new_fs);
> > +	return retval;
> > +}
> > +
> > +/* Zero out the high bits of extent fields */
> > +static errcode_t zero_high_bits_in_extents(ext2_filsys fs, ext2_ino_t ino,
> > +					   struct ext2_inode *inode)
> > +{
> > +	ext2_extent_handle_t	handle;
> > +	struct ext2fs_extent	extent;
> > +	int			op = EXT2_EXTENT_ROOT;
> > +	errcode_t		errcode;
> > +
> > +	if (!(inode->i_flags & EXT4_EXTENTS_FL))
> > +		return 0;
> > +
> > +	errcode = ext2fs_extent_open(fs, ino, &handle);
> > +	if (errcode)
> > +		return errcode;
> > +
> > +	while (1) {
> > +		errcode = ext2fs_extent_get(handle, op, &extent);
> > +		if (errcode)
> > +			break;
> > +
> > +		op = EXT2_EXTENT_NEXT_SIB;
> > +
> > +		if (extent.e_pblk > (1ULL << 32)) {
> > +			extent.e_pblk &= (1ULL << 32) - 1;
> > +			errcode = ext2fs_extent_replace(handle, 0, &extent);
> > +			if (errcode)
> > +				break;
> > +		}
> > +	}
> > +
> > +	/* Ok if we run off the end */
> > +	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
> > +		errcode = 0;
> > +	ext2fs_extent_free(handle);
> > +	return errcode;
> > +}
> > +
> > +/* Zero out the high bits of inodes. */
> > +static errcode_t zero_high_bits_in_inodes(ext2_filsys fs)
> > +{
> > +	int length = EXT2_INODE_SIZE(fs->super);
> > +	struct ext2_inode *inode = NULL;
> > +	ext2_inode_scan	scan = NULL;
> > +	errcode_t	retval;
> > +	ext2_ino_t	ino;
> > +
> > +	if (fs->super->s_creator_os != EXT2_OS_LINUX)
> > +		return 0;
> > +
> > +	retval = ext2fs_open_inode_scan(fs, 0, &scan);
> > +	if (retval)
> > +		return retval;
> > +
> > +	retval = ext2fs_get_mem(length, &inode);
> > +	if (retval)
> > +		goto out;
> > +
> > +	do {
> > +		retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
> > +		if (retval)
> > +			goto out;
> > +		if (!ino)
> > +			break;
> > +		if (!ext2fs_test_inode_bitmap2(fs->inode_map, ino))
> > +			continue;
> > +
> > +		/*
> > +		 * Here's how we deal with high block number fields:
> > +		 *
> > +		 *  - i_size_high has been been written out with i_size_lo
> > +		 *    since the ext2 days, so no conversion is needed.
> > +		 *
> > +		 *  - i_blocks_hi is guarded by both the huge_file feature and
> > +		 *    inode flags and has always been written out with
> > +		 *    i_blocks_lo if the feature is set.  The field is only
> > +		 *    ever read if both feature and inode flag are set, so
> > +		 *    we don't need to zero it now.
> > +		 *
> > +		 *  - i_file_acl_high can be uninitialized, so zero it if
> > +		 *    it isn't already.
> > +		 */
> > +		if (inode->osd2.linux2.l_i_file_acl_high) {
> > +			inode->osd2.linux2.l_i_file_acl_high = 0;
> > +			retval = ext2fs_write_inode_full(fs, ino, inode,
> > +							 length);
> > +			if (retval)
> > +				goto out;
> > +		}
> > +
> > +		retval = zero_high_bits_in_extents(fs, ino, inode);
> > +		if (retval)
> > +			goto out;
> > +	} while (ino);
> > +
> > +out:
> > +	if (inode)
> > +		ext2fs_free_mem(&inode);
> > +	if (scan)
> > +		ext2fs_close_inode_scan(scan);
> > +	return retval;
> > +}
> > +
> > +static errcode_t convert_64bit(ext2_filsys *fs_p, int direction)
> > +{
> > +	ext2_filsys fs = *fs_p;
> > +	errcode_t retval;
> >  
> >  	/*
> >  	 * Is resize2fs going to demand a fsck run? Might as well tell the
> > @@ -459,21 +776,25 @@ static void convert_64bit(ext2_filsys fs, int direction)
> >  	if (!fsck_requested &&
> >  	    ((fs->super->s_state & EXT2_ERROR_FS) ||
> >  	     !(fs->super->s_state & EXT2_VALID_FS) ||
> > -	     fs->super->s_lastcheck < fs->super->s_mtime))
> > +	     fs->super->s_lastcheck < fs->super->s_mtime)) {
> >  		request_fsck_afterwards(fs);
> > -	if (fsck_requested)
> > -		fprintf(stderr, _("After running e2fsck, please run `resize2fs %s %s"),
> > -			direction > 0 ? "-b" : "-s", fs->device_name);
> > -	else
> > -		fprintf(stderr, _("Please run `resize2fs %s %s"),
> > -			direction > 0 ? "-b" : "-s", fs->device_name);
> > +		return 0;
> > +	}
> >  
> > -	if (undo_file)
> > -		fprintf(stderr, _(" -z \"%s\""), undo_file);
> > -	if (direction > 0)
> > -		fprintf(stderr, _("' to enable 64-bit mode.\n"));
> > -	else
> > -		fprintf(stderr, _("' to disable 64-bit mode.\n"));
> > +	/*
> > +	 * Read bitmaps now since we are definitely going to need them and they
> > +	 * get properly duplicated when creating new fs handle in
> > +	 * resize_group_descriptors()
> > +	 */
> > +	retval = ext2fs_read_bitmaps(fs);
> > +	if (retval)
> > +		return retval;
> > +
> > +	retval = resize_group_descriptors(fs_p, direction);
> > +	if (retval)
> > +		return retval;
> > +
> > +	return zero_high_bits_in_inodes(*fs_p);
> >  }
> >  
> >  /* Rewrite extents */
> > @@ -1253,9 +1574,9 @@ mmp_error:
> >  	}
> >  
> >  	/*
> > -	 * We don't actually toggle 64bit; resize2fs does that.  But this
> > -	 * must come after the metadata_csum feature_on so that it won't
> > -	 * complain about the lack of 64bit.
> > +	 * Handle 64-bit conversion. We return the feature to the original
> > +	 * value for now until the conversion really takes place. Otherwise
> > +	 * some helper macros get confused.
> >  	 */
> >  	if (FEATURE_ON(E2P_FEATURE_INCOMPAT,
> >  		       EXT4_FEATURE_INCOMPAT_64BIT)) {
> > @@ -1264,8 +1585,8 @@ mmp_error:
> >  					  "while mounted!\n"));
> >  			exit(1);
> >  		}
> > -		sb->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_64BIT;
> >  		feature_64bit = 1;
> > +		sb->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_64BIT;
> >  	}
> >  	if (FEATURE_OFF(E2P_FEATURE_INCOMPAT,
> >  			EXT4_FEATURE_INCOMPAT_64BIT)) {
> > @@ -1274,8 +1595,8 @@ mmp_error:
> >  					  "while mounted!\n"));
> >  			exit(1);
> >  		}
> > -		sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
> >  		feature_64bit = -1;
> > +		sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
> >  	}
> >  
> >  	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
> > @@ -3080,6 +3401,9 @@ retry_open:
> >  		}
> >  	}
> >  
> > +	if (feature_64bit)
> > +		convert_64bit(&fs, feature_64bit);
> > +
> >  	if (rewrite_checksums)
> >  		rewrite_metadata_checksums(fs);
> >  
> > @@ -3113,6 +3437,5 @@ closefs:
> >  		exit(1);
> >  	}
> >  
> > -	convert_64bit(fs, feature_64bit);
> >  	return (ext2fs_close_free(&fs) ? 1 : 0);
> >  }
> > -- 
> > 2.1.4
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2015-08-07 15:42 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-07 10:51 [PATCH 00/19] e2fsprogs: Resizing rewrite Jan Kara
2015-08-07 10:51 ` [PATCH 01/19] ext2fs: Move function to initialize uninitialized bitmaps to libext2fs Jan Kara
2015-08-07 10:51 ` [PATCH 02/19] ext2fs: Use range marking function to mark all inode table blocks as used Jan Kara
2015-08-07 10:51 ` [PATCH 03/19] ext2fs: Add pointer to allocator private data into ext2_filsys Jan Kara
2015-08-07 10:51 ` [PATCH 04/19] ext2fs: Implement ext2fs_allocate_group_table2() Jan Kara
2015-08-07 10:51 ` [PATCH 05/19] resize2fs: Use ext2fs_allocate_group_table2() Jan Kara
2015-08-07 10:51 ` [PATCH 06/19] ext2fs: Make ext2fs_reserve_super_and_bgd() clear block_uninit flag Jan Kara
2015-08-07 10:51 ` [PATCH 07/19] ext2fs: Provide helper for wiping resize inode Jan Kara
2015-08-07 10:51 ` [PATCH 08/19] ext2fs: Implement block moving in libext2fs Jan Kara
2015-08-07 15:55   ` Darrick J. Wong
2015-08-26 15:55     ` Jan Kara
2015-08-07 10:51 ` [PATCH 09/19] ext2fs: Implement inode " Jan Kara
2015-08-07 10:51 ` [PATCH 10/19] tune2fs: Implement setting and disabling of 64-bit feature Jan Kara
2015-08-07 15:32   ` Darrick J. Wong
2015-08-07 15:42     ` Darrick J. Wong [this message]
2015-08-26 15:51       ` Jan Kara
2015-08-07 10:51 ` [PATCH 11/19] mke2fs: Allow specifying number of reserved inodes Jan Kara
2015-08-07 15:37   ` Darrick J. Wong
2015-08-26 15:49     ` Jan Kara
2015-08-07 10:51 ` [PATCH 12/19] libext2fs: Bump default number of reserved inodes to 64 Jan Kara
2015-08-07 10:58   ` Alexey Lyashkov
2015-08-07 11:03     ` Jan Kara
2015-08-07 18:11       ` Alexey Lyashkov
2015-08-07 19:11   ` Andreas Dilger
2015-08-26 15:58     ` Jan Kara
2015-08-07 10:51 ` [PATCH 13/19] tune2fs: Add support for changing number of reserved inodes Jan Kara
2015-08-07 18:58   ` Andreas Dilger
2015-08-26 16:11     ` Jan Kara
2015-08-08  7:45   ` Alexey Lyashkov
2015-08-26 16:07     ` Jan Kara
2015-08-07 10:51 ` [PATCH 14/19] resize2fs: Rip out 64-bit feature handling from resize2fs Jan Kara
2015-08-07 10:51 ` [PATCH 15/19] resize2fs: Remove duplicit condition Jan Kara
2015-08-07 19:01   ` Andreas Dilger
2015-08-26 16:12     ` Jan Kara
2015-08-07 10:51 ` [PATCH 16/19] ext2fs: Add extent dumping function to extent mapping code Jan Kara
2015-08-07 10:51 ` [PATCH 17/19] resize2fs: Remove " Jan Kara
2015-08-07 10:51 ` [PATCH 18/19] ext2fs: Move extent mapping test Jan Kara
2015-08-07 10:51 ` [PATCH 19/19] resize2fs: Use libextfs2 helpers for resizing Jan Kara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150807154223.GE10037@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=jack@suse.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).