summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzat Khuzhin <a3at.mail@gmail.com>2014-07-28 11:43:25 +0400
committerTheodore Ts'o <tytso@mit.edu>2014-07-28 20:21:59 -0400
commit9c2c1e9a3d12563c68d6817b609bbfec0af149cb (patch)
tree2fec8f95790d1370f1e747a96da7c6f5d09a0585
parent7dfefaf413bbd4f7f51e2664dc4911873236ffdd (diff)
downloade2fsprogs-9c2c1e9a3d12563c68d6817b609bbfec0af149cb.tar.gz
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 <adilger@dilger.ca> Signed-off-by: Azat Khuzhin <a3at.mail@gmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--lib/ext2fs/ext2fs.h2
-rw-r--r--lib/ext2fs/kernel-jbd.h6
-rw-r--r--misc/tune2fs.c90
-rw-r--r--misc/uuidd.c3
4 files changed, 93 insertions, 8 deletions
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index ab57534d..d3a34d50 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -39,6 +39,8 @@ extern "C" {
#define SUPERBLOCK_OFFSET 1024
#define SUPERBLOCK_SIZE 1024
+#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 059bf8fa..2baae735 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -164,6 +164,9 @@ typedef struct journal_revoke_header_s
#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.
*/
@@ -208,7 +211,8 @@ typedef struct journal_superblock_s
__u32 s_padding[44];
/* 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 74e57ae6..0c1feb1e 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -207,6 +207,18 @@ static int get_journal_sb(ext2_filsys jfs, char buf[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
*/
@@ -261,11 +273,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;
@@ -1915,6 +1924,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[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,
+ -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;
@@ -2203,6 +2274,7 @@ retry_open:
int set_csum = 0;
dgrp_t i;
char buf[SUPERBLOCK_SIZE];
+ char old_uuid[UUID_SIZE];
if (sb->s_feature_ro_compat &
EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
@@ -2230,6 +2302,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);
@@ -2264,9 +2338,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 (I_flag) {
diff --git a/misc/uuidd.c b/misc/uuidd.c
index 5a531380..02ca6be8 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;