From c86085044195c8b721fe9ee327d790316399781e Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 27 Apr 2008 16:10:32 -0400 Subject: [PATCH] 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" --- lib/ext2fs/ext2fs.h | 2 ++ lib/ext2fs/mkjournal.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 9283fd2..7a1d966 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -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); diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c index 23cc60c..ca8e733 100644 --- a/lib/ext2fs/mkjournal.c +++ b/lib/ext2fs/mkjournal.c @@ -135,11 +135,69 @@ errout: } /* + * 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; -- 1.8.3.1