User Tools

Site Tools


Some basic VM call documentation

Secondary cache

The secondary block cache is a mechanism to utilize all available system memory as a disk cache. This functionality has to be in VM because it must be able to free the cache blocks if memory is needed for anything else, without blocking on it. I.e. it cannot rely on any other process to first free memory.

It is intended to be used by filesystem processes to store blocks it evicts from its own cache, hence the name 'secondary cache' and the use of the word 'block' and most of the time.

Logical Interface

Blocks are identified by a (dev, dev_off) pair. This pair uniquely identifies a cache block in VM. These numbers have meaning to VM too: dev is the full device number (i.e. major together with minor) of the device it resides on, and dev_off is the offset from the minor device.

Furthermore each block has an inode and an inode offset associated with it. If the block is a file data block, this inode number must be a number uniquely identifying this file. Otherwise the inode number must be VMC_NO_INODE and the inode offset is irrelevant. The inode metadata is informational, they needn't be unique in the VM cache.

Logically there are three operations:

  1. Set a block. The caller passes the virtual address of the block, its length, and its identification to VM. VM will keep that block and the metadata in its cache. This is the way to indicate a new cache block to VM, for possible later retrieval. The (dev, dev_off) pair is required and is unique; a possible existing block with that ID will be removed from the cache.
  2. Map a block. The caller passes the (dev, dev_off) pair to VM, together with further metadata. If the block exists, VM maps the cache block in and returns the address to the caller. VM updates its notion of the inode and inode offset of the block.
  3. Clear blocks. The caller passes a dev device identifier to VM, and VM removes all blocks associated with that device from its cache.

C Interface

There are three calls, vm_set_cacheblock, vm_map_cacheblock, and vm_clear_cache.

int vm_set_cacheblock(void *block, u32_t dev, u64_t dev_offset,
u64_t ino, u64_t ino_offset, u32_t *flags, int blocksize);

This call indicates a new block to VM. If the block is not inode data, ino must be VMC_NO_INODE. flags points to a 32-bit flags field that is a mask of VMMC_* values. This is currently unused but it is to be expected that in the future, VM will evict blocks not marked by VMMC_BLOCK_LOCKED or VMMC_DIRTY, so callers must set these when in use or dirty, respectively.

The caller has allocated memory for block and filled it with the correct data already.

The call returns OK or an error code.

void *vm_map_cacheblock(u32_t dev, u64_t dev_offset,
        u64_t ino, u64_t ino_offset, u32_t *flags, int blocksize);

This call requests the block identified by the device number and offset to be mapped in. It returns an address on success or MAP_FAILED on failure (e.g. block not found). VM updates its notion of the inode metadata with the parameters if the block was already in the cache.

int vm_clear_cache(u32_t dev);

This call requests that VM forget all blocks associated with the given device. This call should be used (directly or indirectly) by file systems when 1) they get a REQ_FLUSH request from VFS, and 2) when they successfully unmount. This ensures that no stale blocks remain in VM, which could cause corruption upon recall later.

releases/3.2.1/developersguide/vmcalls.txt · Last modified: 2014/11/11 14:52 (external edit)