tune2fs, mke2fs: add the ability to control the location of the journal

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index 67ddbf8..ae74bce 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -409,6 +409,13 @@
 (i.e., 1MB if using 1k blocks, 4MB if using 4k blocks, etc.)
 and may be no more than 10,240,000 filesystem blocks or half the total
 file system size (whichever is smaller)
+.TP
+.BI location =journal-location
+Specify the location of the journal.  The argument
+.I journal-location
+can either be specified as a block number, or if the number has a units
+suffix (e.g., 'M', 'G', etc.) interpret it as the offset from the
+beginning of the file system.
 @JDEV@.TP
 @JDEV@.BI device= external-journal
 @JDEV@Attach the filesystem to the journal block device located on
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index acc603d..dd77a00 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -97,6 +97,7 @@
 static __u32	fs_stride;
 static int	quotatype = -1;  /* Initialize both user and group quotas by default */
 static __u64	offset;
+static blk64_t journal_location = ~0LL;
 
 static struct ext2_super_block fs_param;
 static char *fs_uuid = NULL;
@@ -2010,6 +2011,15 @@
 					       EXT2_MKJOURNAL_LAZYINIT : 0;
 	journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
 
+	if (!journal_location_string)
+		journal_location_string = get_string_from_profile(fs_types,
+						"journal_location", "");
+	if ((journal_location == ~0ULL) && journal_location_string &&
+	    *journal_location_string)
+		journal_location = parse_num_blocks2(journal_location_string,
+						fs_param.s_log_block_size);
+	free(journal_location_string);
+
 	/* Get options from profile */
 	for (cpp = fs_types; *cpp; cpp++) {
 		tmp = NULL;
@@ -2724,8 +2734,9 @@
 			       journal_blocks);
 			fflush(stdout);
 		}
-		retval = ext2fs_add_journal_inode(fs, journal_blocks,
-						  journal_flags);
+		retval = ext2fs_add_journal_inode2(fs, journal_blocks,
+						   journal_location,
+						   journal_flags);
 		if (retval) {
 			com_err(program_name, retval, "%s",
 				_("\n\twhile trying to create journal"));
diff --git a/misc/mke2fs.conf.5.in b/misc/mke2fs.conf.5.in
index 0625d0e..758cdf4 100644
--- a/misc/mke2fs.conf.5.in
+++ b/misc/mke2fs.conf.5.in
@@ -357,6 +357,9 @@
 initializing the filesystem in the background when the filesystem is
 first mounted.
 .TP
+.I journal_location
+This relation specifies the location of the journal.
+.TP
 .I inode_ratio
 This relation specifies the default inode ratio if the user does not
 specify one on the command line.
diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in
index da21080..9455707 100644
--- a/misc/tune2fs.8.in
+++ b/misc/tune2fs.8.in
@@ -333,6 +333,13 @@
 and may be no more than 102,400 filesystem blocks.
 There must be enough free space in the filesystem to create a journal of
 that size.
+.TP
+.BI location =journal-location
+Specify the location of the journal.  The argument
+.I journal-location
+can either be specified as a block number, or if the number has a units
+suffix (e.g., 'M', 'G', etc.) interpret it as the offset from the
+beginning of the file system.
 @JDEV@.TP
 @JDEV@.BI device= external-journal
 @JDEV@Attach the filesystem to the journal block device located on
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index b8cd347..64a76f1 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -98,6 +98,7 @@
 
 int journal_size, journal_flags;
 char *journal_device;
+static blk64_t journal_location = ~0LL;
 
 static struct list_head blk_move_list;
 
@@ -694,8 +695,13 @@
 		fflush(stdout);
 		journal_blocks = figure_journal_size(journal_size, fs);
 
-		retval = ext2fs_add_journal_inode(fs, journal_blocks,
-						  journal_flags);
+		if (journal_location_string)
+			journal_location =
+				parse_num_blocks2(journal_location_string,
+						  fs->super->s_log_block_size);
+		retval = ext2fs_add_journal_inode2(fs, journal_blocks,
+						   journal_location,
+						   journal_flags);
 		if (retval) {
 			fprintf(stderr, "\n");
 			com_err(program_name, retval, "%s",
diff --git a/misc/util.c b/misc/util.c
index 40c8858..92ab79f 100644
--- a/misc/util.c
+++ b/misc/util.c
@@ -34,6 +34,8 @@
 #include "blkid/blkid.h"
 #include "util.h"
 
+char *journal_location_string = NULL;
+
 #ifndef HAVE_STRCASECMP
 int strcasecmp (char *s1, char *s2)
 {
@@ -218,6 +220,12 @@
 			journal_size = strtoul(arg, &p, 0);
 			if (*p)
 				journal_usage++;
+		} else if (!strcmp(token, "location")) {
+			if (!arg) {
+				journal_usage++;
+				continue;
+			}
+			journal_location_string = strdup(arg);
 		} else if (strcmp(token, "v1_superblock") == 0) {
 			journal_flags |= EXT2_MKJOURNAL_V1_SUPER;
 			continue;
@@ -231,7 +239,8 @@
 			"\tis set off by an equals ('=') sign.\n\n"
 			"Valid journal options are:\n"
 			"\tsize=<journal size in megabytes>\n"
-			"\tdevice=<journal device>\n\n"
+			"\tdevice=<journal device>\n"
+			"\tlocation=<journal location>\n\n"
 			"The journal size must be between "
 			"1024 and 10240000 filesystem blocks.\n\n"), stderr);
 		free(buf);
diff --git a/misc/util.h b/misc/util.h
index f872c38..11604d0 100644
--- a/misc/util.h
+++ b/misc/util.h
@@ -13,6 +13,7 @@
 extern int	 journal_size;
 extern int	 journal_flags;
 extern char	*journal_device;
+extern char	*journal_location_string;
 
 #ifndef HAVE_STRCASECMP
 extern int strcasecmp (char *s1, char *s2);