/*
 * readahead.c -- Prefetch filesystem metadata to speed up fsck.
 *
 * Copyright (C) 2014 Oracle.
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Library
 * General Public License, version 2.
 * %End-Header%
 */

#include "config.h"
#include <string.h>

#include "e2fsck.h"

#undef DEBUG

#ifdef DEBUG
# define dbg_printf(f, a...)  do {printf(f, ## a); fflush(stdout); } while (0)
#else
# define dbg_printf(f, a...)
#endif

struct read_dblist {
	errcode_t err;
	blk64_t run_start;
	blk64_t run_len;
	int flags;
};

static int readahead_dir_block(ext2_filsys fs, struct ext2_db_entry2 *db,
			       void *priv_data)
{
	struct read_dblist *pr = priv_data;
	e2_blkcnt_t count = (pr->flags & E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT ?
			     1 : db->blockcnt);

	if (!pr->run_len || db->blk != pr->run_start + pr->run_len) {
		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 += count;

	return pr->err ? DBLIST_ABORT : 0;
}

errcode_t e2fsck_readahead_dblist(ext2_filsys fs, int flags,
				  ext2_dblist dblist,
				  unsigned long long start,
				  unsigned long long count)
{
	errcode_t err;
	struct read_dblist pr;

	dbg_printf("%s: flags=0x%x\n", __func__, flags);
	if (flags & ~E2FSCK_RA_DBLIST_ALL_FLAGS)
		return EXT2_ET_INVALID_ARGUMENT;

	memset(&pr, 0, sizeof(pr));
	pr.flags = flags;
	err = ext2fs_dblist_iterate3(dblist, readahead_dir_block, start,
				     count, &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;
}

static errcode_t e2fsck_readahead_bitmap(ext2_filsys fs,
					 ext2fs_block_bitmap ra_map)
{
	blk64_t start, end, out;
	errcode_t err;

	start = 1;
	end = ext2fs_blocks_count(fs->super) - 1;

	err = ext2fs_find_first_set_block_bitmap2(ra_map, start, end, &out);
	while (err == 0) {
		start = out;
		err = ext2fs_find_first_zero_block_bitmap2(ra_map, start, end,
							   &out);
		if (err == ENOENT) {
			out = end;
			err = 0;
		} else if (err)
			break;

		err = io_channel_cache_readahead(fs->io, start, out - start);
		if (err)
			break;
		start = out;
		err = ext2fs_find_first_set_block_bitmap2(ra_map, start, end,
							  &out);
	}

	if (err == ENOENT)
		err = 0;

	return err;
}

/* Try not to spew bitmap range errors for readahead */
static errcode_t mark_bmap_range(ext2fs_block_bitmap map,
				 blk64_t blk, unsigned int num)
{
	if (blk >= ext2fs_get_generic_bmap_start(map) &&
	    blk + num <= ext2fs_get_generic_bmap_end(map))
		ext2fs_mark_block_bitmap_range2(map, blk, num);
	else
		return EXT2_ET_INVALID_ARGUMENT;
	return 0;
}

static errcode_t mark_bmap(ext2fs_block_bitmap map, blk64_t blk)
{
	if (blk >= ext2fs_get_generic_bmap_start(map) &&
	    blk <= ext2fs_get_generic_bmap_end(map))
		ext2fs_mark_block_bitmap2(map, blk);
	else
		return EXT2_ET_INVALID_ARGUMENT;
	return 0;
}

errcode_t e2fsck_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;
	ext2fs_block_bitmap		ra_map = NULL;
	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 & ~E2FSCK_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_allocate_block_bitmap(fs, "readahead bitmap",
					   &ra_map);
	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 & E2FSCK_READA_SUPER) {
			err = mark_bmap(ra_map, super);
			if (err)
				break;
		}

		if (flags & E2FSCK_READA_GDT) {
			err = mark_bmap_range(ra_map,
					      old_gdt ? old_gdt : new_gdt,
					      blocks);
			if (err)
				break;
		}

		if ((flags & E2FSCK_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 = mark_bmap(ra_map, super);
			if (err)
				break;
		}

		if ((flags & E2FSCK_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 = mark_bmap(ra_map, super);
			if (err)
				break;
		}

		if ((flags & E2FSCK_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 = mark_bmap_range(ra_map, super, blocks);
			if (err)
				break;
		}
	}

	if (!err)
		err = e2fsck_readahead_bitmap(fs, ra_map);

	ext2fs_free_block_bitmap(ra_map);
	return err;
}

int e2fsck_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;
}

unsigned long long e2fsck_guess_readahead(ext2_filsys fs)
{
	unsigned long long guess;

	/*
	 * The optimal readahead sizes were experimentally determined by
	 * djwong in August 2014.  Setting the RA size to two block groups'
	 * worth of inode table blocks seems to yield the largest reductions
	 * in e2fsck runtime.
	 */
	guess = 2ULL * fs->blocksize * fs->inode_blocks_per_group;

	/* Disable RA if it'd use more 1/50th of RAM. */
	if (get_memory_size() > (guess * 50))
		return guess / 1024;

	return 0;
}
