[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <609A6301-38DD-4794-B707-A4E5A7A84B5F@dilger.ca>
Date: Mon, 17 Mar 2014 17:11:09 -0600
From: Andreas Dilger <adilger@...ger.ca>
To: "Darrick J. Wong" <darrick.wong@...cle.com>
Cc: tytso@....edu, linux-ext4@...r.kernel.org
Subject: Re: [PATCH 36/49] libext2fs: allow clients to read-ahead metadata
On Mar 11, 2014, at 12:57 AM, Darrick J. Wong <darrick.wong@...cle.com> wrote:
> This patch adds to libext2fs the ability to pre-fetch metadata
> into the page cache in the hopes of speeding up libext2fs' clients.
> There are two new library functions -- the first allows a client to
> readahead a list of blocks, and the second is a helper function that
> uses that first mechanism to load group data (bitmaps, inode tables).
>
> e2fsck will employ both of these methods to speed itself up.
You can also add a Reviewed-by: Andreas Dilger <adilger@...ger.ca> on this.
> diff --git a/lib/ext2fs/readahead.c b/lib/ext2fs/readahead.c
> new file mode 100644
> index 0000000..ed6e555
> --- /dev/null
> +++ b/lib/ext2fs/readahead.c
> @@ -0,0 +1,188 @@
> +struct read_dblist {
> + errcode_t err;
> + blk64_t run_start;
> + blk64_t run_len;
> +};
> +
> +static EXT2_QSORT_TYPE readahead_dir_block_cmp(const void *a, const void *b)
> +{
> + const struct ext2_db_entry2 *db_a =
> + (const struct ext2_db_entry2 *) a;
> + const struct ext2_db_entry2 *db_b =
> + (const struct ext2_db_entry2 *) b;
> +
> + return (int) (db_a->blk - db_b->blk);
> +}
> +
> +static int readahead_dir_block(ext2_filsys fs, struct ext2_db_entry2 *db,
> + void *priv_data)
> +{
> + errcode_t err = 0;
> + struct read_dblist *pr = priv_data;
> +
> + if (!pr->run_len || db->blk != pr->run_start + pr->run_len) {
It probably isn't necessary to check "!pr->run_len", since the only
case where this isn't entered on a new look is db->blk == 0, which is
always loaded when the filesystem is mounted anyway.
Cheers, Andreas
> + if (pr->run_len) {
> + pr->err = io_channel_cache_readahead(fs->io,
> + pr->run_start,
> + pr->run_len);
> + dbg_printf("readahead start=%llu len=%llu err=%d\n",
> + pr->run_start, pr->run_len,
> + (int)pr->err);
> + }
> + pr->run_start = db->blk;
> + pr->run_len = 0;
> + }
> + pr->run_len += db->blockcnt;
> +
> + return pr->err ? DBLIST_ABORT : 0;
> +}
> +
> +errcode_t ext2fs_readahead_dblist(ext2_filsys fs, int flags,
> + ext2_dblist dblist)
> +{
> + errcode_t err;
> + struct read_dblist pr;
> +
> + dbg_printf("%s: flags=0x%x\n", __func__, flags);
> + if (flags)
> + return EXT2_ET_INVALID_ARGUMENT;
> +
> + ext2fs_dblist_sort2(dblist, readahead_dir_block_cmp);
> +
> + memset(&pr, 0, sizeof(pr));
> + err = ext2fs_dblist_iterate2(dblist, readahead_dir_block, &pr);
> + if (pr.err)
> + return pr.err;
> + if (err)
> + return err;
> +
> + if (pr.run_len)
> + err = io_channel_cache_readahead(fs->io, pr.run_start,
> + pr.run_len);
> +
> + return err;
> +}
> +
> +errcode_t ext2fs_readahead(ext2_filsys fs, int flags, dgrp_t start,
> + dgrp_t ngroups)
> +{
> + blk64_t super, old_gdt, new_gdt;
> + blk_t blocks;
> + dgrp_t i;
> + ext2_dblist dblist;
> + dgrp_t end = start + ngroups;
> + errcode_t err = 0;
> +
> + dbg_printf("%s: flags=0x%x start=%d groups=%d\n", __func__, flags,
> + start, ngroups);
> + if (flags & ~EXT2_READA_ALL_FLAGS)
> + return EXT2_ET_INVALID_ARGUMENT;
> +
> + if (end > fs->group_desc_count)
> + end = fs->group_desc_count;
> +
> + if (flags == 0)
> + return 0;
> +
> + err = ext2fs_init_dblist(fs, &dblist);
> + if (err)
> + return err;
> +
> + for (i = start; i < end; i++) {
> + err = ext2fs_super_and_bgd_loc2(fs, i, &super, &old_gdt,
> + &new_gdt, &blocks);
> + if (err)
> + break;
> +
> + if (flags & EXT2_READA_SUPER) {
> + err = ext2fs_add_dir_block2(dblist, 0, super, 0);
> + if (err)
> + break;
> + }
> +
> + if (flags & EXT2_READA_GDT) {
> + if (old_gdt)
> + err = ext2fs_add_dir_block2(dblist, 0, old_gdt,
> + blocks);
> + else if (new_gdt)
> + err = ext2fs_add_dir_block2(dblist, 0, new_gdt,
> + blocks);
> + else
> + err = 0;
> + if (err)
> + break;
> + }
> +
> + if ((flags & EXT2_READA_BBITMAP) &&
> + !ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
> + ext2fs_bg_free_blocks_count(fs, i) <
> + fs->super->s_blocks_per_group) {
> + super = ext2fs_block_bitmap_loc(fs, i);
> + err = ext2fs_add_dir_block2(dblist, 0, super, 1);
> + if (err)
> + break;
> + }
> +
> + if ((flags & EXT2_READA_IBITMAP) &&
> + !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
> + ext2fs_bg_free_inodes_count(fs, i) <
> + fs->super->s_inodes_per_group) {
> + super = ext2fs_inode_bitmap_loc(fs, i);
> + err = ext2fs_add_dir_block2(dblist, 0, super, 1);
> + if (err)
> + break;
> + }
> +
> + if ((flags & EXT2_READA_ITABLE) &&
> + ext2fs_bg_free_inodes_count(fs, i) <
> + fs->super->s_inodes_per_group) {
> + super = ext2fs_inode_table_loc(fs, i);
> + blocks = fs->inode_blocks_per_group -
> + (ext2fs_bg_itable_unused(fs, i) *
> + EXT2_INODE_SIZE(fs->super) / fs->blocksize);
> + err = ext2fs_add_dir_block2(dblist, 0, super, blocks);
> + if (err)
> + break;
> + }
> + }
> +
> + if (!err)
> + err = ext2fs_readahead_dblist(fs, 0, dblist);
> +
> + ext2fs_free_dblist(dblist);
> + return err;
> +}
> +
> +int ext2fs_can_readahead(ext2_filsys fs)
> +{
> + errcode_t err;
> +
> + err = io_channel_cache_readahead(fs->io, 0, 1);
> + dbg_printf("%s: supp=%d\n", __func__, err != EXT2_ET_OP_NOT_SUPPORTED);
> + return err != EXT2_ET_OP_NOT_SUPPORTED;
> +}
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Cheers, Andreas
Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)
Powered by blists - more mailing lists