summaryrefslogtreecommitdiff
path: root/lib/ext2fs/mkjournal.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext2fs/mkjournal.c')
-rw-r--r--lib/ext2fs/mkjournal.c112
1 files changed, 66 insertions, 46 deletions
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 838d751c..884d9c07 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -250,6 +250,7 @@ static int mkjournal_proc(ext2_filsys fs,
es->err = retval;
return BLOCK_ABORT;
}
+ ext2fs_block_alloc_stats2(fs, new_blk, +1);
es->newblocks++;
}
if (blockcnt >= 0)
@@ -285,7 +286,6 @@ static int mkjournal_proc(ext2_filsys fs,
return BLOCK_ABORT;
}
*blocknr = es->goal = new_blk;
- ext2fs_block_alloc_stats2(fs, new_blk, +1);
if (es->num_blocks == 0)
return (BLOCK_CHANGED | BLOCK_ABORT);
@@ -295,13 +295,43 @@ static int mkjournal_proc(ext2_filsys fs,
}
/*
+ * Calculate the initial goal block to be roughly at the middle of the
+ * filesystem. Pick a group that has the largest number of free
+ * blocks.
+ */
+static blk64_t get_midpoint_journal_block(ext2_filsys fs)
+{
+ dgrp_t group, start, end, i, log_flex;
+
+ group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
+ fs->super->s_first_data_block) / 2);
+ log_flex = 1 << fs->super->s_log_groups_per_flex;
+ if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
+ group = group & ~(log_flex - 1);
+ while ((group < fs->group_desc_count) &&
+ ext2fs_bg_free_blocks_count(fs, group) == 0)
+ group++;
+ if (group == fs->group_desc_count)
+ group = 0;
+ start = group;
+ } else
+ start = (group > 0) ? group-1 : group;
+ end = ((group+1) < fs->group_desc_count) ? group+1 : group;
+ group = start;
+ for (i = start + 1; i <= end; i++)
+ if (ext2fs_bg_free_blocks_count(fs, i) >
+ ext2fs_bg_free_blocks_count(fs, group))
+ group = i;
+ return ext2fs_group_first_block2(fs, group);
+}
+
+/*
* This function creates a journal using direct I/O routines.
*/
static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
- blk_t num_blocks, int flags)
+ blk_t num_blocks, blk64_t goal, int flags)
{
char *buf;
- dgrp_t group, start, end, i, log_flex;
errcode_t retval;
struct ext2_inode inode;
unsigned long long inode_size;
@@ -312,13 +342,15 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
return retval;
if ((retval = ext2fs_read_bitmaps(fs)))
- return retval;
+ goto out2;
if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
- return retval;
+ goto out2;
- if (inode.i_blocks > 0)
- return EEXIST;
+ if (inode.i_blocks > 0) {
+ retval = EEXIST;
+ goto out2;
+ }
es.num_blocks = num_blocks;
es.newblocks = 0;
@@ -326,41 +358,14 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
es.err = 0;
es.flags = flags;
es.zero_count = 0;
+ es.goal = (goal != ~0ULL) ? goal : get_midpoint_journal_block(fs);
if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
inode.i_flags |= EXT4_EXTENTS_FL;
if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
- return retval;
+ goto out2;
}
- /*
- * Set the initial goal block to be roughly at the middle of
- * the filesystem. Pick a group that has the largest number
- * of free blocks.
- */
- group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
- fs->super->s_first_data_block) / 2);
- log_flex = 1 << fs->super->s_log_groups_per_flex;
- if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
- group = group & ~(log_flex - 1);
- while ((group < fs->group_desc_count) &&
- ext2fs_bg_free_blocks_count(fs, group) == 0)
- group++;
- if (group == fs->group_desc_count)
- group = 0;
- start = group;
- } else
- start = (group > 0) ? group-1 : group;
- end = ((group+1) < fs->group_desc_count) ? group+1 : group;
- group = start;
- for (i=start+1; i <= end; i++)
- if (ext2fs_bg_free_blocks_count(fs, i) >
- ext2fs_bg_free_blocks_count(fs, group))
- group = i;
-
- es.goal = (fs->super->s_blocks_per_group * group) +
- fs->super->s_first_data_block;
-
retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND,
0, mkjournal_proc, &es);
if (es.err) {
@@ -380,7 +385,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
inode_size = (unsigned long long)fs->blocksize * num_blocks;
inode.i_size = inode_size & 0xFFFFFFFF;
inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
- if (inode.i_size_high)
+ if (ext2fs_needs_large_file_feature(inode_size))
fs->super->s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
@@ -400,6 +405,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
errout:
ext2fs_zero_blocks2(0, 0, 0, 0, 0);
+out2:
ext2fs_free_mem(&buf);
return retval;
}
@@ -490,20 +496,27 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
* POSIX routines if the filesystem is mounted, or using direct I/O
* functions if it is not.
*/
-errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
+errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
+ blk64_t goal, int flags)
{
errcode_t retval;
ext2_ino_t journal_ino;
struct stat st;
char jfile[1024];
- int mount_flags, f;
+ int mount_flags;
int fd = -1;
- if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
- jfile, sizeof(jfile)-10)))
+ if (flags & EXT2_MKJOURNAL_NO_MNT_CHECK)
+ mount_flags = 0;
+ else if ((retval = ext2fs_check_mount_point(fs->device_name,
+ &mount_flags,
+ jfile, sizeof(jfile)-10)))
return retval;
if (mount_flags & EXT2_MF_MOUNTED) {
+#if HAVE_EXT2_IOCTLS
+ int f = 0;
+#endif
strcat(jfile, "/.journal");
/*
@@ -516,9 +529,10 @@ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
#if HAVE_EXT2_IOCTLS
fd = open(jfile, O_RDONLY);
if (fd >= 0) {
- f = 0;
- ioctl(fd, EXT2_IOC_SETFLAGS, &f);
+ retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
close(fd);
+ if (retval)
+ return retval;
}
#endif
#endif
@@ -574,7 +588,7 @@ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
}
journal_ino = EXT2_JOURNAL_INO;
if ((retval = write_journal_inode(fs, journal_ino,
- num_blocks, flags)))
+ num_blocks, goal, flags)))
return retval;
}
@@ -587,11 +601,17 @@ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
ext2fs_mark_super_dirty(fs);
return 0;
errout:
- if (fd > 0)
+ if (fd >= 0)
close(fd);
return retval;
}
+errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
+{
+ return ext2fs_add_journal_inode2(fs, num_blocks, ~0ULL, flags);
+}
+
+
#ifdef DEBUG
main(int argc, char **argv)
{
@@ -612,7 +632,7 @@ main(int argc, char **argv)
exit(1);
}
- retval = ext2fs_add_journal_inode(fs, 1024);
+ retval = ext2fs_add_journal_inode(fs, 1024, 0);
if (retval) {
com_err(argv[0], retval, "while adding journal to %s",
device_name);