2014-07-10 14:35:20

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

[PATCH 1/5] lib: add EXT2_ prefix for SUPERBLOCK_{OFFSET,SIZE}
[PATCH 2/5] journal: use consts instead of 1024 and add helper for
[PATCH 3/5] tune2fs: remove_journal_device(): use the correct block
[PATCH 4/5] tune2fs: update journal super block when changing UUID
[PATCH 5/5] tune2fs: update journal users while updating fs UUID


2014-07-10 14:35:23

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 1/5] lib: add EXT2_ prefix for SUPERBLOCK_{OFFSET,SIZE}

Since mostly all macros have this prefix, and to avoid potential name
clashes.

Proposed-by: Andreas Dilger <[email protected]>
Signed-off-by: Azat Khuzhin <[email protected]>
Reviewed-by: Andreas Dilger <[email protected]>
---
e2fsck/super.c | 4 ++--
e2fsck/util.c | 4 ++--
lib/ext2fs/closefs.c | 18 +++++++++---------
lib/ext2fs/dupfs.c | 8 ++++----
lib/ext2fs/ext2fs.h | 10 ++++++++--
lib/ext2fs/imager.c | 4 ++--
lib/ext2fs/initialize.c | 4 ++--
lib/ext2fs/openfs.c | 12 ++++++------
lib/ext2fs/tst_badblocks.c | 4 ++--
lib/ext2fs/undo_io.c | 4 ++--
misc/e2undo.c | 4 ++--
misc/mke2fs.c | 4 ++--
12 files changed, 43 insertions(+), 37 deletions(-)

diff --git a/e2fsck/super.c b/e2fsck/super.c
index c8669f8..d58a789 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -921,7 +921,7 @@ int check_backup_super_block(e2fsck_t ctx)
dgrp_t g;
blk64_t sb;
int ret = 0;
- char buf[SUPERBLOCK_SIZE];
+ char buf[EXT2_SUPERBLOCK_SIZE];
struct ext2_super_block *backup_sb;

/*
@@ -944,7 +944,7 @@ int check_backup_super_block(e2fsck_t ctx)

sb = ext2fs_group_first_block2(fs, g);

- retval = io_channel_read_blk(fs->io, sb, -SUPERBLOCK_SIZE,
+ retval = io_channel_read_blk(fs->io, sb, -EXT2_SUPERBLOCK_SIZE,
buf);
if (retval)
continue;
diff --git a/e2fsck/util.c b/e2fsck/util.c
index fec6179..75e11de 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -540,7 +540,7 @@ blk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
if (manager->open(name, 0, &io) != 0)
goto cleanup;

- if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
+ if (ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &buf))
goto cleanup;
sb = (struct ext2_super_block *) buf;

@@ -551,7 +551,7 @@ blk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
superblock++;
io_channel_set_blksize(io, blocksize);
if (io_channel_read_blk64(io, superblock,
- -SUPERBLOCK_SIZE, buf))
+ -EXT2_SUPERBLOCK_SIZE, buf))
continue;
#ifdef WORDS_BIGENDIAN
if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index c2eaec1..5223400 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -199,8 +199,8 @@ static errcode_t write_primary_superblock(ext2_filsys fs,

if (!fs->io->manager->write_byte || !fs->orig_super) {
fallback:
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
- retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE,
+ io_channel_set_blksize(fs->io, EXT2_SUPERBLOCK_OFFSET);
+ retval = io_channel_write_blk64(fs->io, 1, -EXT2_SUPERBLOCK_SIZE,
super);
io_channel_set_blksize(fs->io, fs->blocksize);
return retval;
@@ -209,11 +209,11 @@ static errcode_t write_primary_superblock(ext2_filsys fs,
old_super = (__u16 *) fs->orig_super;
new_super = (__u16 *) super;

- for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
+ for (check_idx = 0; check_idx < EXT2_SUPERBLOCK_SIZE/2; check_idx++) {
if (old_super[check_idx] == new_super[check_idx])
continue;
write_idx = check_idx;
- for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
+ for (check_idx++; check_idx < EXT2_SUPERBLOCK_SIZE/2; check_idx++)
if (old_super[check_idx] == new_super[check_idx])
break;
size = 2 * (check_idx - write_idx);
@@ -222,14 +222,14 @@ static errcode_t write_primary_superblock(ext2_filsys fs,
size, write_idx*2);
#endif
retval = io_channel_write_byte(fs->io,
- SUPERBLOCK_OFFSET + (2 * write_idx), size,
+ EXT2_SUPERBLOCK_OFFSET + (2 * write_idx), size,
new_super + write_idx);
if (retval == EXT2_ET_UNIMPLEMENTED)
goto fallback;
if (retval)
return retval;
}
- memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
+ memcpy(fs->orig_super, super, EXT2_SUPERBLOCK_SIZE);
return 0;
}

@@ -269,7 +269,7 @@ static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
if (retval)
return retval;

- return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE,
+ return io_channel_write_blk64(fs->io, group_block, -EXT2_SUPERBLOCK_SIZE,
super_shadow);
}

@@ -320,7 +320,7 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
/* Prepare the group descriptors for writing */
#ifdef WORDS_BIGENDIAN
retval = EXT2_ET_NO_MEMORY;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
+ retval = ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
@@ -412,7 +412,7 @@ write_primary_superblock_only:
/*
* Write out master superblock. This has to be done
* separately, since it is located at a fixed location
- * (SUPERBLOCK_OFFSET). We flush all other pending changes
+ * (EXT2_SUPERBLOCK_OFFSET). We flush all other pending changes
* out to disk first, just to avoid a race condition with an
* insy-tinsy window....
*/
diff --git a/lib/ext2fs/dupfs.c b/lib/ext2fs/dupfs.c
index 02721e1..6840b12 100644
--- a/lib/ext2fs/dupfs.c
+++ b/lib/ext2fs/dupfs.c
@@ -53,15 +53,15 @@ errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
goto errout;
strcpy(fs->device_name, src->device_name);

- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
+ retval = ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &fs->super);
if (retval)
goto errout;
- memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
+ memcpy(fs->super, src->super, EXT2_SUPERBLOCK_SIZE);

- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
+ retval = ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &fs->orig_super);
if (retval)
goto errout;
- memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
+ memcpy(fs->orig_super, src->orig_super, EXT2_SUPERBLOCK_SIZE);

retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 599c972..f21c389 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -36,8 +36,14 @@ extern "C" {
* (some versions have the padding set up so that the superblock is
* 1032 bytes long).
*/
-#define SUPERBLOCK_OFFSET 1024
-#define SUPERBLOCK_SIZE 1024
+#define EXT2_SUPERBLOCK_OFFSET 1024
+#define EXT2_SUPERBLOCK_SIZE 1024
+/**
+ * Deprecated, will be removed in the next release
+ * Instead use EXT2_* with the same names.
+ */
+#define SUPERBLOCK_OFFSET EXT2_SUPERBLOCK_OFFSET
+#define SUPERBLOCK_SIZE EXT2_SUPERBLOCK_SIZE

/*
* The last ext2fs revision level that this version of the library is
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index 378a3c8..92f6db9 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -203,7 +203,7 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
* Write out the superblock
*/
memset(buf, 0, fs->blocksize);
- memcpy(buf, fs->super, SUPERBLOCK_SIZE);
+ memcpy(buf, fs->super, EXT2_SUPERBLOCK_SIZE);
actual = write(fd, buf, fs->blocksize);
if (actual == -1) {
retval = errno;
@@ -266,7 +266,7 @@ errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
/*
* Now copy in the superblock and group descriptors
*/
- memcpy(fs->super, buf, SUPERBLOCK_SIZE);
+ memcpy(fs->super, buf, EXT2_SUPERBLOCK_SIZE);

memcpy(fs->group_desc, buf + fs->blocksize,
fs->blocksize * fs->group_desc_count);
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 75fbf8e..f1a6f55 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -133,12 +133,12 @@ errcode_t ext2fs_initialize(const char *name, int flags,
goto cleanup;

strcpy(fs->device_name, name);
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
+ retval = ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &super);
if (retval)
goto cleanup;
fs->super = super;

- memset(super, 0, SUPERBLOCK_SIZE);
+ memset(super, 0, EXT2_SUPERBLOCK_SIZE);

#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index b4122de..6055a86 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -164,7 +164,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
goto cleanup;
fs->image_io = fs->io;
fs->io->app_data = fs;
- retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super);
+ retval = io_channel_alloc_buf(fs->io, -EXT2_SUPERBLOCK_SIZE, &fs->super);
if (retval)
goto cleanup;
if (flags & EXT2_FLAG_IMAGE_FILE) {
@@ -187,7 +187,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
* If the user specifies a specific block # for the
* superblock, then he/she must also specify the block size!
* Otherwise, read the master superblock located at offset
- * SUPERBLOCK_OFFSET from the start of the partition.
+ * EXT2_SUPERBLOCK_OFFSET from the start of the partition.
*
* Note: we only save a backup copy of the superblock if we
* are reading the superblock from the primary superblock location.
@@ -201,19 +201,19 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
group_block = superblock;
fs->orig_super = 0;
} else {
- io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
+ io_channel_set_blksize(fs->io, EXT2_SUPERBLOCK_OFFSET);
superblock = 1;
group_block = 0;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
+ retval = ext2fs_get_mem(EXT2_SUPERBLOCK_SIZE, &fs->orig_super);
if (retval)
goto cleanup;
}
- retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
+ retval = io_channel_read_blk(fs->io, superblock, -EXT2_SUPERBLOCK_SIZE,
fs->super);
if (retval)
goto cleanup;
if (fs->orig_super)
- memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
+ memcpy(fs->orig_super, fs->super, EXT2_SUPERBLOCK_SIZE);

if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) {
retval = 0;
diff --git a/lib/ext2fs/tst_badblocks.c b/lib/ext2fs/tst_badblocks.c
index 3b39ef1..85d63fb 100644
--- a/lib/ext2fs/tst_badblocks.c
+++ b/lib/ext2fs/tst_badblocks.c
@@ -225,8 +225,8 @@ int file_test_invalid(badblocks_list bb)
fs = malloc(sizeof(struct struct_ext2_filsys));
memset(fs, 0, sizeof(struct struct_ext2_filsys));
fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
- fs->super = malloc(SUPERBLOCK_SIZE);
- memset(fs->super, 0, SUPERBLOCK_SIZE);
+ fs->super = malloc(EXT2_SUPERBLOCK_SIZE);
+ memset(fs->super, 0, EXT2_SUPERBLOCK_SIZE);
fs->super->s_first_data_block = 1;
ext2fs_blocks_count_set(fs->super, 100);

diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c
index 0e05c93..c498b2a 100644
--- a/lib/ext2fs/undo_io.c
+++ b/lib/ext2fs/undo_io.c
@@ -113,8 +113,8 @@ static errcode_t write_file_system_identity(io_channel undo_channel,
channel = data->real;
block_size = channel->block_size;

- io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
- retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
+ io_channel_set_blksize(channel, EXT2_SUPERBLOCK_OFFSET);
+ retval = io_channel_read_blk64(channel, 1, -EXT2_SUPERBLOCK_SIZE, &super);
if (retval)
goto err_out;

diff --git a/misc/e2undo.c b/misc/e2undo.c
index a43c26f..cc8fa77 100644
--- a/misc/e2undo.c
+++ b/misc/e2undo.c
@@ -45,8 +45,8 @@ static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
TDB_DATA tdb_key, tdb_data;
struct ext2_super_block super;

- io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
- retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
+ io_channel_set_blksize(channel, EXT2_SUPERBLOCK_OFFSET);
+ retval = io_channel_read_blk64(channel, 1, -EXT2_SUPERBLOCK_SIZE, &super);
if (retval) {
com_err(prg_name, retval,
"%s", _("Failed to read the file system data \n"));
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index b451cc3..df5b9d8 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -2398,8 +2398,8 @@ static int should_do_undo(const char *name)
goto open_err_out;
}

- io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
- retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
+ io_channel_set_blksize(channel, EXT2_SUPERBLOCK_OFFSET);
+ retval = io_channel_read_blk64(channel, 1, -EXT2_SUPERBLOCK_SIZE, &super);
if (retval) {
retval = 0;
goto err_out;
--
2.0.0


2014-07-10 14:35:31

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 4/5] tune2fs: update journal super block when changing UUID for fs.

Using -U option you can change the UUID for fs, however it will not work
for journal device, since it have a copy of this UUID inside jsb (i.e.
journal super block). So copy UUID on change into that block.

Here is the initial thread:
http://comments.gmane.org/gmane.comp.file-systems.ext4/44532

You can reproduce this by executing following commands:
$ fallocate -l100M /tmp/dev
$ fallocate -l100M /tmp/journal
$ sudo /sbin/losetup /dev/loop1 /tmp/dev
$ sudo /sbin/losetup /dev/loop0 /tmp/journal
$ mke2fs -O journal_dev /tmp/journal
$ tune2fs -U da1f2ed0-60f6-aaaa-92fd-738701418523 /tmp/journal
$ sudo mke2fs -t ext4 -J device=/dev/loop0 /dev/loop1
$ dumpe2fs -h /tmp/dev | fgrep UUID
dumpe2fs 1.43-WIP (18-May-2014)
Filesystem UUID: 8a776be9-12eb-411f-8e88-b873575ecfb6
Journal UUID: e3d02151-e776-4865-af25-aecb7291e8e5
$ sudo e2fsck /dev/vdc
e2fsck 1.43-WIP (18-May-2014)
External journal does not support this filesystem

/dev/loop1: ********** WARNING: Filesystem still has errors **********

Reported-by: Chin Tzung Cheng <[email protected]>
Signed-off-by: Azat Khuzhin <[email protected]>
Reviewed-by: Andreas Dilger <[email protected]>
---
misc/tune2fs.c | 74 ++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 56 insertions(+), 18 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index b395c7c..d1fa6ba 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -180,6 +180,38 @@ static __u32 clear_ok_features[3] = {
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM
};

+/**
+ * Try to get journal super block if any
+ */
+static int get_journal_sb(ext2_filsys jfs, char buf[EXT2_SUPERBLOCK_SIZE])
+{
+ int retval;
+ int start;
+ journal_superblock_t *jsb;
+
+ if (!(jfs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+
+ /* Get the journal superblock */
+ if ((retval = io_channel_read_blk64(jfs->io,
+ ext2fs_journal_sb_start(jfs->blocksize), -EXT2_SUPERBLOCK_SIZE, buf))) {
+ com_err(program_name, retval, "%s",
+ _("while reading journal superblock"));
+ return retval;
+ }
+
+ jsb = (journal_superblock_t *) buf;
+ if ((jsb->s_header.h_magic != (unsigned)ntohl(JFS_MAGIC_NUMBER)) ||
+ (jsb->s_header.h_blocktype != (unsigned)ntohl(JFS_SUPERBLOCK_V2))) {
+ fputs(_("Journal superblock not found!\n"), stderr);
+ return EXT2_ET_BAD_MAGIC;
+ }
+
+ return 0;
+}
+
/*
* Remove an external journal from the filesystem
*/
@@ -223,29 +255,15 @@ static int remove_journal_device(ext2_filsys fs)
_("while trying to open external journal"));
goto no_valid_journal;
}
- if (!(jfs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
- fprintf(stderr, _("%s is not a journal device.\n"),
- journal_path);
- goto no_valid_journal;
- }

- start = ext2fs_journal_sb_start(fs->blocksize);
- /* Get the journal superblock */
- if ((retval = io_channel_read_blk64(jfs->io, start,
- -EXT2_SUPERBLOCK_SIZE, buf))) {
- com_err(program_name, retval, "%s",
- _("while reading journal superblock"));
+ if ((retval = get_journal_sb(jfs, buf))) {
+ if (retval == EXT2_ET_UNSUPP_FEATURE)
+ fprintf(stderr, _("%s is not a journal device.\n"),
+ journal_path);
goto no_valid_journal;
}

jsb = (journal_superblock_t *) buf;
- if ((jsb->s_header.h_magic != (unsigned)ntohl(JFS_MAGIC_NUMBER)) ||
- (jsb->s_header.h_blocktype != (unsigned)ntohl(JFS_SUPERBLOCK_V2))) {
- fputs(_("Journal superblock not found!\n"), stderr);
- goto no_valid_journal;
- }
-
/* Find the filesystem UUID */
nr_users = ntohl(jsb->s_nr_users);
for (i = 0; i < nr_users; i++) {
@@ -2695,6 +2713,7 @@ retry_open:
if (U_flag) {
int set_csum = 0;
dgrp_t i;
+ char buf[EXT2_SUPERBLOCK_SIZE];

if (ext2fs_has_group_desc_csum(fs)) {
/*
@@ -2740,6 +2759,25 @@ retry_open:
ext2fs_group_desc_csum_set(fs, i);
fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
}
+
+ /* If this is a journal dev, we need to copy UUID into jsb */
+ if (!(rc = get_journal_sb(fs, buf))) {
+ journal_superblock_t *jsb;
+
+ jsb = (journal_superblock_t *) buf;
+ fputs(_("Need to update journal superblock.\n"), stdout);
+ memcpy(jsb->s_uuid, sb->s_uuid, sizeof(sb->s_uuid));
+
+ /* Writeback the journal superblock */
+ if ((rc = io_channel_write_blk64(fs->io,
+ ext2fs_journal_sb_start(fs->blocksize),
+ -EXT2_SUPERBLOCK_SIZE, buf)))
+ goto closefs;
+ } else if (rc != EXT2_ET_UNSUPP_FEATURE)
+ goto closefs;
+ else
+ rc = 0; /** Reset rc to avoid ext2fs_mmp_stop() */
+
ext2fs_mark_super_dirty(fs);
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
--
2.0.0


2014-07-10 14:35:29

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 3/5] tune2fs: remove_journal_device(): use the correct block to find jsb

Signed-off-by: Azat Khuzhin <[email protected]>
Reviewed-by: Andreas Dilger <[email protected]>
---
misc/tune2fs.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 9d21623..b395c7c 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -193,6 +193,7 @@ static int remove_journal_device(ext2_filsys fs)
errcode_t retval;
int commit_remove_journal = 0;
io_manager io_ptr;
+ int start;

if (f_flag)
commit_remove_journal = 1; /* force removal even if error */
@@ -229,8 +230,10 @@ static int remove_journal_device(ext2_filsys fs)
goto no_valid_journal;
}

+ start = ext2fs_journal_sb_start(fs->blocksize);
/* Get the journal superblock */
- if ((retval = io_channel_read_blk64(jfs->io, 1, -EXT2_SUPERBLOCK_SIZE, buf))) {
+ if ((retval = io_channel_read_blk64(jfs->io, start,
+ -EXT2_SUPERBLOCK_SIZE, buf))) {
com_err(program_name, retval, "%s",
_("while reading journal superblock"));
goto no_valid_journal;
@@ -261,7 +264,8 @@ static int remove_journal_device(ext2_filsys fs)
jsb->s_nr_users = htonl(nr_users);

/* Write back the journal superblock */
- if ((retval = io_channel_write_blk64(jfs->io, 1, -EXT2_SUPERBLOCK_SIZE, buf))) {
+ if ((retval = io_channel_write_blk64(jfs->io, start,
+ -EXT2_SUPERBLOCK_SIZE, buf))) {
com_err(program_name, retval,
"while writing journal superblock.");
goto no_valid_journal;
--
2.0.0


2014-07-10 14:35:26

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 2/5] journal: use consts instead of 1024 and add helper for journal with 1k blocksize

Use EXT2_MIN_BLOCK_SIZE/JFS_MIN_JOURNAL_BLOCKS instead of hardcoded 1024
when it is okay, and also add a helper ext2fs_journal_sb_start() that
will return start of journal sb with special case for fs with 1k block
size.

Signed-off-by: Azat Khuzhin <[email protected]>
Reviewed-by: Andreas Dilger <[email protected]>
---
e2fsck/journal.c | 5 ++---
lib/ext2fs/ext2fs.h | 1 +
lib/ext2fs/mkjournal.c | 28 ++++++++++++++++------------
misc/tune2fs.c | 6 +++---
4 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index a7b1150..785d283 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -443,8 +443,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
if (ext_journal) {
blk64_t maxlen;

- if (ctx->fs->blocksize == 1024)
- start = 1;
+ start = ext2fs_journal_sb_start(ctx->fs->blocksize) - 1;
bh = getblk(dev_journal, start, ctx->fs->blocksize);
if (!bh) {
retval = EXT2_ET_NO_MEMORY;
@@ -455,7 +454,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
brelse(bh);
goto errout;
}
- memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
+ memcpy(&jsuper, start ? bh->b_data : bh->b_data + EXT2_SUPERBLOCK_OFFSET,
sizeof(jsuper));
brelse(bh);
#ifdef WORDS_BIGENDIAN
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index f21c389..1a96f24 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1504,6 +1504,7 @@ extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks,
extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
blk64_t goal, int flags);
extern int ext2fs_default_journal_size(__u64 num_blocks);
+extern int ext2fs_journal_sb_start(int blocksize);

/* openfs.c */
extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 884d9c0..ae5cd56 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -49,7 +49,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
errcode_t retval;
journal_superblock_t *jsb;

- if (num_blocks < 1024)
+ if (num_blocks < JFS_MIN_JOURNAL_BLOCKS)
return EXT2_ET_JOURNAL_TOO_SMALL;

if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
@@ -75,10 +75,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
if (fs->super->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
jsb->s_nr_users = 0;
- if (fs->blocksize == 1024)
- jsb->s_first = htonl(3);
- else
- jsb->s_first = htonl(2);
+ jsb->s_first = htonl(ext2fs_journal_sb_start(fs->blocksize) + 1);
}

*ret_jsb = (char *) jsb;
@@ -430,6 +427,13 @@ int ext2fs_default_journal_size(__u64 num_blocks)
return 32768;
}

+int ext2fs_journal_sb_start(int blocksize)
+{
+ if (blocksize == EXT2_MIN_BLOCK_SIZE)
+ return 2;
+ return 1;
+}
+
/*
* This function adds a journal device to a filesystem
*/
@@ -437,7 +441,7 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
{
struct stat st;
errcode_t retval;
- char buf[1024];
+ char buf[EXT2_SUPERBLOCK_SIZE];
journal_superblock_t *jsb;
int start;
__u32 i, nr_users;
@@ -450,10 +454,9 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */

/* Get the journal superblock */
- start = 1;
- if (journal_dev->blocksize == 1024)
- start++;
- if ((retval = io_channel_read_blk64(journal_dev->io, start, -1024,
+ start = ext2fs_journal_sb_start(journal_dev->blocksize);
+ if ((retval = io_channel_read_blk64(journal_dev->io, start,
+ -EXT2_SUPERBLOCK_SIZE,
buf)))
return retval;

@@ -479,7 +482,8 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
}

/* Writeback the journal superblock */
- if ((retval = io_channel_write_blk64(journal_dev->io, start, -1024, buf)))
+ if ((retval = io_channel_write_blk64(journal_dev->io, start,
+ -EXT2_SUPERBLOCK_SIZE, buf)))
return retval;

fs->super->s_journal_inum = 0;
@@ -632,7 +636,7 @@ main(int argc, char **argv)
exit(1);
}

- retval = ext2fs_add_journal_inode(fs, 1024, 0);
+ retval = ext2fs_add_journal_inode(fs, JFS_MIN_JOURNAL_BLOCKS, 0);
if (retval) {
com_err(argv[0], retval, "while adding journal to %s",
device_name);
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index d95cc3d..9d21623 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -187,7 +187,7 @@ static int remove_journal_device(ext2_filsys fs)
{
char *journal_path;
ext2_filsys jfs;
- char buf[1024];
+ char buf[EXT2_SUPERBLOCK_SIZE];
journal_superblock_t *jsb;
int i, nr_users;
errcode_t retval;
@@ -230,7 +230,7 @@ static int remove_journal_device(ext2_filsys fs)
}

/* Get the journal superblock */
- if ((retval = io_channel_read_blk64(jfs->io, 1, -1024, buf))) {
+ if ((retval = io_channel_read_blk64(jfs->io, 1, -EXT2_SUPERBLOCK_SIZE, buf))) {
com_err(program_name, retval, "%s",
_("while reading journal superblock"));
goto no_valid_journal;
@@ -261,7 +261,7 @@ static int remove_journal_device(ext2_filsys fs)
jsb->s_nr_users = htonl(nr_users);

/* Write back the journal superblock */
- if ((retval = io_channel_write_blk64(jfs->io, 1, -1024, buf))) {
+ if ((retval = io_channel_write_blk64(jfs->io, 1, -EXT2_SUPERBLOCK_SIZE, buf))) {
com_err(program_name, retval,
"while writing journal superblock.");
goto no_valid_journal;
--
2.0.0


2014-07-10 14:35:34

by Azat Khuzhin

[permalink] [raw]
Subject: [PATCH 5/5] tune2fs: update journal users while updating fs UUID (with external journal)

When we have fs with external journal device, and updating it's UUID, we
should update UUID in users list for that external journal device.

Before:
$ tune2fs -U clear /tmp/dev
tune2fs 1.42.10 (18-May-2014)
$ dumpe2fs /tmp/dev | fgrep UUID
dumpe2fs 1.42.10 (18-May-2014)
Filesystem UUID: <none>
Journal UUID: da1f2ed0-60f6-aaaa-92fd-738701418523
$ dumpe2fs /tmp/journal | fgrep users -A10
dumpe2fs 1.42.10 (18-May-2014)
Journal number of users: 2
Journal users: 0707762d-638e-4bc6-944e-ae8ee7a3359e
0ad849df-1041-4f0a-b1c1-2f949d6a1e37

After:
$ sudo tune2fs -U clear /tmp/dev
tune2fs 1.43-WIP (18-May-2014)
$ dumpe2fs /tmp/dev | fgrep UUID
dumpe2fs 1.42.10 (18-May-2014)
Filesystem UUID: <none>
Journal UUID: da1f2ed0-60f6-aaaa-92fd-738701418523
$ dumpe2fs /tmp/journal | fgrep users -A10
dumpe2fs 1.42.10 (18-May-2014)
Journal number of users: 2
Journal users: 0707762d-638e-4bc6-944e-ae8ee7a3359e
00000000-0000-0000-0000-000000000000

Also add some consts to avoid *magic numbers*:
- UUID_STR_SIZE
- UUID_SIZE
- JFS_USERS_MAX
- JFS_USERS_SIZE

Proposed-by: Andreas Dilger <[email protected]>
Signed-off-by: Azat Khuzhin <[email protected]>
---
lib/ext2fs/ext2fs.h | 2 ++
lib/ext2fs/kernel-jbd.h | 6 +++-
misc/tune2fs.c | 90 +++++++++++++++++++++++++++++++++++++++++++++----
misc/uuidd.c | 3 +-
4 files changed, 93 insertions(+), 8 deletions(-)

diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 1a96f24..f9e12c8 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -45,6 +45,8 @@ extern "C" {
#define SUPERBLOCK_OFFSET EXT2_SUPERBLOCK_OFFSET
#define SUPERBLOCK_SIZE EXT2_SUPERBLOCK_SIZE

+#define UUID_STR_SIZE 37
+
/*
* The last ext2fs revision level that this version of the library is
* able to support.
diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h
index 130c3a2..a9cdc30 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -186,6 +186,9 @@ struct journal_revoke_tail {
#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */


+#define UUID_SIZE 16
+#define JFS_USERS_MAX 48
+#define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX)
/*
* The journal superblock. All fields are in big-endian byte order.
*/
@@ -233,7 +236,8 @@ typedef struct journal_superblock_s
__u32 s_checksum; /* crc32c(superblock) */

/* 0x0100 */
- __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
+ __u8 s_users[JFS_USERS_SIZE]; /* ids of all fs'es sharing the log */
+
/* 0x0400 */
} journal_superblock_t;

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index d1fa6ba..9f5b96c 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -212,6 +212,18 @@ static int get_journal_sb(ext2_filsys jfs, char buf[EXT2_SUPERBLOCK_SIZE])
return 0;
}

+static void *
+journal_user(char uuid[UUID_SIZE], char s_users[JFS_USERS_SIZE], int nr_users)
+{
+ int i;
+ for (i = 0; i < nr_users; i++) {
+ if (memcmp(uuid, &s_users[i * UUID_SIZE], UUID_SIZE) == 0)
+ return &s_users[i * UUID_SIZE];
+ }
+
+ return NULL;
+}
+
/*
* Remove an external journal from the filesystem
*/
@@ -266,11 +278,8 @@ static int remove_journal_device(ext2_filsys fs)
jsb = (journal_superblock_t *) buf;
/* Find the filesystem UUID */
nr_users = ntohl(jsb->s_nr_users);
- for (i = 0; i < nr_users; i++) {
- if (memcmp(fs->super->s_uuid, &jsb->s_users[i * 16], 16) == 0)
- break;
- }
- if (i >= nr_users) {
+
+ if (!journal_user(fs->super->s_uuid, jsb->s_users, nr_users)) {
fputs(_("Filesystem's UUID not found on journal device.\n"),
stderr);
commit_remove_journal = 1;
@@ -2426,6 +2435,68 @@ static int tune2fs_setup_tdb(const char *name, io_manager *io_ptr)
return retval;
}

+int
+fs_update_journal_user(struct ext2_super_block *sb, char old_uuid[UUID_SIZE])
+{
+ int retval, nr_users, start;
+ journal_superblock_t *jsb;
+ ext2_filsys jfs;
+ char *j_uuid, *journal_path;
+ char uuid[UUID_STR_SIZE];
+ char buf[EXT2_SUPERBLOCK_SIZE];
+
+ if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) ||
+ uuid_is_null(sb->s_journal_uuid))
+ return 0;
+
+ uuid_unparse(sb->s_journal_uuid, uuid);
+ journal_path = blkid_get_devname(NULL, "UUID", uuid);
+ if (!journal_path)
+ return 0;
+
+ retval = ext2fs_open2(journal_path, io_options,
+ EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_RW,
+ 0, 0, unix_io_manager, &jfs);
+ if (retval) {
+ com_err(program_name, retval,
+ _("while trying to open %s"),
+ journal_path);
+ return retval;
+ }
+
+ if ((retval = get_journal_sb(jfs, buf))) {
+ if (retval == EXT2_ET_UNSUPP_FEATURE)
+ fprintf(stderr, _("%s is not a journal device.\n"),
+ journal_path);
+ return retval;
+ }
+
+ jsb = (journal_superblock_t *) buf;
+ /* Find the filesystem UUID */
+ nr_users = ntohl(jsb->s_nr_users);
+
+ if (!(j_uuid = journal_user(old_uuid, jsb->s_users, nr_users))) {
+ fputs(_("Filesystem's UUID not found on journal device.\n"),
+ stderr);
+ return EXT2_ET_LOAD_EXT_JOURNAL;
+ }
+
+ memcpy(j_uuid, sb->s_uuid, UUID_SIZE);
+
+ start = ext2fs_journal_sb_start(jfs->blocksize);
+ /* Write back the journal superblock */
+ if ((retval = io_channel_write_blk64(jfs->io, start,
+ -EXT2_SUPERBLOCK_SIZE, buf))) {
+ com_err(program_name, retval,
+ "while writing journal superblock.");
+ return retval;
+ }
+
+ ext2fs_close(jfs);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
errcode_t retval;
@@ -2714,6 +2785,7 @@ retry_open:
int set_csum = 0;
dgrp_t i;
char buf[EXT2_SUPERBLOCK_SIZE];
+ char old_uuid[UUID_SIZE];

if (ext2fs_has_group_desc_csum(fs)) {
/*
@@ -2740,6 +2812,8 @@ retry_open:
if (i >= fs->group_desc_count)
set_csum = 1;
}
+
+ memcpy(old_uuid, sb->s_uuid, UUID_SIZE);
if ((strcasecmp(new_UUID, "null") == 0) ||
(strcasecmp(new_UUID, "clear") == 0)) {
uuid_clear(sb->s_uuid);
@@ -2775,9 +2849,13 @@ retry_open:
goto closefs;
} else if (rc != EXT2_ET_UNSUPP_FEATURE)
goto closefs;
- else
+ else {
rc = 0; /** Reset rc to avoid ext2fs_mmp_stop() */

+ if ((rc = fs_update_journal_user(sb, old_uuid)))
+ goto closefs;
+ }
+
ext2fs_mark_super_dirty(fs);
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
diff --git a/misc/uuidd.c b/misc/uuidd.c
index 5a53138..02ca6be 100644
--- a/misc/uuidd.c
+++ b/misc/uuidd.c
@@ -36,6 +36,7 @@ extern int optind;
#include "uuid/uuid.h"
#include "uuid/uuidd.h"
#include "nls-enable.h"
+#include "ext2fs/ext2fs.h"

#ifdef __GNUC__
#define CODE_ATTR(x) __attribute__(x)
@@ -236,7 +237,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
uuid_t uu;
mode_t save_umask;
char reply_buf[1024], *cp;
- char op, str[37];
+ char op, str[UUID_STR_SIZE];
int i, s, ns, len, num;
int fd_pidfile, ret;

--
2.0.0


2014-07-26 07:33:33

by Azat Khuzhin

[permalink] [raw]
Subject: Re: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

On Thu, Jul 10, 2014 at 06:35:03PM +0400, Azat Khuzhin wrote:
> [PATCH 1/5] lib: add EXT2_ prefix for SUPERBLOCK_{OFFSET,SIZE}
> [PATCH 2/5] journal: use consts instead of 1024 and add helper for
> [PATCH 3/5] tune2fs: remove_journal_device(): use the correct block
> [PATCH 4/5] tune2fs: update journal super block when changing UUID
> [PATCH 5/5] tune2fs: update journal users while updating fs UUID

Hi Ted, any news on this?

Cheers,
Azat.

2014-07-26 14:31:07

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

On Sat, Jul 26, 2014 at 11:33:29AM +0400, Azat Khuzhin wrote:
> On Thu, Jul 10, 2014 at 06:35:03PM +0400, Azat Khuzhin wrote:
> > [PATCH 1/5] lib: add EXT2_ prefix for SUPERBLOCK_{OFFSET,SIZE}
> > [PATCH 2/5] journal: use consts instead of 1024 and add helper for
> > [PATCH 3/5] tune2fs: remove_journal_device(): use the correct block
> > [PATCH 4/5] tune2fs: update journal super block when changing UUID
> > [PATCH 5/5] tune2fs: update journal users while updating fs UUID
>
> Hi Ted, any news on this?

What branch was this against? The first patch scared me, since making
global changes to rename a constant is very likely to cause all sorts
of patch conflicts, especially when I have to juggle patches across
the maint and next branches. So that's why I put it off.

I know there are some real bug fixes here, and it's helpful it those
come *first*, and make the minimal changes necessary, so I can apply
it to the maint branch and not have to worry about potential merge
conflicts.

In general, for global renames/cleanups, especially ones that don't
actually fix any bugs, and which are there mostly for aesthetic
reasons, I'd much prefer to hold off making them until after 1.43.0 is
released, and after I've a abandoned making any further releases
(except for truely catastrophic bugs) on the 1.42.x branch.

Cheers,

- Ted


2014-07-28 08:06:23

by Azat Khuzhin

[permalink] [raw]
Subject: Re: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

On 26 Jul 2014 18:31, "Theodore Ts'o" <tytso <[email protected]>@
<[email protected]>mit.edu <[email protected]>> wrote:
>
> On Sat, Jul 26, 2014 at 11:33:29AM +0400, Azat Khuzhin wrote:
> > On Thu, Jul 10, 2014 at 06:35:03PM +0400, Azat Khuzhin wrote:
> > > [PATCH 1/5] lib: add EXT2_ prefix for SUPERBLOCK_{OFFSET,SIZE}
> > > [PATCH 2/5] journal: use consts instead of 1024 and add helper for
> > > [PATCH 3/5] tune2fs: remove_journal_device(): use the correct block
> > > [PATCH 4/5] tune2fs: update journal super block when changing UUID
> > > [PATCH 5/5] tune2fs: update journal users while updating fs UUID
> >
> > Hi Ted, any news on this?
>
> What branch was this against? The first patch scared me, since making
> global changes to rename a constant is very likely to cause all sorts
> of patch conflicts, especially when I have to juggle patches across
> the maint and next branches. So that's why I put it off.

AFAIR it was against master.
Yeah massive rename will do a lot of conflicts, I've just rebased them
against maint without first patch and sent new patchset (v3).

>
> I know there are some real bug fixes here, and it's helpful it those
> come *first*, and make the minimal changes necessary, so I can apply
> it to the maint branch and not have to worry about potential merge
> conflicts.

There is one patch that I decide to leave, while it's not bugfix -
"journal: use consts instead of 1024 and add helper for journal with 1k
blocksize" because it will add one helper that is really useful instead
of hardcoding it in place in next patches.

>
> In general, for global renames/cleanups, especially ones that don't
> actually fix any bugs, and which are there mostly for aesthetic
> reasons, I'd much prefer to hold off making them until after 1.43.0 is
> released, and after I've a abandoned making any further releases
> (except for truely catastrophic bugs) on the 1.42.x branch.
>

Got it.

Thanks.
Azat.

2014-07-28 13:00:25

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

On Mon, Jul 28, 2014 at 12:06:19PM +0400, Azat Khuzhin wrote:
>
> AFAIR it was against master.
> Yeah massive rename will do a lot of conflicts, I've just rebased them
> against maint without first patch and sent new patchset (v3).

Great, thanks!

For future information, if you are doing development, it's better to
use either the maint branch (for bug fixes) or the next branch. The
next branch is non-rewinding, so it's safe to do development against
it, and it's generally a few days ahead of the master branch,
especially after I've added a large number of patches.

he basic idea is that if there are some end users which are using
e2fsprogs' master branch, while any patches that get merged into
"next" should be clean and safe and Bug Free(tm), that we give those
patches a few days for people to find bugs and really obvious/stupid
flaws that either (a) I made or that (b) I missed in my review before
those new commits "graduate" to master.

Cheers,

- Ted

2014-07-28 13:53:10

by Azat Khuzhin

[permalink] [raw]
Subject: Re: [PATCH 0/5] e2fsprogs: some small cleanups and fixes for journal code

On Mon, Jul 28, 2014 at 09:00:22AM -0400, Theodore Ts'o wrote:
> On Mon, Jul 28, 2014 at 12:06:19PM +0400, Azat Khuzhin wrote:
> >
> > AFAIR it was against master.
> > Yeah massive rename will do a lot of conflicts, I've just rebased them
> > against maint without first patch and sent new patchset (v3).
>
> Great, thanks!
>
> For future information, if you are doing development, it's better to
> use either the maint branch (for bug fixes) or the next branch. The
> next branch is non-rewinding, so it's safe to do development against
> it, and it's generally a few days ahead of the master branch,
> especially after I've added a large number of patches.
>
> he basic idea is that if there are some end users which are using
> e2fsprogs' master branch, while any patches that get merged into
> "next" should be clean and safe and Bug Free(tm), that we give those
> patches a few days for people to find bugs and really obvious/stupid
> flaws that either (a) I made or that (b) I missed in my review before
> those new commits "graduate" to master.

Yeah, thanks for explanation Ted, I read about this, but I forgot to
change branch before writing patches.

Thanks,
Azat.