[prev in list] [next in list] [prev in thread] [next in thread] 

List:       tux2-dev
Subject:    Re: [tux2-dev] Index blocks in page cache
From:       Daniel Phillips <phillips () bonn-fries ! net>
Date:       2001-07-13 17:16:32
[Download RAW message or body]

Here is a code skeleton for an ext2_get_block written along the lines I
described in my previous email.  It has the form of an unrolled
recursive procedure: it goes deeper into the recursion as it fails to
find index data present in the cache, working bottom up through the
index levels.  As it unwinds, it reads in the missing blocks.

In a real implementation each is_present line would set a buffer
variable, creating the buffer if necessary, and that buffer would be
used by the read_it and get_data lines.  I didn't show that level of
detail here.

The real ext2_get_block also has a create parameter.  This would be
handled by the read_it lines, which would allocate and fill in a new
block if necessary.

There are also concurrency issues to worry about.  For example, while
on process is reading a missing block, another process could fill in the
same index entry, so that has to be serialized or handled in some way.

This code is not meant to be complete or correct in any way.  Its
purpose is to show how the previously described metadata-in-page-cache
scheme works in practice.  So without further ado:

static int ext2_get_block (struct inode *inode,
	long iblock, struct buffer_head *bh_result)
{
	d1 = iblock - 12;
	x0 = (d1 >> ptrs_per_block_bits) + base0;
	if (!is_present (inode, x0))
	{
		if (x0 == base0)
			block = ind (inode);
		else
		{
			x1 = (x0 >> ptrs_per_block_bits) + base1;
			if (!is_present (inode, x1))
			{
				if (x1 == base1)
					block = dind (inode);
				else
				{
					x2 = (x1 >> ptrs_per_block_bits) + base2;
					if (!is_present (inode, x2))
						read_it (inode, x2, tind (inode));
					block = get_data (inode, x2)[x1 & pmask];
				}
				read_it (inode, x1, block);
			}
			block = get_data (inode, x1)[x0 & pmask];
		}
		read_it (inode, x0, block, create);
	}
	bh_result->b_blocknr = get_data (inode, x0)[d1 & pmask];
	return 0;
}

int is_present (inode, unsigned index):
   Checks that a buffer is present and uptodate.

int read_it (struct inode *inode, unsigned index, u32 block):
   Converts the given metadata block index into a page index/buffer
   number, find the page in the inode's metadata mapping or creates it
   if it isn't there, adds buffers to the page if necessary, enters the
   given block number into the buffer, synchronously reads the block,
   or, if the block number is zero, fills the buffer with zero and marks
   it uptodate
   
u32 *get_data (struct inode *inode, unsigned index):
   As above, but just returns the indexed buffer's data area,

u32 ind (inode):
   returns the inode's indirect pointer 

u32 dind (inode):
   returns the inode's double indirect pointer 

u32 tind (inode):
   returns the inode's triple indirect pointer 

ptrs_per_block_bits, base0, base1, base2:
   precalculated filesystem-constant values

--
Daniel
_______________________________________________
tux2-dev mailing list
tux2-dev@list.innominate.org
http://innominate.org/mailman/listinfo/tux2-dev

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic