ext2fs_add_journal_inode: Optimize writing the journal data blocks

Add a new function ext2fs_zero_blocks(), and use it so that journal
data blocks is written in larger chunks to speed up the creation of
the journal.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
bitmap-optimize
Theodore Ts'o 2008-04-27 16:10:32 -04:00
parent 5f8a5ae6b8
commit c860850441
2 changed files with 88 additions and 1 deletions

View File

@ -1014,6 +1014,8 @@ extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum
const char *name);
/* mkjournal.c */
extern errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
blk_t *ret_blk, int *ret_count);
extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
__u32 size, int flags,
char **ret_jsb);

View File

@ -134,12 +134,70 @@ errout:
return retval;
}
/*
* Convenience function which zeros out _num_ blocks starting at
* _blk_. In case of an error, the details of the error is returned
* via _ret_blk_ and _ret_count_ if they are non-NULL pointers.
* Returns 0 on success, and an error code on an error.
*
* As a special case, if the first argument is NULL, then it will
* attempt to free the static zeroizing buffer. (This is to keep
* programs that check for memory leaks happy.)
*/
#define STRIDE_LENGTH 8
errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
blk_t *ret_blk, int *ret_count)
{
int j, count;
static char *buf;
errcode_t retval;
/* If fs is null, clean up the static buffer and return */
if (!fs) {
if (buf) {
free(buf);
buf = 0;
}
return 0;
}
/* Allocate the zeroizing buffer if necessary */
if (!buf) {
buf = malloc(fs->blocksize * STRIDE_LENGTH);
if (!buf)
return ENOMEM;
memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
}
/* OK, do the write loop */
j=0;
while (j < num) {
if (blk % STRIDE_LENGTH)
count = STRIDE_LENGTH - (blk % STRIDE_LENGTH);
else {
count = num - j;
if (count > STRIDE_LENGTH)
count = STRIDE_LENGTH;
}
retval = io_channel_write_blk(fs->io, blk, count, buf);
if (retval) {
if (ret_count)
*ret_count = count;
if (ret_blk)
*ret_blk = blk;
return retval;
}
j += count; blk += count;
}
return 0;
}
/*
* Helper function for creating the journal using direct I/O routines
*/
struct mkjournal_struct {
int num_blocks;
int newblocks;
blk_t blk_to_zero;
int zero_count;
char *buf;
errcode_t err;
};
@ -169,7 +227,27 @@ static int mkjournal_proc(ext2_filsys fs,
es->num_blocks--;
es->newblocks++;
retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
retval = 0;
if (blockcnt <= 0)
retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
else {
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_blocks(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);
@ -216,6 +294,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
es.newblocks = 0;
es.buf = buf;
es.err = 0;
es.zero_count = 0;
retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
0, mkjournal_proc, &es);
@ -223,6 +302,12 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
retval = es.err;
goto errout;
}
if (es.zero_count) {
retval = ext2fs_zero_blocks(fs, es.blk_to_zero,
es.zero_count, 0, 0);
if (retval)
goto errout;
}
if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
goto errout;