diff options
Diffstat (limited to 'lib/ext2fs/mkjournal.c')
-rw-r--r-- | lib/ext2fs/mkjournal.c | 112 |
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); |