Proposal : cache of Blocks for BlockDeviceAPI

A brief overview of what we have currently :



public interface FSBlockDeviceAPI extends BlockDeviceAPI {

public int getSectorSize();

public PartitionTableEntry getPartitionTableEntry();

}



public interface BlockDeviceAPI extends DeviceAPI {

public abstract long getLength()

public abstract void read(long devOffset, byte[] dest, int destOffset, int length)

public abstract void write(long devOffset, byte[] src, int srcOffset, int length)

public abstract void flush()

}




This is what I propose :

On the model of the class BlockAlignmentSupport, this class implements the cache and do the alignment :

public class BlockCache implements BlockDeviceAPI {

public BlockAlignmentSupport(FSBlockDeviceAPI parentApi)

public BlockAlignmentSupport(BlockDeviceAPI parentApi, int blockSize)



public long getLength() // delegate to parentApi



// align an then delegate to parentApi

public void read(long devOffset, byte[] dest, int destOffset, int length)



// align an then delegate to parentApi

public void write(long devOffset, byte[] src, int srcOffset, int length)// delegate to parentApi



public void flush()// delegate to parentApi

}



This class will be in the package org.jnode.driver.block



Two class named Block and BlockCache in the package org.jnode.fs.ext2.cache should be refactored (moved to the package org.jnode.driver.block). These classes also need to become more generic and used for the cache.



Do you agree ?

sector operations

I would add the following methods for performance reasons:

public abstract int getBlockSize(); //should return the underlying sector size
public abstract void readBlock(long blockNr, byte[] dest);
public abstract void writeBlock(long blockNr, byte[] src);

This way we could avoid a lot of costly mappings (it's quite easy to map between blocks and sectors so there's no need to do a mapping to from blocks to bytes, than from bytes to sectors).

Andras

what do you mean by block and sector ?

For me, a block is a sector : the smallest quantity of data a BlockDevice can read/write.

What do you think about putting these 3 methods in the class Block.
Because :
- the block know his size
- the block can read/write himself with a BlockDevice as a member variable of the class
- the block can copy his data to a buffer given by the user
- the block is created by the BlockDevice : the BlockDevice act as a Factory of Blocks

blocks and sectors

What do you think about putting these 3 methods in the class Block.
Sorry for the confusion, I was talking about the BlockCache class that you have described in your proposal.

> For me, a block is a sector :
I think the IDE driver handles sectors and they are usually 512 bytes, but I may be wrong. However a filesystem block can be of some different size (e.g. ext2 uses 1024, 2048, 4096 etc. bytes long blocks).

>the smallest quantity of data a BlockDevice can read/write.
In this sense the units that the cache handles are sectors, so we'll need to know the ratio of a block to a sector.

Your arguments are certainly true, everything can be read and written with the read and write methods that you have suggested. But as these operations are not neccessarily aligned to sector boundaries, a mapping is needed. What I was suggesting is no big deal just including two methods that expect their input to be aligned (because their inputs are blocks, they will be aligned to sectors as well), so the mapping can be avoided. Then in the FS implementations it's just a matter of translating 1 filesystem block to some sectors (indeed this is a kind of simple mapping), but we spare some calculations, that's all.
Anyway I have realized we need to add a sourceOffset parameter to the methods I have mentioned.

Andras