mirror of https://github.com/vitalif/e2fsprogs
libext2fs: use fallocate for creating journals and hugefiles
Use the new fallocate API for creating the journal and the mk_hugefile feature. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>debian
parent
5aad5b8e0e
commit
4f868703f6
|
@ -227,89 +227,6 @@ errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for creating the journal using direct I/O routines
|
||||
*/
|
||||
struct mkjournal_struct {
|
||||
int num_blocks;
|
||||
int newblocks;
|
||||
blk64_t goal;
|
||||
blk64_t blk_to_zero;
|
||||
int zero_count;
|
||||
int flags;
|
||||
char *buf;
|
||||
errcode_t err;
|
||||
};
|
||||
|
||||
static int mkjournal_proc(ext2_filsys fs,
|
||||
blk64_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk64_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
|
||||
blk64_t new_blk;
|
||||
errcode_t retval;
|
||||
|
||||
if (*blocknr) {
|
||||
es->goal = *blocknr;
|
||||
return 0;
|
||||
}
|
||||
if (blockcnt &&
|
||||
(EXT2FS_B2C(fs, es->goal) == EXT2FS_B2C(fs, es->goal+1)))
|
||||
new_blk = es->goal+1;
|
||||
else {
|
||||
es->goal &= ~EXT2FS_CLUSTER_MASK(fs);
|
||||
retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
ext2fs_block_alloc_stats2(fs, new_blk, +1);
|
||||
es->newblocks++;
|
||||
}
|
||||
if (blockcnt >= 0)
|
||||
es->num_blocks--;
|
||||
|
||||
retval = 0;
|
||||
if (blockcnt <= 0)
|
||||
retval = io_channel_write_blk64(fs->io, new_blk, 1, es->buf);
|
||||
else if (!(es->flags & EXT2_MKJOURNAL_LAZYINIT)) {
|
||||
if (es->zero_count) {
|
||||
if ((es->blk_to_zero + es->zero_count == new_blk) &&
|
||||
(es->zero_count < 1024))
|
||||
es->zero_count++;
|
||||
else {
|
||||
retval = ext2fs_zero_blocks2(fs,
|
||||
es->blk_to_zero,
|
||||
es->zero_count,
|
||||
0, 0);
|
||||
es->zero_count = 0;
|
||||
}
|
||||
}
|
||||
if (es->zero_count == 0) {
|
||||
es->blk_to_zero = new_blk;
|
||||
es->zero_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockcnt == 0)
|
||||
memset(es->buf, 0, fs->blocksize);
|
||||
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
*blocknr = es->goal = new_blk;
|
||||
|
||||
if (es->num_blocks == 0)
|
||||
return (BLOCK_CHANGED | BLOCK_ABORT);
|
||||
else
|
||||
return BLOCK_CHANGED;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the initial goal block to be roughly at the middle of the
|
||||
* filesystem. Pick a group that has the largest number of free
|
||||
|
@ -351,7 +268,8 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
|
|||
errcode_t retval;
|
||||
struct ext2_inode inode;
|
||||
unsigned long long inode_size;
|
||||
struct mkjournal_struct es;
|
||||
int falloc_flags = EXT2_FALLOCATE_FORCE_INIT;
|
||||
blk64_t zblk;
|
||||
|
||||
if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags,
|
||||
&buf)))
|
||||
|
@ -368,40 +286,16 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
|
|||
goto out2;
|
||||
}
|
||||
|
||||
es.num_blocks = num_blocks;
|
||||
es.newblocks = 0;
|
||||
es.buf = buf;
|
||||
es.err = 0;
|
||||
es.flags = flags;
|
||||
es.zero_count = 0;
|
||||
es.goal = (goal != ~0ULL) ? goal : get_midpoint_journal_block(fs);
|
||||
if (goal == ~0ULL)
|
||||
goal = get_midpoint_journal_block(fs);
|
||||
|
||||
if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
|
||||
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)))
|
||||
goto out2;
|
||||
}
|
||||
|
||||
retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND,
|
||||
0, mkjournal_proc, &es);
|
||||
if (retval)
|
||||
goto out2;
|
||||
if (es.err) {
|
||||
retval = es.err;
|
||||
goto out2;
|
||||
}
|
||||
if (es.zero_count) {
|
||||
retval = ext2fs_zero_blocks2(fs, es.blk_to_zero,
|
||||
es.zero_count, 0, 0);
|
||||
if (retval)
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
|
||||
goto out2;
|
||||
if (!(flags & EXT2_MKJOURNAL_LAZYINIT))
|
||||
falloc_flags |= EXT2_FALLOCATE_ZERO_BLOCKS;
|
||||
|
||||
inode_size = (unsigned long long)fs->blocksize * num_blocks;
|
||||
ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
|
||||
inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0);
|
||||
inode.i_links_count = 1;
|
||||
inode.i_mode = LINUX_S_IFREG | 0600;
|
||||
|
@ -409,9 +303,21 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
|
|||
if (retval)
|
||||
goto out2;
|
||||
|
||||
retval = ext2fs_fallocate(fs, falloc_flags, journal_ino,
|
||||
&inode, goal, 0, num_blocks);
|
||||
if (retval)
|
||||
goto out2;
|
||||
|
||||
if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode)))
|
||||
goto out2;
|
||||
retval = 0;
|
||||
|
||||
retval = ext2fs_bmap2(fs, journal_ino, &inode, NULL, 0, 0, NULL, &zblk);
|
||||
if (retval)
|
||||
goto out2;
|
||||
|
||||
retval = io_channel_write_blk64(fs->io, zblk, 1, buf);
|
||||
if (retval)
|
||||
goto out2;
|
||||
|
||||
memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
|
||||
fs->super->s_jnl_blocks[15] = inode.i_size_high;
|
||||
|
|
|
@ -258,12 +258,7 @@ static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
|
|||
|
||||
{
|
||||
errcode_t retval;
|
||||
blk64_t lblk, bend = 0;
|
||||
__u64 size;
|
||||
blk64_t left;
|
||||
blk64_t count = 0;
|
||||
struct ext2_inode inode;
|
||||
ext2_extent_handle_t handle;
|
||||
|
||||
retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino);
|
||||
if (retval)
|
||||
|
@ -283,85 +278,20 @@ static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
|
|||
|
||||
ext2fs_inode_alloc_stats2(fs, *ino, +1, 0);
|
||||
|
||||
retval = ext2fs_extent_open2(fs, *ino, &inode, &handle);
|
||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
|
||||
EXT3_FEATURE_INCOMPAT_EXTENTS))
|
||||
inode.i_flags |= EXT4_EXTENTS_FL;
|
||||
retval = ext2fs_fallocate(fs,
|
||||
EXT2_FALLOCATE_FORCE_INIT |
|
||||
EXT2_FALLOCATE_ZERO_BLOCKS,
|
||||
*ino, &inode, goal, 0, num);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = ext2fs_inode_size_set(fs, &inode, num * fs->blocksize);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
lblk = 0;
|
||||
left = num ? num : 1;
|
||||
while (left) {
|
||||
blk64_t pblk, end;
|
||||
blk64_t n = left;
|
||||
|
||||
retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
|
||||
goal, ext2fs_blocks_count(fs->super) - 1, &end);
|
||||
if (retval)
|
||||
goto errout;
|
||||
goal = end;
|
||||
|
||||
retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, goal,
|
||||
ext2fs_blocks_count(fs->super) - 1, &bend);
|
||||
if (retval == ENOENT) {
|
||||
bend = ext2fs_blocks_count(fs->super);
|
||||
if (num == 0)
|
||||
left = 0;
|
||||
}
|
||||
if (!num || bend - goal < left)
|
||||
n = bend - goal;
|
||||
pblk = goal;
|
||||
if (num)
|
||||
left -= n;
|
||||
goal += n;
|
||||
count += n;
|
||||
ext2fs_block_alloc_stats_range(fs, pblk, n, +1);
|
||||
|
||||
if (zero_hugefile) {
|
||||
blk64_t ret_blk;
|
||||
retval = ext2fs_zero_blocks2(fs, pblk, n,
|
||||
&ret_blk, NULL);
|
||||
|
||||
if (retval)
|
||||
com_err(program_name, retval,
|
||||
_("while zeroing block %llu "
|
||||
"for hugefile"), ret_blk);
|
||||
}
|
||||
|
||||
while (n) {
|
||||
blk64_t l = n;
|
||||
struct ext2fs_extent newextent;
|
||||
|
||||
if (l > EXT_INIT_MAX_LEN)
|
||||
l = EXT_INIT_MAX_LEN;
|
||||
|
||||
newextent.e_len = l;
|
||||
newextent.e_pblk = pblk;
|
||||
newextent.e_lblk = lblk;
|
||||
newextent.e_flags = 0;
|
||||
|
||||
retval = ext2fs_extent_insert(handle,
|
||||
EXT2_EXTENT_INSERT_AFTER, &newextent);
|
||||
if (retval)
|
||||
return retval;
|
||||
pblk += l;
|
||||
lblk += l;
|
||||
n -= l;
|
||||
}
|
||||
}
|
||||
|
||||
retval = ext2fs_read_inode(fs, *ino, &inode);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
retval = ext2fs_iblk_add_blocks(fs, &inode,
|
||||
count / EXT2FS_CLUSTER_RATIO(fs));
|
||||
if (retval)
|
||||
goto errout;
|
||||
size = (__u64) count * fs->blocksize;
|
||||
retval = ext2fs_inode_size_set(fs, &inode, size);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
retval = ext2fs_write_new_inode(fs, *ino, &inode);
|
||||
retval = ext2fs_write_inode(fs, *ino, &inode);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
|
@ -379,13 +309,7 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
errout:
|
||||
if (handle)
|
||||
ext2fs_extent_free(handle);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -572,6 +496,8 @@ errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name)
|
|||
printf(_("with %llu blocks each"), num_blocks);
|
||||
fputs(": ", stdout);
|
||||
}
|
||||
if (num_blocks == 0)
|
||||
num_blocks = ext2fs_blocks_count(fs->super) - goal;
|
||||
for (i=0; i < num_files; i++) {
|
||||
ext2_ino_t ino;
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ Change in FS metadata:
|
|||
Reserved GDT blocks at 4-259
|
||||
Block bitmap at 260 (+259)
|
||||
@@ -45,7 +46,7 @@
|
||||
7789 free blocks, 1013 free inodes, 2 directories
|
||||
Free blocks: 404-8192
|
||||
0 free blocks, 1013 free inodes, 2 directories
|
||||
Free blocks:
|
||||
Free inodes: 12-1024
|
||||
-Group 1: (Blocks 8193-16384)
|
||||
+Group 1: (Blocks 8193-16384) [ITABLE_ZEROED]
|
||||
|
@ -58,8 +58,8 @@ Change in FS metadata:
|
|||
Reserved GDT blocks at 8196-8451
|
||||
Block bitmap at 8452 (+259)
|
||||
@@ -54,6 +55,6 @@
|
||||
7803 free blocks, 1024 free inodes, 0 directories
|
||||
Free blocks: 8582-16384
|
||||
0 free blocks, 1024 free inodes, 0 directories
|
||||
Free blocks:
|
||||
Free inodes: 1025-2048
|
||||
-Group 2: (Blocks 16385-24576)
|
||||
+Group 2: (Blocks 16385-24576) [ITABLE_ZEROED]
|
||||
|
|
Loading…
Reference in New Issue