Whamcloud - gitweb
Merge branch 'maint' into next
authorTheodore Ts'o <tytso@mit.edu>
Tue, 29 Jul 2014 14:53:49 +0000 (10:53 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 29 Jul 2014 14:53:49 +0000 (10:53 -0400)
e2fsck/journal.c
lib/ext2fs/ext2fs.h
lib/ext2fs/kernel-jbd.h
lib/ext2fs/mkjournal.c
misc/tune2fs.c
misc/uuidd.c

index a971df1..206685a 100644 (file)
@@ -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 + SUPERBLOCK_OFFSET,
                       sizeof(jsuper));
                brelse(bh);
 #ifdef WORDS_BIGENDIAN
index 8caba78..7812956 100644 (file)
@@ -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.
@@ -1501,6 +1503,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,
index 130c3a2..a9cdc30 100644 (file)
@@ -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;
 
index e8316a7..96b6d36 100644 (file)
@@ -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;
@@ -428,6 +425,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
  */
@@ -435,7 +439,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[SUPERBLOCK_SIZE];
        journal_superblock_t    *jsb;
        int             start;
        __u32           i, nr_users;
@@ -448,10 +452,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,
+                                           -SUPERBLOCK_SIZE,
                                            buf)))
                return retval;
 
@@ -477,7 +480,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,
+                                           -SUPERBLOCK_SIZE, buf)))
                return retval;
 
        fs->super->s_journal_inum = 0;
@@ -630,7 +634,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);
index 601a6c8..5aaea5e 100644 (file)
@@ -180,6 +180,50 @@ 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[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), -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;
+}
+
+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
  */
@@ -187,12 +231,13 @@ static int remove_journal_device(ext2_filsys fs)
 {
        char            *journal_path;
        ext2_filsys     jfs;
-       char            buf[1024];
+       char            buf[SUPERBLOCK_SIZE];
        journal_superblock_t    *jsb;
        int             i, nr_users;
        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 */
@@ -222,34 +267,19 @@ 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;
-       }
 
-       /* Get the journal superblock */
-       if ((retval = io_channel_read_blk64(jfs->io, 1, -1024, 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++) {
-               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;
@@ -261,7 +291,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, -1024, buf))) {
+       if ((retval = io_channel_write_blk64(jfs->io, start,
+           -SUPERBLOCK_SIZE, buf))) {
                com_err(program_name, retval,
                        "while writing journal superblock.");
                goto no_valid_journal;
@@ -2404,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[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;
@@ -2691,6 +2784,8 @@ retry_open:
        if (U_flag) {
                int set_csum = 0;
                dgrp_t i;
+               char buf[SUPERBLOCK_SIZE];
+               char old_uuid[UUID_SIZE];
 
                if (ext2fs_has_group_desc_csum(fs)) {
                        /*
@@ -2717,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);
@@ -2736,6 +2833,29 @@ 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),
+                                       -SUPERBLOCK_SIZE, buf)))
+                               goto closefs;
+               } else if (rc != EXT2_ET_UNSUPP_FEATURE)
+                       goto closefs;
+               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))
index 5a53138..02ca6be 100644 (file)
@@ -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;