* [PATCH 2/2] resize2fs: Add discard support
2011-02-01 17:14 [PATCH 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
@ 2011-02-01 17:14 ` Lukas Czerner
2011-02-01 19:15 ` [PATCH 1/2] resize2fs: Add support for lazy itable initialization Andreas Dilger
` (2 subsequent siblings)
3 siblings, 0 replies; 13+ messages in thread
From: Lukas Czerner @ 2011-02-01 17:14 UTC (permalink / raw)
To: linux-ext4; +Cc: tytso, lczerner
This commit adds two new extended options - discard and nodiscard. When
'-E discard' is specified, resize2fs will attempt to discard the portion
of the device which will be used to extend the file system.
As a side-effect, if the discard also zeroes data (every subsequent read
form discarded block will return zeros) resize2fs will skip inode table
initialization, but still set the EXT2_BG_INODE_ZEROED flag. The default
is 'nodiscard'.
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
---
resize/main.c | 11 ++++++-
resize/resize2fs.8.in | 14 +++++++++
resize/resize2fs.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-
resize/resize2fs.h | 3 ++
4 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/resize/main.c b/resize/main.c
index 0f1a8db..f7e6a0e 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -61,6 +61,9 @@ static errcode_t resize_progress_func(ext2_resize_t rfs, int pass,
ext2fs_progress_close(progress);
progress = 0;
switch (pass) {
+ case E2_RSZ_DISCARD_DEVICE:
+ label = _("Discarding device");
+ break;
case E2_RSZ_EXTEND_ITABLE_PASS:
label = _("Extending the inode table");
break;
@@ -181,6 +184,10 @@ static void parse_extended_opts(int *flags, const char *opts)
lazy = 1;
if (lazy)
*flags |= RESIZE_LAZY_ITABLE_INIT;
+ } else if (!strcmp(token, "discard")) {
+ *flags |= RESIZE_DISCARD;
+ } else if (!strcmp(token, "nodiscard")) {
+ *flags &= ~RESIZE_DISCARD;
} else {
r_usage++;
badopt = token;
@@ -192,7 +199,9 @@ static void parse_extended_opts(int *flags, const char *opts)
"and may take an argument which\n"
"\tis set off by an equals ('=') sign.\n\n"
"Valid extended options are:\n"
- "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
+ "\tlazy_itable_init=<0 to disable, 1 to enable>\n"
+ "\tdiscard\n"
+ "\tnodiscard\n\n"),
badopt ? badopt : "");
free(buf);
exit(1);
diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
index 448265c..3e47610 100644
--- a/resize/resize2fs.8.in
+++ b/resize/resize2fs.8.in
@@ -148,6 +148,20 @@ resize noticeably, but it requires the kernel to finish
initializing the filesystem in the background when the filesystem is
mounted. If the option value is omitted, it defaults to 1 to
enable lazy inode table initialization.
+TP
+.BI discard
+Attempt to discard blocks
+.BR resize2fs
+is going to use to extend the filesystem (discarding blocks is useful on solid
+state devices and sparse / thin-provisioned storage) before the resize. If the
+device advertises that discard also zeroes data (any subsequent read after the
+discard and before write returns zero), then mark all not-yet-zeroed inode
+tables as zeroed. This significantly speed up filesystem resize if
+.BR lazy_itable_init
+is not specified.
+.TP
+.BI nodiscard
+Do not attempt to discard blocks before resize. This is the default.
.SH KNOWN BUGS
The minimum size of the filesystem as estimated by resize2fs may be
incorrect, especially for filesystems with 1k and 2k blocksizes.
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 1101364..34ac506 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -66,6 +66,54 @@ static errcode_t fix_sb_journal_backup(ext2_filsys fs);
#define SUPER_OVERHEAD(fs) (1 + (fs)->desc_blocks +\
(fs)->super->s_reserved_gdt_blocks)
+#define DISCARD_STEP_MB (2048)
+
+static int resize2fs_discard_device(ext2_resize_t rfs, blk64_t start,
+ blk64_t end)
+{
+ ext2_filsys fs = rfs->new_fs;
+ blk64_t blocks = end - start;
+ blk64_t count = DISCARD_STEP_MB;
+ blk64_t cur = 0;
+ int retval = 0;
+
+ if (start >= end)
+ return -EINVAL;
+
+ count *= (1024 * 1024);
+ count /= fs->blocksize;
+
+ if (rfs->progress) {
+ retval = rfs->progress(rfs, E2_RSZ_DISCARD_DEVICE,
+ cur, blocks);
+ if (retval)
+ return retval;
+ }
+
+ while (cur < blocks) {
+ if (cur + count > blocks)
+ count = blocks - cur;
+ retval = io_channel_discard(fs->io, start + cur, count,
+ fs->blocksize);
+ if (retval)
+ break;
+
+ cur += count;
+ if (rfs->progress) {
+ retval = rfs->progress(rfs, E2_RSZ_DISCARD_DEVICE,
+ cur, blocks);
+ if (retval)
+ break;
+ }
+ }
+
+ if (retval && rfs->progress) {
+ printf(_("\nDiscard Failed - "));
+ printf("%s\n",error_message(retval));
+ }
+ return retval;
+}
+
/*
* This is the top-level routine which does the dirty deed....
*/
@@ -103,6 +151,28 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
if (retval)
goto errout;
+ /*
+ * Attempt to discard space which we are going to use to extend the
+ * file system. We do no need to abort file system resize if this
+ * fails due to EOPNOTSUPP, just clear RESIZE_DISCARD flag
+ */
+ if ((flags & RESIZE_DISCARD) &&
+ (*new_size > ext2fs_blocks_count(fs->super))) {
+ if (io_channel_discard_zeroes_data(rfs->new_fs->io))
+ flags |= RESIZE_DISCARD_ZEROES;
+ retval = resize2fs_discard_device(rfs,
+ ext2fs_blocks_count(fs->super),
+ *new_size);
+ if (retval = -EOPNOTSUPP)
+ flags &= ~(RESIZE_DISCARD & RESIZE_DISCARD_ZEROES);
+ else {
+ fprintf(stderr, _("Warning: Something went wrong"
+ "while discarding, maybe due programming"
+ "error, or the device is broken. Exiting!\n"));
+ exit(retval);
+ }
+ }
+
retval = adjust_superblock(rfs, *new_size, flags);
if (retval)
goto errout;
@@ -499,6 +569,8 @@ retry:
adjblocks = 0;
ext2fs_bg_flags_zap(fs, i);
+ if (csum_flag && (flags & RESIZE_DISCARD_ZEROES))
+ ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED);
if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
else if (csum_flag)
@@ -672,7 +744,7 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
if (retval)
goto errout;
- if (!(flags & RESIZE_LAZY_ITABLE_INIT))
+ if (!(flags & (RESIZE_LAZY_ITABLE_INIT | RESIZE_DISCARD_ZEROES)))
retval = write_inode_tables(rfs, fs);
errout:
return retval;
diff --git a/resize/resize2fs.h b/resize/resize2fs.h
index a968071..d9aee33 100644
--- a/resize/resize2fs.h
+++ b/resize/resize2fs.h
@@ -80,6 +80,8 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
#define RESIZE_PERCENT_COMPLETE 0x0100
#define RESIZE_VERBOSE 0x0200
#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
+#define RESIZE_DISCARD 0x0800 /* Discard space before attempt to resize */
+#define RESIZE_DISCARD_ZEROES 0x1000 /* Discard zeroes data */
/*
* The core state structure for the ext2 resizer
@@ -115,6 +117,7 @@ struct ext2_resize_struct {
/*
* Progress pass numbers...
*/
+#define E2_RSZ_DISCARD_DEVICE 0
#define E2_RSZ_EXTEND_ITABLE_PASS 1
#define E2_RSZ_BLOCK_RELOC_PASS 2
#define E2_RSZ_INODE_SCAN_PASS 3
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-02-01 17:14 [PATCH 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
2011-02-01 17:14 ` [PATCH 2/2] resize2fs: Add discard support Lukas Czerner
@ 2011-02-01 19:15 ` Andreas Dilger
2011-02-01 19:31 ` Lukas Czerner
2011-02-16 10:42 ` [PATCH " Lukas Czerner
2012-01-12 7:47 ` Lukas Czerner
3 siblings, 1 reply; 13+ messages in thread
From: Andreas Dilger @ 2011-02-01 19:15 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, tytso
On 2011-02-01, at 10:14, Lukas Czerner wrote:
> This commit adds extended options '-E' to the resize2fs code along with
> the first extended option lazy_itable_init=n.
Here it says the option is "=n", is it also possible to force this with "=y"?
> +static void parse_extended_opts(int *flags, const char *opts)
> +{
> + if (!strcmp(token, "lazy_itable_init")) {
> + int lazy;
> + if (arg)
> + lazy = strtoul(arg, &p, 0);
> + else
> + lazy = 1;
> + if (lazy)
> + *flags |= RESIZE_LAZY_ITABLE_INIT;
Here it parses the option as "=0" or "=1", not "=n" or "=y". It looks like "=n" will accidentally return 0 from strtoul(), so that works as expected, but the "=y" option would fail (it would also return 0).
> + if (r_usage) {
> + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
It looks a bit confusing "=<0 to disable", I thought initially that meant any value <= 0 would disable it, though I later see that there is a closing '>'. I think it is more standard to use "{}" braces for "one of these options must be given".
> @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> + flags |= RESIZE_LAZY_ITABLE_INIT;
> +
> + if (extended_opts)
> + parse_extended_opts(&flags, extended_opts);
Good that the command-line options override the default value.
> +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
Similarly, this should use "{}" around the options instead of "<>".
> +If enabled and the uninit_bg feature is enabled, the inode table will
> +not be fully initialized by
I would write "not be zeroed out on disk", since it is otherwise unclear
if "not fully initialized" means that there will be less inodes available
or some other issues if the inode table is not "fully" initialized.
Cheers, Andreas
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-02-01 19:15 ` [PATCH 1/2] resize2fs: Add support for lazy itable initialization Andreas Dilger
@ 2011-02-01 19:31 ` Lukas Czerner
2011-02-02 11:16 ` [PATCH v2 " Lukas Czerner
0 siblings, 1 reply; 13+ messages in thread
From: Lukas Czerner @ 2011-02-01 19:31 UTC (permalink / raw)
To: Andreas Dilger; +Cc: Lukas Czerner, linux-ext4, tytso
On Tue, 1 Feb 2011, Andreas Dilger wrote:
> On 2011-02-01, at 10:14, Lukas Czerner wrote:
> > This commit adds extended options '-E' to the resize2fs code along with
> > the first extended option lazy_itable_init=n.
>
> Here it says the option is "=n", is it also possible to force this with "=y"?
Oh, no not really. It should be just =0 or =1, it is the same as we have in
mke2fs.
>
> > +static void parse_extended_opts(int *flags, const char *opts)
> > +{
> > + if (!strcmp(token, "lazy_itable_init")) {
> > + int lazy;
> > + if (arg)
> > + lazy = strtoul(arg, &p, 0);
> > + else
> > + lazy = 1;
> > + if (lazy)
> > + *flags |= RESIZE_LAZY_ITABLE_INIT;
>
> Here it parses the option as "=0" or "=1", not "=n" or "=y". It looks like "=n" will accidentally return 0 from strtoul(), so that works as expected, but the "=y" option would fail (it would also return 0).
As I mentioned it is not supposed to work with =y or =n, but only with
=0 or =1. So I think it is expected, isn't it ?
>
> > + if (r_usage) {
> > + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> > + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
>
> It looks a bit confusing "=<0 to disable", I thought initially that meant any value <= 0 would disable it, though I later see that there is a closing '>'. I think it is more standard to use "{}" braces for "one of these options must be given".
:) I did not noticed that before, but you're right, I'll change that to
use "{}".
>
> > @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> > + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> > + flags |= RESIZE_LAZY_ITABLE_INIT;
> > +
> > + if (extended_opts)
> > + parse_extended_opts(&flags, extended_opts);
>
> Good that the command-line options override the default value.
Yes, it suppose to be that way.
>
> > +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
>
> Similarly, this should use "{}" around the options instead of "<>".
>
> > +If enabled and the uninit_bg feature is enabled, the inode table will
> > +not be fully initialized by
>
> I would write "not be zeroed out on disk", since it is otherwise unclear
> if "not fully initialized" means that there will be less inodes available
> or some other issues if the inode table is not "fully" initialized.
Right.
>
> Cheers, Andreas
>
Thanks!
-Lukas
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 1/2] resize2fs: Add support for lazy itable initialization
2011-02-01 19:31 ` Lukas Czerner
@ 2011-02-02 11:16 ` Lukas Czerner
2011-02-03 20:36 ` [PATCH] mke2fs: Add support for lazy journal initialization Andreas Dilger
2011-08-11 14:53 ` [PATCH v2 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
0 siblings, 2 replies; 13+ messages in thread
From: Lukas Czerner @ 2011-02-02 11:16 UTC (permalink / raw)
To: linux-ext4; +Cc: tytso, lczerner, adilger
Lazy inode table initialization speeds up file system resize operation
because we can let the inode tables uninitialized. For some time now the
mke2fs has similar option and now, when we have in-kernel lazyinit
implementation we can add this feature to the resize2fs as well.
This commit adds extended options '-E' to the resize2fs code along with
the first extended option lazy_itable_init=n, where n is a 0 or 1,
though the '=n' argument can be omitted. With lazy_itable_init extended
option one can instruct resize2fs to skip inode table initialization to
significantly speed-up file system resize. If the option is omitted and
the file system supports lazy inode table initialization it defaults to 1.
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
---
resize/main.c | 68 +++++++++++++++++++++++++++++++-
resize/online.c | 2 +-
resize/resize2fs.8.in | 20 +++++++++
resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
resize/resize2fs.h | 3 +-
5 files changed, 148 insertions(+), 50 deletions(-)
diff --git a/resize/main.c b/resize/main.c
index 28a49ba..03127ea 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
static void usage (char *prog)
{
fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
- "[-p] device [new_size]\n\n"), prog);
+ "[-p] [-E extended_options] device [new_size]\n\n"),
+ prog);
exit (1);
}
@@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
#endif
}
+static void parse_extended_opts(int *flags, const char *opts)
+{
+ char *buf, *token, *next, *p, *arg, *badopt = 0;
+ int len;
+ int r_usage = 0;
+
+ len = strlen(opts);
+ buf = malloc(len+1);
+ if (!buf) {
+ fprintf(stderr,
+ _("Couldn't allocate memory to parse options!\n"));
+ exit(1);
+ }
+ strcpy(buf, opts);
+ for (token = buf; token && *token; token = next) {
+ p = strchr(token, ',');
+ next = 0;
+ if (p) {
+ *p = 0;
+ next = p+1;
+ }
+ arg = strchr(token, '=');
+ if (arg) {
+ *arg = 0;
+ arg++;
+ }
+ if (!strcmp(token, "lazy_itable_init")) {
+ int lazy;
+ if (arg)
+ lazy = strtoul(arg, &p, 0);
+ else
+ lazy = 1;
+ if (lazy == 1)
+ *flags |= RESIZE_LAZY_ITABLE_INIT;
+ } else {
+ r_usage++;
+ badopt = token;
+ }
+ }
+ if (r_usage) {
+ fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
+ "Extended options are separated by commas, "
+ "and may take an argument which\n"
+ "\tis set off by an equals ('=') sign.\n\n"
+ "Valid extended options are:\n"
+ "\tlazy_itable_init[={0 to disable, 1 to enable}]\n\n"),
+ badopt ? badopt : "");
+ free(buf);
+ exit(1);
+ }
+ free(buf);
+}
+
int main (int argc, char ** argv)
{
errcode_t retval;
@@ -174,6 +228,7 @@ int main (int argc, char ** argv)
long sysval;
int len, mount_flags;
char *mtpt;
+ char * extended_opts = NULL;
#ifdef ENABLE_NLS
setlocale(LC_MESSAGES, "");
@@ -189,7 +244,7 @@ int main (int argc, char ** argv)
if (argc && *argv)
program_name = *argv;
- while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
+ while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
switch (c) {
case 'h':
usage(program_name);
@@ -215,6 +270,9 @@ int main (int argc, char ** argv)
case 'S':
use_stride = atoi(optarg);
break;
+ case 'E':
+ extended_opts = optarg;
+ break;
default:
usage(program_name);
}
@@ -232,6 +290,12 @@ int main (int argc, char ** argv)
if (io_options)
*io_options++ = 0;
+ if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
+ flags |= RESIZE_LAZY_ITABLE_INIT;
+
+ if (extended_opts)
+ parse_extended_opts(&flags, extended_opts);
+
/*
* Figure out whether or not the device is mounted, and if it is
* where it is mounted.
diff --git a/resize/online.c b/resize/online.c
index 1d8d4ec..7bc27b3 100644
--- a/resize/online.c
+++ b/resize/online.c
@@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
* but at least it allows on-line resizing to function.
*/
new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
- retval = adjust_fs_info(new_fs, fs, 0, *new_size);
+ retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
if (retval)
return retval;
diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
index e02345d..7fbc979 100644
--- a/resize/resize2fs.8.in
+++ b/resize/resize2fs.8.in
@@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
.B \-S
.I RAID-stride
]
+[
+.B \-E
+.I extended-options
+]
.I device
[
.I size
@@ -128,6 +132,22 @@ The
program will heuristically determine the RAID stride that was specified
when the filesystem was created. This option allows the user to
explicitly specify a RAID stride setting to be used by resize2fs instead.
+.TP
+.B \-E \fIextended-options
+Set extended options for the filesystem. Extended options are comma
+separated, and may take an argument using the equals ('=') sign.
+The following extended options are supported:
+.RS 1.2i
+.TP
+.B lazy_itable_init\fR[\fB= \fI{0 to disable, 1 to enable}\fR]
+If enabled and the uninit_bg feature is enabled, the inode table will
+not be zeroed out on disk by
+.BR resize2fs .
+This speeds up filesystem
+resize noticeably, but it requires the kernel to finish
+initializing the filesystem in the background when the filesystem is
+mounted. If the option value is omitted, it defaults to 1 to
+enable lazy inode table initialization.
.SH KNOWN BUGS
The minimum size of the filesystem as estimated by resize2fs may be
incorrect, especially for filesystems with 1k and 2k blocksizes.
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 216a626..1101364 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -41,7 +41,8 @@
#endif
static void fix_uninit_block_bitmaps(ext2_filsys fs);
-static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
+static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
+ int flags);
static errcode_t blocks_to_move(ext2_resize_t rfs);
static errcode_t block_mover(ext2_resize_t rfs);
static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
@@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
if (retval)
goto errout;
- retval = adjust_superblock(rfs, *new_size);
+ retval = adjust_superblock(rfs, *new_size, flags);
if (retval)
goto errout;
@@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
* filesystem.
*/
errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
- ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
+ ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
+ int flags)
{
errcode_t retval;
blk64_t overhead = 0;
@@ -497,8 +499,12 @@ retry:
adjblocks = 0;
ext2fs_bg_flags_zap(fs, i);
- if (csum_flag)
+ if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
+ ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
+ else if (csum_flag)
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
+ else
+ flags &= ~RESIZE_LAZY_ITABLE_INIT;
if (i == fs->group_desc_count-1) {
numblocks = (ext2fs_blocks_count(fs->super) -
fs->super->s_first_data_block) %
@@ -562,18 +568,57 @@ errout:
return (retval);
}
+static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
+{
+ unsigned long i, max_group;
+ errcode_t retval;
+ int adj = 0;
+
+ memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
+ adj = rfs->old_fs->group_desc_count;
+ max_group = fs->group_desc_count - adj;
+ if (rfs->progress) {
+ retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
+ 0, max_group);
+ if (retval)
+ goto out;
+ }
+
+ for (i = rfs->old_fs->group_desc_count;
+ i < fs->group_desc_count; i++) {
+ /*
+ * Write out the new inode table
+ */
+ retval = io_channel_write_blk64(fs->io,
+ ext2fs_inode_table_loc(fs, i),
+ fs->inode_blocks_per_group,
+ rfs->itable_buf);
+ if (retval)
+ break;
+
+ io_channel_flush(fs->io);
+ if (rfs->progress) {
+ retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
+ i - adj + 1, max_group);
+ if (retval)
+ break;
+ }
+ }
+ io_channel_flush(fs->io);
+out:
+ return retval;
+}
+
+
/*
* This routine adjusts the superblock and other data structures, both
* in disk as well as in memory...
*/
-static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
+static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
+ int flags)
{
- ext2_filsys fs;
- int adj = 0;
+ ext2_filsys fs;
errcode_t retval;
- blk64_t group_block;
- unsigned long i;
- unsigned long max_group;
fs = rfs->new_fs;
ext2fs_mark_super_dirty(fs);
@@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
if (retval)
return retval;
- retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
+ retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
+ flags);
if (retval)
goto errout;
@@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
if (retval)
goto errout;
- 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;
-
- adj = rfs->old_fs->group_desc_count;
- max_group = fs->group_desc_count - adj;
- if (rfs->progress) {
- retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
- 0, max_group);
- if (retval)
- goto errout;
- }
- for (i = rfs->old_fs->group_desc_count;
- i < fs->group_desc_count; i++) {
- /*
- * Write out the new inode table
- */
- retval = io_channel_write_blk64(fs->io,
- ext2fs_inode_table_loc(fs, i),
- fs->inode_blocks_per_group,
- rfs->itable_buf);
- if (retval) goto errout;
-
- io_channel_flush(fs->io);
- if (rfs->progress) {
- retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
- i - adj + 1, max_group);
- if (retval)
- goto errout;
- }
- group_block += fs->super->s_blocks_per_group;
- }
- io_channel_flush(fs->io);
- retval = 0;
-
+ if (!(flags & RESIZE_LAZY_ITABLE_INIT))
+ retval = write_inode_tables(rfs, fs);
errout:
return retval;
}
diff --git a/resize/resize2fs.h b/resize/resize2fs.h
index 2184759..a968071 100644
--- a/resize/resize2fs.h
+++ b/resize/resize2fs.h
@@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
#define RESIZE_PERCENT_COMPLETE 0x0100
#define RESIZE_VERBOSE 0x0200
+#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
/*
* The core state structure for the ext2 resizer
@@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
ext2fs_block_bitmap reserve_blocks,
- blk64_t new_size);
+ blk64_t new_size, int flags);
extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH] mke2fs: Add support for lazy journal initialization
2011-02-02 11:16 ` [PATCH v2 " Lukas Czerner
@ 2011-02-03 20:36 ` Andreas Dilger
2011-02-07 14:15 ` Lukas Czerner
2011-08-11 14:53 ` [PATCH v2 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
1 sibling, 1 reply; 13+ messages in thread
From: Andreas Dilger @ 2011-02-03 20:36 UTC (permalink / raw)
To: Ted Ts'o; +Cc: Lukas Czerner, ext4 List
[-- Attachment #1: Type: text/plain, Size: 488 bytes --]
This patch adds the ability to skip zeroing the journal on disk. This can
significantly speed up mke2fs with large journals. At worst the uninitialized
journal is only a very short-term risk (if at all), because the journal will
be overwritten on any new filesystem as soon as any significant amount of data
is written to disk, unlike lazy_itable_init which can leave uninitialized
itable blocks indefinitely (in the absence of the kernel init thread).
Cheers, Andreas
[-- Attachment #2: 0001-mke2fs-Add-lazy-journal-initialization-option.patch --]
[-- Type: application/octet-stream, Size: 7896 bytes --]
From a7f156b9078e2b121c4c7d509b55476804ae3f92 Mon Sep 17 00:00:00 2001
From: Andreas Dilger <adilger@dilger.ca>
Date: Thu, 3 Feb 2011 13:04:15 -0700
Subject: [PATCH] mke2fs: Add lazy journal initialization option
This patch adds the ability to skip zeroing the journal on disk. This can
significantly speed up mke2fs with large journals. At worst the uninitialized
journal is only a very short-term risk (if at all), because the journal will
be overwritten on any new filesystem as soon as any significant amount of data
is written to disk, unlike lazy_itable_init which can leave uninitialized
itable blocks indefinitely (in the absence of the kernel init thread).
Signed-off-by: Andreas Dilger <adilger@dilger.ca>
---
lib/ext2fs/ext2fs.h | 5 ++---
lib/ext2fs/mkjournal.c | 22 ++++++++++++++++++----
lib/ext2fs/unix_io.c | 2 ++
misc/mke2fs.8.in | 10 +++++++++-
misc/mke2fs.c | 19 +++++++++++++++++--
5 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index a204eb7..9fb77eb 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -193,10 +193,9 @@ typedef struct ext2_file *ext2_file_t;
/*
* Flags for mkjournal
- *
- * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
*/
-#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
+#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 /* create V1 superblock (deprecated) */
+#define EXT2_MKJOURNAL_LAZYINIT 0x0000002 /* don't zero journal inode before use*/
struct opaque_ext2_group_desc;
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 242c537..9ddd04c 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -103,7 +103,7 @@ static errcode_t write_journal_file(ext2_filsys fs, char *filename,
/* Open the device or journal file */
if ((fd = open(filename, O_WRONLY)) < 0) {
retval = errno;
- goto errout;
+ goto errfree;
}
/* Write the superblock out */
@@ -117,6 +117,9 @@ static errcode_t write_journal_file(ext2_filsys fs, char *filename,
goto errout;
memset(buf, 0, fs->blocksize);
+ if (flags & EXT2_MKJOURNAL_LAZYINIT)
+ goto success;
+
for (i = 1; i < size; i++) {
ret_size = write(fd, buf, fs->blocksize);
if (ret_size < 0) {
@@ -126,10 +129,12 @@ static errcode_t write_journal_file(ext2_filsys fs, char *filename,
if (ret_size != (int) fs->blocksize)
goto errout;
}
- close(fd);
+success:
retval = 0;
errout:
+ close(fd);
+errfree:
ext2fs_free_mem(&buf);
return retval;
}
@@ -213,6 +218,7 @@ struct mkjournal_struct {
blk64_t goal;
blk64_t blk_to_zero;
int zero_count;
+ int flags;
char *buf;
errcode_t err;
};
@@ -242,9 +248,9 @@ static int mkjournal_proc(ext2_filsys fs,
es->newblocks++;
retval = 0;
- if (blockcnt <= 0)
+ if (blockcnt <= 0) {
retval = io_channel_write_blk64(fs->io, new_blk, 1, es->buf);
- else {
+ } else if (!(es->flags & EXT2_MKJOURNAL_LAZYINIT)) {
if (es->zero_count) {
if ((es->blk_to_zero + es->zero_count == new_blk) &&
(es->zero_count < 1024))
@@ -308,6 +314,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
es.newblocks = 0;
es.buf = buf;
es.err = 0;
+ es.flags = flags;
es.zero_count = 0;
if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
@@ -504,6 +511,13 @@ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
return errno;
+ /* Note that we can't do lazy journal initialization for mounted
+ * filesystems, since the zero writing is also allocating the
+ * journal blocks. We could use fallocate, but not all kernels
+ * support that, and creating a journal on a mounted ext2
+ * filesystems is extremely rare these days... Skip it for now. */
+ flags &= ~EXT2_MKJOURNAL_LAZYINIT;
+
if ((retval = write_journal_file(fs, jfile, size, flags)))
goto errout;
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 82e0fe4..73e5daf 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -472,8 +472,10 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
if (flags & IO_FLAG_EXCLUSIVE)
open_flags |= O_EXCL;
+#ifdef O_DIRECT
if (flags & IO_FLAG_DIRECT_IO)
open_flags |= O_DIRECT;
+#endif
data->flags = flags;
#ifdef HAVE_OPEN64
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index 2eead17..b0f1e18 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -232,7 +232,15 @@ This speeds up filesystem
initialization noticeably, but it requires the kernel to finish
initializing the filesystem in the background when the filesystem is
first mounted. If the option value is omitted, it defaults to 1 to
-enable lazy inode table initialization.
+enable lazy inode table zeroing.
+.TP
+.B lazy_journal_init\fR[\fB= \fI{0 to disable, 1 to enable}\fR]
+If enabled, the journal inode will not be fully zeroed out by
+.BR mke2fs .
+This speeds up filesystem initialization noticeably, but carries some
+small risk if the system crashes before the journal has been overwritten
+entirely one time. If the option value is omitted, it defaults to 1 to
+enable lazy journal inode zeroing.
.TP
.B test_fs
Set a flag in the filesystem superblock indicating that it may be
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 0ba4a4c..f45de47 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -501,6 +501,10 @@ static void create_journal_dev(ext2_filsys fs)
_("while initializing journal superblock"));
exit(1);
}
+
+ if (journal_flags & EXT2_MKJOURNAL_LAZYINIT)
+ goto write_superblock;
+
ext2fs_numeric_progress_init(fs, &progress,
_("Zeroing journal device: "),
ext2fs_blocks_count(fs->super));
@@ -525,6 +529,8 @@ static void create_journal_dev(ext2_filsys fs)
}
ext2fs_zero_blocks2(0, 0, 0, 0, 0);
+ ext2fs_numeric_progress_close(fs, &progress, NULL);
+write_superblock:
retval = io_channel_write_blk64(fs->io,
fs->super->s_first_data_block+1,
1, buf);
@@ -533,7 +539,6 @@ static void create_journal_dev(ext2_filsys fs)
_("while writing journal superblock"));
exit(1);
}
- ext2fs_numeric_progress_close(fs, &progress, NULL);
}
static void show_stats(ext2_filsys fs)
@@ -744,6 +749,12 @@ static void parse_extended_opts(struct ext2_super_block *param,
}
} else if (!strcmp(token, "test_fs")) {
param->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+ } else if (!strcmp(token, "lazy_journal_init")) {
+ if (arg)
+ journal_flags |= strtoul(arg, &p, 0) ?
+ EXT2_MKJOURNAL_LAZYINIT : 0;
+ else
+ journal_flags |= EXT2_MKJOURNAL_LAZYINIT;
} else if (!strcmp(token, "lazy_itable_init")) {
if (arg)
lazy_itable_init = strtoul(arg, &p, 0);
@@ -767,7 +778,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
"\tstride=<RAID per-disk data chunk in blocks>\n"
"\tstripe-width=<RAID stride * data disks in blocks>\n"
"\tresize=<resize maximum size in blocks>\n"
- "\tlazy_itable_init=<0 to disable, 1 to enable>\n"
+ "\tlazy_itable_init={0 to disable, 1 to enable}\n"
+ "\tlazy_journal_init={0 to disable, 1 to enable}\n"
"\ttest_fs\n"
"\tdiscard\n"
"\tnodiscard\n\n"),
@@ -1756,6 +1768,9 @@ profile_error:
lazy_itable_init = get_bool_from_profile(fs_types,
"lazy_itable_init",
lazy_itable_init);
+ journal_flags |= get_bool_from_profile(fs_types,
+ "lazy_journal_init", 0) ?
+ EXT2_MKJOURNAL_LAZYINIT : 0;
discard = get_bool_from_profile(fs_types, "discard" , discard);
/* Get options from profile */
--
1.7.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] mke2fs: Add support for lazy journal initialization
2011-02-03 20:36 ` [PATCH] mke2fs: Add support for lazy journal initialization Andreas Dilger
@ 2011-02-07 14:15 ` Lukas Czerner
2011-02-07 16:29 ` Andreas Dilger
0 siblings, 1 reply; 13+ messages in thread
From: Lukas Czerner @ 2011-02-07 14:15 UTC (permalink / raw)
To: Andreas Dilger; +Cc: Ted Ts'o, Lukas Czerner, ext4 List
On Thu, 3 Feb 2011, Andreas Dilger wrote:
> This patch adds the ability to skip zeroing the journal on disk. This can
> significantly speed up mke2fs with large journals. At worst the uninitialized
> journal is only a very short-term risk (if at all), because the journal will
> be overwritten on any new filesystem as soon as any significant amount of data
> is written to disk, unlike lazy_itable_init which can leave uninitialized
> itable blocks indefinitely (in the absence of the kernel init thread).
>
> Cheers, Andreas
>
Hi Andreas,
I think that we can skip the journal zeroing if the underlying device,
or the journal device supports discard, and advertise that discard
zeroes data. It is the same behavior as in the case of inode tables and
it would be nice to have the same thing for journal. Are you planning to
implement this as well ?
Thanks!
-Lukas
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] mke2fs: Add support for lazy journal initialization
2011-02-07 14:15 ` Lukas Czerner
@ 2011-02-07 16:29 ` Andreas Dilger
0 siblings, 0 replies; 13+ messages in thread
From: Andreas Dilger @ 2011-02-07 16:29 UTC (permalink / raw)
To: Lukas Czerner; +Cc: Ted Ts'o, ext4 List
On 2011-02-07, at 06:15, Lukas Czerner wrote:
> On Thu, 3 Feb 2011, Andreas Dilger wrote:
>> This patch adds the ability to skip zeroing the journal on disk. This can
>> significantly speed up mke2fs with large journals. At worst the uninitialized
>> journal is only a very short-term risk (if at all), because the journal will
>> be overwritten on any new filesystem as soon as any significant amount of data
>> is written to disk, unlike lazy_itable_init which can leave uninitialized
>> itable blocks indefinitely (in the absence of the kernel init thread).
>
> I think that we can skip the journal zeroing if the underlying device,
> or the journal device supports discard, and advertise that discard
> zeroes data. It is the same behavior as in the case of inode tables and
> it would be nice to have the same thing for journal. Are you planning to
> implement this as well ?
That detection didn't exist when I originally wrote that patch. It definitely makes sense to default to not zeroing the journal if discard has been done.
Cheers, Andreas
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/2] resize2fs: Add support for lazy itable initialization
2011-02-02 11:16 ` [PATCH v2 " Lukas Czerner
2011-02-03 20:36 ` [PATCH] mke2fs: Add support for lazy journal initialization Andreas Dilger
@ 2011-08-11 14:53 ` Lukas Czerner
1 sibling, 0 replies; 13+ messages in thread
From: Lukas Czerner @ 2011-08-11 14:53 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, tytso, adilger
On Wed, 2 Feb 2011, Lukas Czerner wrote:
> Lazy inode table initialization speeds up file system resize operation
> because we can let the inode tables uninitialized. For some time now the
> mke2fs has similar option and now, when we have in-kernel lazyinit
> implementation we can add this feature to the resize2fs as well.
>
> This commit adds extended options '-E' to the resize2fs code along with
> the first extended option lazy_itable_init=n, where n is a 0 or 1,
> though the '=n' argument can be omitted. With lazy_itable_init extended
> option one can instruct resize2fs to skip inode table initialization to
> significantly speed-up file system resize. If the option is omitted and
> the file system supports lazy inode table initialization it defaults to 1.
Hi Ted,
those two patches are lying long enough. Any chance merging them ? Or
would I need to rebase and repost ?
Thanks!
-Lukas
>
> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> ---
> resize/main.c | 68 +++++++++++++++++++++++++++++++-
> resize/online.c | 2 +-
> resize/resize2fs.8.in | 20 +++++++++
> resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
> resize/resize2fs.h | 3 +-
> 5 files changed, 148 insertions(+), 50 deletions(-)
>
> diff --git a/resize/main.c b/resize/main.c
> index 28a49ba..03127ea 100644
> --- a/resize/main.c
> +++ b/resize/main.c
> @@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
> static void usage (char *prog)
> {
> fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
> - "[-p] device [new_size]\n\n"), prog);
> + "[-p] [-E extended_options] device [new_size]\n\n"),
> + prog);
>
> exit (1);
> }
> @@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
> #endif
> }
>
> +static void parse_extended_opts(int *flags, const char *opts)
> +{
> + char *buf, *token, *next, *p, *arg, *badopt = 0;
> + int len;
> + int r_usage = 0;
> +
> + len = strlen(opts);
> + buf = malloc(len+1);
> + if (!buf) {
> + fprintf(stderr,
> + _("Couldn't allocate memory to parse options!\n"));
> + exit(1);
> + }
> + strcpy(buf, opts);
> + for (token = buf; token && *token; token = next) {
> + p = strchr(token, ',');
> + next = 0;
> + if (p) {
> + *p = 0;
> + next = p+1;
> + }
> + arg = strchr(token, '=');
> + if (arg) {
> + *arg = 0;
> + arg++;
> + }
> + if (!strcmp(token, "lazy_itable_init")) {
> + int lazy;
> + if (arg)
> + lazy = strtoul(arg, &p, 0);
> + else
> + lazy = 1;
> + if (lazy == 1)
> + *flags |= RESIZE_LAZY_ITABLE_INIT;
> + } else {
> + r_usage++;
> + badopt = token;
> + }
> + }
> + if (r_usage) {
> + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> + "Extended options are separated by commas, "
> + "and may take an argument which\n"
> + "\tis set off by an equals ('=') sign.\n\n"
> + "Valid extended options are:\n"
> + "\tlazy_itable_init[={0 to disable, 1 to enable}]\n\n"),
> + badopt ? badopt : "");
> + free(buf);
> + exit(1);
> + }
> + free(buf);
> +}
> +
> int main (int argc, char ** argv)
> {
> errcode_t retval;
> @@ -174,6 +228,7 @@ int main (int argc, char ** argv)
> long sysval;
> int len, mount_flags;
> char *mtpt;
> + char * extended_opts = NULL;
>
> #ifdef ENABLE_NLS
> setlocale(LC_MESSAGES, "");
> @@ -189,7 +244,7 @@ int main (int argc, char ** argv)
> if (argc && *argv)
> program_name = *argv;
>
> - while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
> + while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
> switch (c) {
> case 'h':
> usage(program_name);
> @@ -215,6 +270,9 @@ int main (int argc, char ** argv)
> case 'S':
> use_stride = atoi(optarg);
> break;
> + case 'E':
> + extended_opts = optarg;
> + break;
> default:
> usage(program_name);
> }
> @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> if (io_options)
> *io_options++ = 0;
>
> + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> + flags |= RESIZE_LAZY_ITABLE_INIT;
> +
> + if (extended_opts)
> + parse_extended_opts(&flags, extended_opts);
> +
> /*
> * Figure out whether or not the device is mounted, and if it is
> * where it is mounted.
> diff --git a/resize/online.c b/resize/online.c
> index 1d8d4ec..7bc27b3 100644
> --- a/resize/online.c
> +++ b/resize/online.c
> @@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
> * but at least it allows on-line resizing to function.
> */
> new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
> - retval = adjust_fs_info(new_fs, fs, 0, *new_size);
> + retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
> if (retval)
> return retval;
>
> diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
> index e02345d..7fbc979 100644
> --- a/resize/resize2fs.8.in
> +++ b/resize/resize2fs.8.in
> @@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
> .B \-S
> .I RAID-stride
> ]
> +[
> +.B \-E
> +.I extended-options
> +]
> .I device
> [
> .I size
> @@ -128,6 +132,22 @@ The
> program will heuristically determine the RAID stride that was specified
> when the filesystem was created. This option allows the user to
> explicitly specify a RAID stride setting to be used by resize2fs instead.
> +.TP
> +.B \-E \fIextended-options
> +Set extended options for the filesystem. Extended options are comma
> +separated, and may take an argument using the equals ('=') sign.
> +The following extended options are supported:
> +.RS 1.2i
> +.TP
> +.B lazy_itable_init\fR[\fB= \fI{0 to disable, 1 to enable}\fR]
> +If enabled and the uninit_bg feature is enabled, the inode table will
> +not be zeroed out on disk by
> +.BR resize2fs .
> +This speeds up filesystem
> +resize noticeably, but it requires the kernel to finish
> +initializing the filesystem in the background when the filesystem is
> +mounted. If the option value is omitted, it defaults to 1 to
> +enable lazy inode table initialization.
> .SH KNOWN BUGS
> The minimum size of the filesystem as estimated by resize2fs may be
> incorrect, especially for filesystems with 1k and 2k blocksizes.
> diff --git a/resize/resize2fs.c b/resize/resize2fs.c
> index 216a626..1101364 100644
> --- a/resize/resize2fs.c
> +++ b/resize/resize2fs.c
> @@ -41,7 +41,8 @@
> #endif
>
> static void fix_uninit_block_bitmaps(ext2_filsys fs);
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags);
> static errcode_t blocks_to_move(ext2_resize_t rfs);
> static errcode_t block_mover(ext2_resize_t rfs);
> static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
> @@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> if (retval)
> goto errout;
>
> - retval = adjust_superblock(rfs, *new_size);
> + retval = adjust_superblock(rfs, *new_size, flags);
> if (retval)
> goto errout;
>
> @@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
> * filesystem.
> */
> errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> - ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
> + ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
> + int flags)
> {
> errcode_t retval;
> blk64_t overhead = 0;
> @@ -497,8 +499,12 @@ retry:
> adjblocks = 0;
>
> ext2fs_bg_flags_zap(fs, i);
> - if (csum_flag)
> + if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
> + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
> + else if (csum_flag)
> ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
> + else
> + flags &= ~RESIZE_LAZY_ITABLE_INIT;
> if (i == fs->group_desc_count-1) {
> numblocks = (ext2fs_blocks_count(fs->super) -
> fs->super->s_first_data_block) %
> @@ -562,18 +568,57 @@ errout:
> return (retval);
> }
>
> +static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
> +{
> + unsigned long i, max_group;
> + errcode_t retval;
> + int adj = 0;
> +
> + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
> + adj = rfs->old_fs->group_desc_count;
> + max_group = fs->group_desc_count - adj;
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + 0, max_group);
> + if (retval)
> + goto out;
> + }
> +
> + for (i = rfs->old_fs->group_desc_count;
> + i < fs->group_desc_count; i++) {
> + /*
> + * Write out the new inode table
> + */
> + retval = io_channel_write_blk64(fs->io,
> + ext2fs_inode_table_loc(fs, i),
> + fs->inode_blocks_per_group,
> + rfs->itable_buf);
> + if (retval)
> + break;
> +
> + io_channel_flush(fs->io);
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + i - adj + 1, max_group);
> + if (retval)
> + break;
> + }
> + }
> + io_channel_flush(fs->io);
> +out:
> + return retval;
> +}
> +
> +
> /*
> * This routine adjusts the superblock and other data structures, both
> * in disk as well as in memory...
> */
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags)
> {
> - ext2_filsys fs;
> - int adj = 0;
> + ext2_filsys fs;
> errcode_t retval;
> - blk64_t group_block;
> - unsigned long i;
> - unsigned long max_group;
>
> fs = rfs->new_fs;
> ext2fs_mark_super_dirty(fs);
> @@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> return retval;
>
> - retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
> + retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
> + flags);
> if (retval)
> goto errout;
>
> @@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> goto errout;
>
> - 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;
> -
> - adj = rfs->old_fs->group_desc_count;
> - max_group = fs->group_desc_count - adj;
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - 0, max_group);
> - if (retval)
> - goto errout;
> - }
> - for (i = rfs->old_fs->group_desc_count;
> - i < fs->group_desc_count; i++) {
> - /*
> - * Write out the new inode table
> - */
> - retval = io_channel_write_blk64(fs->io,
> - ext2fs_inode_table_loc(fs, i),
> - fs->inode_blocks_per_group,
> - rfs->itable_buf);
> - if (retval) goto errout;
> -
> - io_channel_flush(fs->io);
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - i - adj + 1, max_group);
> - if (retval)
> - goto errout;
> - }
> - group_block += fs->super->s_blocks_per_group;
> - }
> - io_channel_flush(fs->io);
> - retval = 0;
> -
> + if (!(flags & RESIZE_LAZY_ITABLE_INIT))
> + retval = write_inode_tables(rfs, fs);
> errout:
> return retval;
> }
> diff --git a/resize/resize2fs.h b/resize/resize2fs.h
> index 2184759..a968071 100644
> --- a/resize/resize2fs.h
> +++ b/resize/resize2fs.h
> @@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
>
> #define RESIZE_PERCENT_COMPLETE 0x0100
> #define RESIZE_VERBOSE 0x0200
> +#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
>
> /*
> * The core state structure for the ext2 resizer
> @@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
>
> extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> ext2fs_block_bitmap reserve_blocks,
> - blk64_t new_size);
> + blk64_t new_size, int flags);
> extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
>
>
>
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-02-01 17:14 [PATCH 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
2011-02-01 17:14 ` [PATCH 2/2] resize2fs: Add discard support Lukas Czerner
2011-02-01 19:15 ` [PATCH 1/2] resize2fs: Add support for lazy itable initialization Andreas Dilger
@ 2011-02-16 10:42 ` Lukas Czerner
2011-05-16 13:41 ` Lukas Czerner
2012-01-12 7:47 ` Lukas Czerner
3 siblings, 1 reply; 13+ messages in thread
From: Lukas Czerner @ 2011-02-16 10:42 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, tytso
On Tue, 1 Feb 2011, Lukas Czerner wrote:
> Lazy inode table initialization speeds up file system resize operation
> because we can let the inode tables uninitialized. For some time now the
> mke2fs has similar option and now, when we have in-kernel lazyinit
> implementation we can add this feature to the resize2fs as well.
>
> This commit adds extended options '-E' to the resize2fs code along with
> the first extended option lazy_itable_init=n. With lazy_itable_init
> extended option one can instruct resize2fs to skip inode table
> initialization to significantly speed-up file system resize. If the
> option is omitted and the file system supports lazy inode table
> initialization it defaults to 1.
ping
>
> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> ---
> resize/main.c | 68 +++++++++++++++++++++++++++++++-
> resize/online.c | 2 +-
> resize/resize2fs.8.in | 20 +++++++++
> resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
> resize/resize2fs.h | 3 +-
> 5 files changed, 148 insertions(+), 50 deletions(-)
>
> diff --git a/resize/main.c b/resize/main.c
> index 28a49ba..0f1a8db 100644
> --- a/resize/main.c
> +++ b/resize/main.c
> @@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
> static void usage (char *prog)
> {
> fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
> - "[-p] device [new_size]\n\n"), prog);
> + "[-p] [-E extended_options] device [new_size]\n\n"),
> + prog);
>
> exit (1);
> }
> @@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
> #endif
> }
>
> +static void parse_extended_opts(int *flags, const char *opts)
> +{
> + char *buf, *token, *next, *p, *arg, *badopt = 0;
> + int len;
> + int r_usage = 0;
> +
> + len = strlen(opts);
> + buf = malloc(len+1);
> + if (!buf) {
> + fprintf(stderr,
> + _("Couldn't allocate memory to parse options!\n"));
> + exit(1);
> + }
> + strcpy(buf, opts);
> + for (token = buf; token && *token; token = next) {
> + p = strchr(token, ',');
> + next = 0;
> + if (p) {
> + *p = 0;
> + next = p+1;
> + }
> + arg = strchr(token, '=');
> + if (arg) {
> + *arg = 0;
> + arg++;
> + }
> + if (!strcmp(token, "lazy_itable_init")) {
> + int lazy;
> + if (arg)
> + lazy = strtoul(arg, &p, 0);
> + else
> + lazy = 1;
> + if (lazy)
> + *flags |= RESIZE_LAZY_ITABLE_INIT;
> + } else {
> + r_usage++;
> + badopt = token;
> + }
> + }
> + if (r_usage) {
> + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> + "Extended options are separated by commas, "
> + "and may take an argument which\n"
> + "\tis set off by an equals ('=') sign.\n\n"
> + "Valid extended options are:\n"
> + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
> + badopt ? badopt : "");
> + free(buf);
> + exit(1);
> + }
> + free(buf);
> +}
> +
> int main (int argc, char ** argv)
> {
> errcode_t retval;
> @@ -174,6 +228,7 @@ int main (int argc, char ** argv)
> long sysval;
> int len, mount_flags;
> char *mtpt;
> + char * extended_opts = NULL;
>
> #ifdef ENABLE_NLS
> setlocale(LC_MESSAGES, "");
> @@ -189,7 +244,7 @@ int main (int argc, char ** argv)
> if (argc && *argv)
> program_name = *argv;
>
> - while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
> + while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
> switch (c) {
> case 'h':
> usage(program_name);
> @@ -215,6 +270,9 @@ int main (int argc, char ** argv)
> case 'S':
> use_stride = atoi(optarg);
> break;
> + case 'E':
> + extended_opts = optarg;
> + break;
> default:
> usage(program_name);
> }
> @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> if (io_options)
> *io_options++ = 0;
>
> + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> + flags |= RESIZE_LAZY_ITABLE_INIT;
> +
> + if (extended_opts)
> + parse_extended_opts(&flags, extended_opts);
> +
> /*
> * Figure out whether or not the device is mounted, and if it is
> * where it is mounted.
> diff --git a/resize/online.c b/resize/online.c
> index 1d8d4ec..7bc27b3 100644
> --- a/resize/online.c
> +++ b/resize/online.c
> @@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
> * but at least it allows on-line resizing to function.
> */
> new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
> - retval = adjust_fs_info(new_fs, fs, 0, *new_size);
> + retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
> if (retval)
> return retval;
>
> diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
> index e02345d..448265c 100644
> --- a/resize/resize2fs.8.in
> +++ b/resize/resize2fs.8.in
> @@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
> .B \-S
> .I RAID-stride
> ]
> +[
> +.B \-E
> +.I extended-options
> +]
> .I device
> [
> .I size
> @@ -128,6 +132,22 @@ The
> program will heuristically determine the RAID stride that was specified
> when the filesystem was created. This option allows the user to
> explicitly specify a RAID stride setting to be used by resize2fs instead.
> +.TP
> +.B \-E \fIextended-options
> +Set extended options for the filesystem. Extended options are comma
> +separated, and may take an argument using the equals ('=') sign.
> +The following extended options are supported:
> +.RS 1.2i
> +.TP
> +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
> +If enabled and the uninit_bg feature is enabled, the inode table will
> +not be fully initialized by
> +.BR resize2fs .
> +This speeds up filesystem
> +resize noticeably, but it requires the kernel to finish
> +initializing the filesystem in the background when the filesystem is
> +mounted. If the option value is omitted, it defaults to 1 to
> +enable lazy inode table initialization.
> .SH KNOWN BUGS
> The minimum size of the filesystem as estimated by resize2fs may be
> incorrect, especially for filesystems with 1k and 2k blocksizes.
> diff --git a/resize/resize2fs.c b/resize/resize2fs.c
> index 216a626..1101364 100644
> --- a/resize/resize2fs.c
> +++ b/resize/resize2fs.c
> @@ -41,7 +41,8 @@
> #endif
>
> static void fix_uninit_block_bitmaps(ext2_filsys fs);
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags);
> static errcode_t blocks_to_move(ext2_resize_t rfs);
> static errcode_t block_mover(ext2_resize_t rfs);
> static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
> @@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> if (retval)
> goto errout;
>
> - retval = adjust_superblock(rfs, *new_size);
> + retval = adjust_superblock(rfs, *new_size, flags);
> if (retval)
> goto errout;
>
> @@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
> * filesystem.
> */
> errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> - ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
> + ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
> + int flags)
> {
> errcode_t retval;
> blk64_t overhead = 0;
> @@ -497,8 +499,12 @@ retry:
> adjblocks = 0;
>
> ext2fs_bg_flags_zap(fs, i);
> - if (csum_flag)
> + if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
> + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
> + else if (csum_flag)
> ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
> + else
> + flags &= ~RESIZE_LAZY_ITABLE_INIT;
> if (i == fs->group_desc_count-1) {
> numblocks = (ext2fs_blocks_count(fs->super) -
> fs->super->s_first_data_block) %
> @@ -562,18 +568,57 @@ errout:
> return (retval);
> }
>
> +static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
> +{
> + unsigned long i, max_group;
> + errcode_t retval;
> + int adj = 0;
> +
> + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
> + adj = rfs->old_fs->group_desc_count;
> + max_group = fs->group_desc_count - adj;
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + 0, max_group);
> + if (retval)
> + goto out;
> + }
> +
> + for (i = rfs->old_fs->group_desc_count;
> + i < fs->group_desc_count; i++) {
> + /*
> + * Write out the new inode table
> + */
> + retval = io_channel_write_blk64(fs->io,
> + ext2fs_inode_table_loc(fs, i),
> + fs->inode_blocks_per_group,
> + rfs->itable_buf);
> + if (retval)
> + break;
> +
> + io_channel_flush(fs->io);
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + i - adj + 1, max_group);
> + if (retval)
> + break;
> + }
> + }
> + io_channel_flush(fs->io);
> +out:
> + return retval;
> +}
> +
> +
> /*
> * This routine adjusts the superblock and other data structures, both
> * in disk as well as in memory...
> */
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags)
> {
> - ext2_filsys fs;
> - int adj = 0;
> + ext2_filsys fs;
> errcode_t retval;
> - blk64_t group_block;
> - unsigned long i;
> - unsigned long max_group;
>
> fs = rfs->new_fs;
> ext2fs_mark_super_dirty(fs);
> @@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> return retval;
>
> - retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
> + retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
> + flags);
> if (retval)
> goto errout;
>
> @@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> goto errout;
>
> - 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;
> -
> - adj = rfs->old_fs->group_desc_count;
> - max_group = fs->group_desc_count - adj;
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - 0, max_group);
> - if (retval)
> - goto errout;
> - }
> - for (i = rfs->old_fs->group_desc_count;
> - i < fs->group_desc_count; i++) {
> - /*
> - * Write out the new inode table
> - */
> - retval = io_channel_write_blk64(fs->io,
> - ext2fs_inode_table_loc(fs, i),
> - fs->inode_blocks_per_group,
> - rfs->itable_buf);
> - if (retval) goto errout;
> -
> - io_channel_flush(fs->io);
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - i - adj + 1, max_group);
> - if (retval)
> - goto errout;
> - }
> - group_block += fs->super->s_blocks_per_group;
> - }
> - io_channel_flush(fs->io);
> - retval = 0;
> -
> + if (!(flags & RESIZE_LAZY_ITABLE_INIT))
> + retval = write_inode_tables(rfs, fs);
> errout:
> return retval;
> }
> diff --git a/resize/resize2fs.h b/resize/resize2fs.h
> index 2184759..a968071 100644
> --- a/resize/resize2fs.h
> +++ b/resize/resize2fs.h
> @@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
>
> #define RESIZE_PERCENT_COMPLETE 0x0100
> #define RESIZE_VERBOSE 0x0200
> +#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
>
> /*
> * The core state structure for the ext2 resizer
> @@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
>
> extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> ext2fs_block_bitmap reserve_blocks,
> - blk64_t new_size);
> + blk64_t new_size, int flags);
> extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
>
>
>
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-02-16 10:42 ` [PATCH " Lukas Czerner
@ 2011-05-16 13:41 ` Lukas Czerner
2011-09-01 8:36 ` Lukas Czerner
0 siblings, 1 reply; 13+ messages in thread
From: Lukas Czerner @ 2011-05-16 13:41 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, tytso
On Wed, 16 Feb 2011, Lukas Czerner wrote:
> On Tue, 1 Feb 2011, Lukas Czerner wrote:
>
> > Lazy inode table initialization speeds up file system resize operation
> > because we can let the inode tables uninitialized. For some time now the
> > mke2fs has similar option and now, when we have in-kernel lazyinit
> > implementation we can add this feature to the resize2fs as well.
> >
> > This commit adds extended options '-E' to the resize2fs code along with
> > the first extended option lazy_itable_init=n. With lazy_itable_init
> > extended option one can instruct resize2fs to skip inode table
> > initialization to significantly speed-up file system resize. If the
> > option is omitted and the file system supports lazy inode table
> > initialization it defaults to 1.
>
> ping
ping^2
>
> >
> > Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> > ---
> > resize/main.c | 68 +++++++++++++++++++++++++++++++-
> > resize/online.c | 2 +-
> > resize/resize2fs.8.in | 20 +++++++++
> > resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
> > resize/resize2fs.h | 3 +-
> > 5 files changed, 148 insertions(+), 50 deletions(-)
> >
> > diff --git a/resize/main.c b/resize/main.c
> > index 28a49ba..0f1a8db 100644
> > --- a/resize/main.c
> > +++ b/resize/main.c
> > @@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
> > static void usage (char *prog)
> > {
> > fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
> > - "[-p] device [new_size]\n\n"), prog);
> > + "[-p] [-E extended_options] device [new_size]\n\n"),
> > + prog);
> >
> > exit (1);
> > }
> > @@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
> > #endif
> > }
> >
> > +static void parse_extended_opts(int *flags, const char *opts)
> > +{
> > + char *buf, *token, *next, *p, *arg, *badopt = 0;
> > + int len;
> > + int r_usage = 0;
> > +
> > + len = strlen(opts);
> > + buf = malloc(len+1);
> > + if (!buf) {
> > + fprintf(stderr,
> > + _("Couldn't allocate memory to parse options!\n"));
> > + exit(1);
> > + }
> > + strcpy(buf, opts);
> > + for (token = buf; token && *token; token = next) {
> > + p = strchr(token, ',');
> > + next = 0;
> > + if (p) {
> > + *p = 0;
> > + next = p+1;
> > + }
> > + arg = strchr(token, '=');
> > + if (arg) {
> > + *arg = 0;
> > + arg++;
> > + }
> > + if (!strcmp(token, "lazy_itable_init")) {
> > + int lazy;
> > + if (arg)
> > + lazy = strtoul(arg, &p, 0);
> > + else
> > + lazy = 1;
> > + if (lazy)
> > + *flags |= RESIZE_LAZY_ITABLE_INIT;
> > + } else {
> > + r_usage++;
> > + badopt = token;
> > + }
> > + }
> > + if (r_usage) {
> > + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> > + "Extended options are separated by commas, "
> > + "and may take an argument which\n"
> > + "\tis set off by an equals ('=') sign.\n\n"
> > + "Valid extended options are:\n"
> > + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
> > + badopt ? badopt : "");
> > + free(buf);
> > + exit(1);
> > + }
> > + free(buf);
> > +}
> > +
> > int main (int argc, char ** argv)
> > {
> > errcode_t retval;
> > @@ -174,6 +228,7 @@ int main (int argc, char ** argv)
> > long sysval;
> > int len, mount_flags;
> > char *mtpt;
> > + char * extended_opts = NULL;
> >
> > #ifdef ENABLE_NLS
> > setlocale(LC_MESSAGES, "");
> > @@ -189,7 +244,7 @@ int main (int argc, char ** argv)
> > if (argc && *argv)
> > program_name = *argv;
> >
> > - while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
> > + while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
> > switch (c) {
> > case 'h':
> > usage(program_name);
> > @@ -215,6 +270,9 @@ int main (int argc, char ** argv)
> > case 'S':
> > use_stride = atoi(optarg);
> > break;
> > + case 'E':
> > + extended_opts = optarg;
> > + break;
> > default:
> > usage(program_name);
> > }
> > @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> > if (io_options)
> > *io_options++ = 0;
> >
> > + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> > + flags |= RESIZE_LAZY_ITABLE_INIT;
> > +
> > + if (extended_opts)
> > + parse_extended_opts(&flags, extended_opts);
> > +
> > /*
> > * Figure out whether or not the device is mounted, and if it is
> > * where it is mounted.
> > diff --git a/resize/online.c b/resize/online.c
> > index 1d8d4ec..7bc27b3 100644
> > --- a/resize/online.c
> > +++ b/resize/online.c
> > @@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
> > * but at least it allows on-line resizing to function.
> > */
> > new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
> > - retval = adjust_fs_info(new_fs, fs, 0, *new_size);
> > + retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
> > if (retval)
> > return retval;
> >
> > diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
> > index e02345d..448265c 100644
> > --- a/resize/resize2fs.8.in
> > +++ b/resize/resize2fs.8.in
> > @@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
> > .B \-S
> > .I RAID-stride
> > ]
> > +[
> > +.B \-E
> > +.I extended-options
> > +]
> > .I device
> > [
> > .I size
> > @@ -128,6 +132,22 @@ The
> > program will heuristically determine the RAID stride that was specified
> > when the filesystem was created. This option allows the user to
> > explicitly specify a RAID stride setting to be used by resize2fs instead.
> > +.TP
> > +.B \-E \fIextended-options
> > +Set extended options for the filesystem. Extended options are comma
> > +separated, and may take an argument using the equals ('=') sign.
> > +The following extended options are supported:
> > +.RS 1.2i
> > +.TP
> > +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
> > +If enabled and the uninit_bg feature is enabled, the inode table will
> > +not be fully initialized by
> > +.BR resize2fs .
> > +This speeds up filesystem
> > +resize noticeably, but it requires the kernel to finish
> > +initializing the filesystem in the background when the filesystem is
> > +mounted. If the option value is omitted, it defaults to 1 to
> > +enable lazy inode table initialization.
> > .SH KNOWN BUGS
> > The minimum size of the filesystem as estimated by resize2fs may be
> > incorrect, especially for filesystems with 1k and 2k blocksizes.
> > diff --git a/resize/resize2fs.c b/resize/resize2fs.c
> > index 216a626..1101364 100644
> > --- a/resize/resize2fs.c
> > +++ b/resize/resize2fs.c
> > @@ -41,7 +41,8 @@
> > #endif
> >
> > static void fix_uninit_block_bitmaps(ext2_filsys fs);
> > -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
> > +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> > + int flags);
> > static errcode_t blocks_to_move(ext2_resize_t rfs);
> > static errcode_t block_mover(ext2_resize_t rfs);
> > static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
> > @@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> > if (retval)
> > goto errout;
> >
> > - retval = adjust_superblock(rfs, *new_size);
> > + retval = adjust_superblock(rfs, *new_size, flags);
> > if (retval)
> > goto errout;
> >
> > @@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
> > * filesystem.
> > */
> > errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> > - ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
> > + ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
> > + int flags)
> > {
> > errcode_t retval;
> > blk64_t overhead = 0;
> > @@ -497,8 +499,12 @@ retry:
> > adjblocks = 0;
> >
> > ext2fs_bg_flags_zap(fs, i);
> > - if (csum_flag)
> > + if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
> > + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
> > + else if (csum_flag)
> > ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
> > + else
> > + flags &= ~RESIZE_LAZY_ITABLE_INIT;
> > if (i == fs->group_desc_count-1) {
> > numblocks = (ext2fs_blocks_count(fs->super) -
> > fs->super->s_first_data_block) %
> > @@ -562,18 +568,57 @@ errout:
> > return (retval);
> > }
> >
> > +static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
> > +{
> > + unsigned long i, max_group;
> > + errcode_t retval;
> > + int adj = 0;
> > +
> > + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
> > + adj = rfs->old_fs->group_desc_count;
> > + max_group = fs->group_desc_count - adj;
> > + if (rfs->progress) {
> > + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > + 0, max_group);
> > + if (retval)
> > + goto out;
> > + }
> > +
> > + for (i = rfs->old_fs->group_desc_count;
> > + i < fs->group_desc_count; i++) {
> > + /*
> > + * Write out the new inode table
> > + */
> > + retval = io_channel_write_blk64(fs->io,
> > + ext2fs_inode_table_loc(fs, i),
> > + fs->inode_blocks_per_group,
> > + rfs->itable_buf);
> > + if (retval)
> > + break;
> > +
> > + io_channel_flush(fs->io);
> > + if (rfs->progress) {
> > + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > + i - adj + 1, max_group);
> > + if (retval)
> > + break;
> > + }
> > + }
> > + io_channel_flush(fs->io);
> > +out:
> > + return retval;
> > +}
> > +
> > +
> > /*
> > * This routine adjusts the superblock and other data structures, both
> > * in disk as well as in memory...
> > */
> > -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> > + int flags)
> > {
> > - ext2_filsys fs;
> > - int adj = 0;
> > + ext2_filsys fs;
> > errcode_t retval;
> > - blk64_t group_block;
> > - unsigned long i;
> > - unsigned long max_group;
> >
> > fs = rfs->new_fs;
> > ext2fs_mark_super_dirty(fs);
> > @@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > if (retval)
> > return retval;
> >
> > - retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
> > + retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
> > + flags);
> > if (retval)
> > goto errout;
> >
> > @@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > if (retval)
> > goto errout;
> >
> > - 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;
> > -
> > - adj = rfs->old_fs->group_desc_count;
> > - max_group = fs->group_desc_count - adj;
> > - if (rfs->progress) {
> > - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > - 0, max_group);
> > - if (retval)
> > - goto errout;
> > - }
> > - for (i = rfs->old_fs->group_desc_count;
> > - i < fs->group_desc_count; i++) {
> > - /*
> > - * Write out the new inode table
> > - */
> > - retval = io_channel_write_blk64(fs->io,
> > - ext2fs_inode_table_loc(fs, i),
> > - fs->inode_blocks_per_group,
> > - rfs->itable_buf);
> > - if (retval) goto errout;
> > -
> > - io_channel_flush(fs->io);
> > - if (rfs->progress) {
> > - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > - i - adj + 1, max_group);
> > - if (retval)
> > - goto errout;
> > - }
> > - group_block += fs->super->s_blocks_per_group;
> > - }
> > - io_channel_flush(fs->io);
> > - retval = 0;
> > -
> > + if (!(flags & RESIZE_LAZY_ITABLE_INIT))
> > + retval = write_inode_tables(rfs, fs);
> > errout:
> > return retval;
> > }
> > diff --git a/resize/resize2fs.h b/resize/resize2fs.h
> > index 2184759..a968071 100644
> > --- a/resize/resize2fs.h
> > +++ b/resize/resize2fs.h
> > @@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
> >
> > #define RESIZE_PERCENT_COMPLETE 0x0100
> > #define RESIZE_VERBOSE 0x0200
> > +#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
> >
> > /*
> > * The core state structure for the ext2 resizer
> > @@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> >
> > extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> > ext2fs_block_bitmap reserve_blocks,
> > - blk64_t new_size);
> > + blk64_t new_size, int flags);
> > extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
> >
> >
> >
>
>
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-05-16 13:41 ` Lukas Czerner
@ 2011-09-01 8:36 ` Lukas Czerner
0 siblings, 0 replies; 13+ messages in thread
From: Lukas Czerner @ 2011-09-01 8:36 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, tytso
On Mon, 16 May 2011, Lukas Czerner wrote:
> On Wed, 16 Feb 2011, Lukas Czerner wrote:
>
> > On Tue, 1 Feb 2011, Lukas Czerner wrote:
> >
> > > Lazy inode table initialization speeds up file system resize operation
> > > because we can let the inode tables uninitialized. For some time now the
> > > mke2fs has similar option and now, when we have in-kernel lazyinit
> > > implementation we can add this feature to the resize2fs as well.
> > >
> > > This commit adds extended options '-E' to the resize2fs code along with
> > > the first extended option lazy_itable_init=n. With lazy_itable_init
> > > extended option one can instruct resize2fs to skip inode table
> > > initialization to significantly speed-up file system resize. If the
> > > option is omitted and the file system supports lazy inode table
> > > initialization it defaults to 1.
> >
> > ping
>
> ping^2
ping^3
>
> >
> > >
> > > Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> > > ---
> > > resize/main.c | 68 +++++++++++++++++++++++++++++++-
> > > resize/online.c | 2 +-
> > > resize/resize2fs.8.in | 20 +++++++++
> > > resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
> > > resize/resize2fs.h | 3 +-
> > > 5 files changed, 148 insertions(+), 50 deletions(-)
> > >
> > > diff --git a/resize/main.c b/resize/main.c
> > > index 28a49ba..0f1a8db 100644
> > > --- a/resize/main.c
> > > +++ b/resize/main.c
> > > @@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
> > > static void usage (char *prog)
> > > {
> > > fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
> > > - "[-p] device [new_size]\n\n"), prog);
> > > + "[-p] [-E extended_options] device [new_size]\n\n"),
> > > + prog);
> > >
> > > exit (1);
> > > }
> > > @@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
> > > #endif
> > > }
> > >
> > > +static void parse_extended_opts(int *flags, const char *opts)
> > > +{
> > > + char *buf, *token, *next, *p, *arg, *badopt = 0;
> > > + int len;
> > > + int r_usage = 0;
> > > +
> > > + len = strlen(opts);
> > > + buf = malloc(len+1);
> > > + if (!buf) {
> > > + fprintf(stderr,
> > > + _("Couldn't allocate memory to parse options!\n"));
> > > + exit(1);
> > > + }
> > > + strcpy(buf, opts);
> > > + for (token = buf; token && *token; token = next) {
> > > + p = strchr(token, ',');
> > > + next = 0;
> > > + if (p) {
> > > + *p = 0;
> > > + next = p+1;
> > > + }
> > > + arg = strchr(token, '=');
> > > + if (arg) {
> > > + *arg = 0;
> > > + arg++;
> > > + }
> > > + if (!strcmp(token, "lazy_itable_init")) {
> > > + int lazy;
> > > + if (arg)
> > > + lazy = strtoul(arg, &p, 0);
> > > + else
> > > + lazy = 1;
> > > + if (lazy)
> > > + *flags |= RESIZE_LAZY_ITABLE_INIT;
> > > + } else {
> > > + r_usage++;
> > > + badopt = token;
> > > + }
> > > + }
> > > + if (r_usage) {
> > > + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> > > + "Extended options are separated by commas, "
> > > + "and may take an argument which\n"
> > > + "\tis set off by an equals ('=') sign.\n\n"
> > > + "Valid extended options are:\n"
> > > + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
> > > + badopt ? badopt : "");
> > > + free(buf);
> > > + exit(1);
> > > + }
> > > + free(buf);
> > > +}
> > > +
> > > int main (int argc, char ** argv)
> > > {
> > > errcode_t retval;
> > > @@ -174,6 +228,7 @@ int main (int argc, char ** argv)
> > > long sysval;
> > > int len, mount_flags;
> > > char *mtpt;
> > > + char * extended_opts = NULL;
> > >
> > > #ifdef ENABLE_NLS
> > > setlocale(LC_MESSAGES, "");
> > > @@ -189,7 +244,7 @@ int main (int argc, char ** argv)
> > > if (argc && *argv)
> > > program_name = *argv;
> > >
> > > - while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
> > > + while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
> > > switch (c) {
> > > case 'h':
> > > usage(program_name);
> > > @@ -215,6 +270,9 @@ int main (int argc, char ** argv)
> > > case 'S':
> > > use_stride = atoi(optarg);
> > > break;
> > > + case 'E':
> > > + extended_opts = optarg;
> > > + break;
> > > default:
> > > usage(program_name);
> > > }
> > > @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> > > if (io_options)
> > > *io_options++ = 0;
> > >
> > > + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> > > + flags |= RESIZE_LAZY_ITABLE_INIT;
> > > +
> > > + if (extended_opts)
> > > + parse_extended_opts(&flags, extended_opts);
> > > +
> > > /*
> > > * Figure out whether or not the device is mounted, and if it is
> > > * where it is mounted.
> > > diff --git a/resize/online.c b/resize/online.c
> > > index 1d8d4ec..7bc27b3 100644
> > > --- a/resize/online.c
> > > +++ b/resize/online.c
> > > @@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
> > > * but at least it allows on-line resizing to function.
> > > */
> > > new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
> > > - retval = adjust_fs_info(new_fs, fs, 0, *new_size);
> > > + retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
> > > if (retval)
> > > return retval;
> > >
> > > diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
> > > index e02345d..448265c 100644
> > > --- a/resize/resize2fs.8.in
> > > +++ b/resize/resize2fs.8.in
> > > @@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
> > > .B \-S
> > > .I RAID-stride
> > > ]
> > > +[
> > > +.B \-E
> > > +.I extended-options
> > > +]
> > > .I device
> > > [
> > > .I size
> > > @@ -128,6 +132,22 @@ The
> > > program will heuristically determine the RAID stride that was specified
> > > when the filesystem was created. This option allows the user to
> > > explicitly specify a RAID stride setting to be used by resize2fs instead.
> > > +.TP
> > > +.B \-E \fIextended-options
> > > +Set extended options for the filesystem. Extended options are comma
> > > +separated, and may take an argument using the equals ('=') sign.
> > > +The following extended options are supported:
> > > +.RS 1.2i
> > > +.TP
> > > +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
> > > +If enabled and the uninit_bg feature is enabled, the inode table will
> > > +not be fully initialized by
> > > +.BR resize2fs .
> > > +This speeds up filesystem
> > > +resize noticeably, but it requires the kernel to finish
> > > +initializing the filesystem in the background when the filesystem is
> > > +mounted. If the option value is omitted, it defaults to 1 to
> > > +enable lazy inode table initialization.
> > > .SH KNOWN BUGS
> > > The minimum size of the filesystem as estimated by resize2fs may be
> > > incorrect, especially for filesystems with 1k and 2k blocksizes.
> > > diff --git a/resize/resize2fs.c b/resize/resize2fs.c
> > > index 216a626..1101364 100644
> > > --- a/resize/resize2fs.c
> > > +++ b/resize/resize2fs.c
> > > @@ -41,7 +41,8 @@
> > > #endif
> > >
> > > static void fix_uninit_block_bitmaps(ext2_filsys fs);
> > > -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
> > > +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> > > + int flags);
> > > static errcode_t blocks_to_move(ext2_resize_t rfs);
> > > static errcode_t block_mover(ext2_resize_t rfs);
> > > static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
> > > @@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> > > if (retval)
> > > goto errout;
> > >
> > > - retval = adjust_superblock(rfs, *new_size);
> > > + retval = adjust_superblock(rfs, *new_size, flags);
> > > if (retval)
> > > goto errout;
> > >
> > > @@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
> > > * filesystem.
> > > */
> > > errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> > > - ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
> > > + ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
> > > + int flags)
> > > {
> > > errcode_t retval;
> > > blk64_t overhead = 0;
> > > @@ -497,8 +499,12 @@ retry:
> > > adjblocks = 0;
> > >
> > > ext2fs_bg_flags_zap(fs, i);
> > > - if (csum_flag)
> > > + if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
> > > + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
> > > + else if (csum_flag)
> > > ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
> > > + else
> > > + flags &= ~RESIZE_LAZY_ITABLE_INIT;
> > > if (i == fs->group_desc_count-1) {
> > > numblocks = (ext2fs_blocks_count(fs->super) -
> > > fs->super->s_first_data_block) %
> > > @@ -562,18 +568,57 @@ errout:
> > > return (retval);
> > > }
> > >
> > > +static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
> > > +{
> > > + unsigned long i, max_group;
> > > + errcode_t retval;
> > > + int adj = 0;
> > > +
> > > + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
> > > + adj = rfs->old_fs->group_desc_count;
> > > + max_group = fs->group_desc_count - adj;
> > > + if (rfs->progress) {
> > > + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > > + 0, max_group);
> > > + if (retval)
> > > + goto out;
> > > + }
> > > +
> > > + for (i = rfs->old_fs->group_desc_count;
> > > + i < fs->group_desc_count; i++) {
> > > + /*
> > > + * Write out the new inode table
> > > + */
> > > + retval = io_channel_write_blk64(fs->io,
> > > + ext2fs_inode_table_loc(fs, i),
> > > + fs->inode_blocks_per_group,
> > > + rfs->itable_buf);
> > > + if (retval)
> > > + break;
> > > +
> > > + io_channel_flush(fs->io);
> > > + if (rfs->progress) {
> > > + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > > + i - adj + 1, max_group);
> > > + if (retval)
> > > + break;
> > > + }
> > > + }
> > > + io_channel_flush(fs->io);
> > > +out:
> > > + return retval;
> > > +}
> > > +
> > > +
> > > /*
> > > * This routine adjusts the superblock and other data structures, both
> > > * in disk as well as in memory...
> > > */
> > > -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > > +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> > > + int flags)
> > > {
> > > - ext2_filsys fs;
> > > - int adj = 0;
> > > + ext2_filsys fs;
> > > errcode_t retval;
> > > - blk64_t group_block;
> > > - unsigned long i;
> > > - unsigned long max_group;
> > >
> > > fs = rfs->new_fs;
> > > ext2fs_mark_super_dirty(fs);
> > > @@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > > if (retval)
> > > return retval;
> > >
> > > - retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
> > > + retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
> > > + flags);
> > > if (retval)
> > > goto errout;
> > >
> > > @@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> > > if (retval)
> > > goto errout;
> > >
> > > - 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;
> > > -
> > > - adj = rfs->old_fs->group_desc_count;
> > > - max_group = fs->group_desc_count - adj;
> > > - if (rfs->progress) {
> > > - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > > - 0, max_group);
> > > - if (retval)
> > > - goto errout;
> > > - }
> > > - for (i = rfs->old_fs->group_desc_count;
> > > - i < fs->group_desc_count; i++) {
> > > - /*
> > > - * Write out the new inode table
> > > - */
> > > - retval = io_channel_write_blk64(fs->io,
> > > - ext2fs_inode_table_loc(fs, i),
> > > - fs->inode_blocks_per_group,
> > > - rfs->itable_buf);
> > > - if (retval) goto errout;
> > > -
> > > - io_channel_flush(fs->io);
> > > - if (rfs->progress) {
> > > - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> > > - i - adj + 1, max_group);
> > > - if (retval)
> > > - goto errout;
> > > - }
> > > - group_block += fs->super->s_blocks_per_group;
> > > - }
> > > - io_channel_flush(fs->io);
> > > - retval = 0;
> > > -
> > > + if (!(flags & RESIZE_LAZY_ITABLE_INIT))
> > > + retval = write_inode_tables(rfs, fs);
> > > errout:
> > > return retval;
> > > }
> > > diff --git a/resize/resize2fs.h b/resize/resize2fs.h
> > > index 2184759..a968071 100644
> > > --- a/resize/resize2fs.h
> > > +++ b/resize/resize2fs.h
> > > @@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
> > >
> > > #define RESIZE_PERCENT_COMPLETE 0x0100
> > > #define RESIZE_VERBOSE 0x0200
> > > +#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
> > >
> > > /*
> > > * The core state structure for the ext2 resizer
> > > @@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> > >
> > > extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> > > ext2fs_block_bitmap reserve_blocks,
> > > - blk64_t new_size);
> > > + blk64_t new_size, int flags);
> > > extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
> > >
> > >
> > >
> >
> >
>
>
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] resize2fs: Add support for lazy itable initialization
2011-02-01 17:14 [PATCH 1/2] resize2fs: Add support for lazy itable initialization Lukas Czerner
` (2 preceding siblings ...)
2011-02-16 10:42 ` [PATCH " Lukas Czerner
@ 2012-01-12 7:47 ` Lukas Czerner
3 siblings, 0 replies; 13+ messages in thread
From: Lukas Czerner @ 2012-01-12 7:47 UTC (permalink / raw)
To: Lukas Czerner; +Cc: linux-ext4, Ted Ts'o
On Tue, 1 Feb 2011, Lukas Czerner wrote:
> Lazy inode table initialization speeds up file system resize operation
> because we can let the inode tables uninitialized. For some time now the
> mke2fs has similar option and now, when we have in-kernel lazyinit
> implementation we can add this feature to the resize2fs as well.
>
> This commit adds extended options '-E' to the resize2fs code along with
> the first extended option lazy_itable_init=n. With lazy_itable_init
> extended option one can instruct resize2fs to skip inode table
> initialization to significantly speed-up file system resize. If the
> option is omitted and the file system supports lazy inode table
> initialization it defaults to 1.
Quadruple ping :)
Hi Ted,
I know that the code has probably already changed since I have posted
the patch a _year ago_ not talking about the new resize interface. But
do you think that it is worth ti trying to rebase it so you can merge it
? I am just asking so it does not hang in the mailing list for another
year again :)
Thanks!
-Lukas
>
> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> ---
> resize/main.c | 68 +++++++++++++++++++++++++++++++-
> resize/online.c | 2 +-
> resize/resize2fs.8.in | 20 +++++++++
> resize/resize2fs.c | 105 +++++++++++++++++++++++++++---------------------
> resize/resize2fs.h | 3 +-
> 5 files changed, 148 insertions(+), 50 deletions(-)
>
> diff --git a/resize/main.c b/resize/main.c
> index 28a49ba..0f1a8db 100644
> --- a/resize/main.c
> +++ b/resize/main.c
> @@ -40,7 +40,8 @@ char *program_name, *device_name, *io_options;
> static void usage (char *prog)
> {
> fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
> - "[-p] device [new_size]\n\n"), prog);
> + "[-p] [-E extended_options] device [new_size]\n\n"),
> + prog);
>
> exit (1);
> }
> @@ -146,6 +147,59 @@ static void determine_fs_stride(ext2_filsys fs)
> #endif
> }
>
> +static void parse_extended_opts(int *flags, const char *opts)
> +{
> + char *buf, *token, *next, *p, *arg, *badopt = 0;
> + int len;
> + int r_usage = 0;
> +
> + len = strlen(opts);
> + buf = malloc(len+1);
> + if (!buf) {
> + fprintf(stderr,
> + _("Couldn't allocate memory to parse options!\n"));
> + exit(1);
> + }
> + strcpy(buf, opts);
> + for (token = buf; token && *token; token = next) {
> + p = strchr(token, ',');
> + next = 0;
> + if (p) {
> + *p = 0;
> + next = p+1;
> + }
> + arg = strchr(token, '=');
> + if (arg) {
> + *arg = 0;
> + arg++;
> + }
> + if (!strcmp(token, "lazy_itable_init")) {
> + int lazy;
> + if (arg)
> + lazy = strtoul(arg, &p, 0);
> + else
> + lazy = 1;
> + if (lazy)
> + *flags |= RESIZE_LAZY_ITABLE_INIT;
> + } else {
> + r_usage++;
> + badopt = token;
> + }
> + }
> + if (r_usage) {
> + fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
> + "Extended options are separated by commas, "
> + "and may take an argument which\n"
> + "\tis set off by an equals ('=') sign.\n\n"
> + "Valid extended options are:\n"
> + "\tlazy_itable_init=<0 to disable, 1 to enable>\n\n"),
> + badopt ? badopt : "");
> + free(buf);
> + exit(1);
> + }
> + free(buf);
> +}
> +
> int main (int argc, char ** argv)
> {
> errcode_t retval;
> @@ -174,6 +228,7 @@ int main (int argc, char ** argv)
> long sysval;
> int len, mount_flags;
> char *mtpt;
> + char * extended_opts = NULL;
>
> #ifdef ENABLE_NLS
> setlocale(LC_MESSAGES, "");
> @@ -189,7 +244,7 @@ int main (int argc, char ** argv)
> if (argc && *argv)
> program_name = *argv;
>
> - while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
> + while ((c = getopt (argc, argv, "d:fFhMPpS:E:")) != EOF) {
> switch (c) {
> case 'h':
> usage(program_name);
> @@ -215,6 +270,9 @@ int main (int argc, char ** argv)
> case 'S':
> use_stride = atoi(optarg);
> break;
> + case 'E':
> + extended_opts = optarg;
> + break;
> default:
> usage(program_name);
> }
> @@ -232,6 +290,12 @@ int main (int argc, char ** argv)
> if (io_options)
> *io_options++ = 0;
>
> + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
> + flags |= RESIZE_LAZY_ITABLE_INIT;
> +
> + if (extended_opts)
> + parse_extended_opts(&flags, extended_opts);
> +
> /*
> * Figure out whether or not the device is mounted, and if it is
> * where it is mounted.
> diff --git a/resize/online.c b/resize/online.c
> index 1d8d4ec..7bc27b3 100644
> --- a/resize/online.c
> +++ b/resize/online.c
> @@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
> * but at least it allows on-line resizing to function.
> */
> new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
> - retval = adjust_fs_info(new_fs, fs, 0, *new_size);
> + retval = adjust_fs_info(new_fs, fs, 0, *new_size, 0);
> if (retval)
> return retval;
>
> diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
> index e02345d..448265c 100644
> --- a/resize/resize2fs.8.in
> +++ b/resize/resize2fs.8.in
> @@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
> .B \-S
> .I RAID-stride
> ]
> +[
> +.B \-E
> +.I extended-options
> +]
> .I device
> [
> .I size
> @@ -128,6 +132,22 @@ The
> program will heuristically determine the RAID stride that was specified
> when the filesystem was created. This option allows the user to
> explicitly specify a RAID stride setting to be used by resize2fs instead.
> +.TP
> +.B \-E \fIextended-options
> +Set extended options for the filesystem. Extended options are comma
> +separated, and may take an argument using the equals ('=') sign.
> +The following extended options are supported:
> +.RS 1.2i
> +.TP
> +.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
> +If enabled and the uninit_bg feature is enabled, the inode table will
> +not be fully initialized by
> +.BR resize2fs .
> +This speeds up filesystem
> +resize noticeably, but it requires the kernel to finish
> +initializing the filesystem in the background when the filesystem is
> +mounted. If the option value is omitted, it defaults to 1 to
> +enable lazy inode table initialization.
> .SH KNOWN BUGS
> The minimum size of the filesystem as estimated by resize2fs may be
> incorrect, especially for filesystems with 1k and 2k blocksizes.
> diff --git a/resize/resize2fs.c b/resize/resize2fs.c
> index 216a626..1101364 100644
> --- a/resize/resize2fs.c
> +++ b/resize/resize2fs.c
> @@ -41,7 +41,8 @@
> #endif
>
> static void fix_uninit_block_bitmaps(ext2_filsys fs);
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags);
> static errcode_t blocks_to_move(ext2_resize_t rfs);
> static errcode_t block_mover(ext2_resize_t rfs);
> static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
> @@ -102,7 +103,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
> if (retval)
> goto errout;
>
> - retval = adjust_superblock(rfs, *new_size);
> + retval = adjust_superblock(rfs, *new_size, flags);
> if (retval)
> goto errout;
>
> @@ -288,7 +289,8 @@ static void free_gdp_blocks(ext2_filsys fs,
> * filesystem.
> */
> errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> - ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
> + ext2fs_block_bitmap reserve_blocks, blk64_t new_size,
> + int flags)
> {
> errcode_t retval;
> blk64_t overhead = 0;
> @@ -497,8 +499,12 @@ retry:
> adjblocks = 0;
>
> ext2fs_bg_flags_zap(fs, i);
> - if (csum_flag)
> + if (csum_flag && (flags & RESIZE_LAZY_ITABLE_INIT))
> + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
> + else if (csum_flag)
> ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT | EXT2_BG_INODE_ZEROED);
> + else
> + flags &= ~RESIZE_LAZY_ITABLE_INIT;
> if (i == fs->group_desc_count-1) {
> numblocks = (ext2fs_blocks_count(fs->super) -
> fs->super->s_first_data_block) %
> @@ -562,18 +568,57 @@ errout:
> return (retval);
> }
>
> +static errcode_t write_inode_tables(ext2_resize_t rfs, ext2_filsys fs)
> +{
> + unsigned long i, max_group;
> + errcode_t retval;
> + int adj = 0;
> +
> + memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
> + adj = rfs->old_fs->group_desc_count;
> + max_group = fs->group_desc_count - adj;
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + 0, max_group);
> + if (retval)
> + goto out;
> + }
> +
> + for (i = rfs->old_fs->group_desc_count;
> + i < fs->group_desc_count; i++) {
> + /*
> + * Write out the new inode table
> + */
> + retval = io_channel_write_blk64(fs->io,
> + ext2fs_inode_table_loc(fs, i),
> + fs->inode_blocks_per_group,
> + rfs->itable_buf);
> + if (retval)
> + break;
> +
> + io_channel_flush(fs->io);
> + if (rfs->progress) {
> + retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> + i - adj + 1, max_group);
> + if (retval)
> + break;
> + }
> + }
> + io_channel_flush(fs->io);
> +out:
> + return retval;
> +}
> +
> +
> /*
> * This routine adjusts the superblock and other data structures, both
> * in disk as well as in memory...
> */
> -static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> +static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size,
> + int flags)
> {
> - ext2_filsys fs;
> - int adj = 0;
> + ext2_filsys fs;
> errcode_t retval;
> - blk64_t group_block;
> - unsigned long i;
> - unsigned long max_group;
>
> fs = rfs->new_fs;
> ext2fs_mark_super_dirty(fs);
> @@ -585,7 +630,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> return retval;
>
> - retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
> + retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size,
> + flags);
> if (retval)
> goto errout;
>
> @@ -626,41 +672,8 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
> if (retval)
> goto errout;
>
> - 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;
> -
> - adj = rfs->old_fs->group_desc_count;
> - max_group = fs->group_desc_count - adj;
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - 0, max_group);
> - if (retval)
> - goto errout;
> - }
> - for (i = rfs->old_fs->group_desc_count;
> - i < fs->group_desc_count; i++) {
> - /*
> - * Write out the new inode table
> - */
> - retval = io_channel_write_blk64(fs->io,
> - ext2fs_inode_table_loc(fs, i),
> - fs->inode_blocks_per_group,
> - rfs->itable_buf);
> - if (retval) goto errout;
> -
> - io_channel_flush(fs->io);
> - if (rfs->progress) {
> - retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
> - i - adj + 1, max_group);
> - if (retval)
> - goto errout;
> - }
> - group_block += fs->super->s_blocks_per_group;
> - }
> - io_channel_flush(fs->io);
> - retval = 0;
> -
> + if (!(flags & RESIZE_LAZY_ITABLE_INIT))
> + retval = write_inode_tables(rfs, fs);
> errout:
> return retval;
> }
> diff --git a/resize/resize2fs.h b/resize/resize2fs.h
> index 2184759..a968071 100644
> --- a/resize/resize2fs.h
> +++ b/resize/resize2fs.h
> @@ -79,6 +79,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
>
> #define RESIZE_PERCENT_COMPLETE 0x0100
> #define RESIZE_VERBOSE 0x0200
> +#define RESIZE_LAZY_ITABLE_INIT 0x0400 /* Do not initialize inode tables*/
>
> /*
> * The core state structure for the ext2 resizer
> @@ -129,7 +130,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
>
> extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
> ext2fs_block_bitmap reserve_blocks,
> - blk64_t new_size);
> + blk64_t new_size, int flags);
> extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
>
>
>
--
^ permalink raw reply [flat|nested] 13+ messages in thread