244 lines
6.3 KiB
C
244 lines
6.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
blcache.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module declares parameters, data structures and functions for
|
||
|
a general purpose disk caching for the boot loader. Although it is
|
||
|
mostly general purpose, it is mainly used for caching filesystem
|
||
|
metadata, since that is the only frequently reaccessed data in the
|
||
|
boot loader. In order to use caching on a device, you must make
|
||
|
sure that there is only one unique BlFileTable entry for that
|
||
|
device and the same device is not opened & cached simultaneously
|
||
|
multiple times under different device ids. Otherwise there will be
|
||
|
cache inconsistencies, since cached data and structures are
|
||
|
maintained based on device id. Also you must make sure to stop
|
||
|
caching when the device is closed.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Cenk Ergan (cenke) 14-Jan-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef _BLCACHE_H
|
||
|
#define _BLCACHE_H
|
||
|
|
||
|
#include "bldr.h"
|
||
|
#include "blrange.h"
|
||
|
|
||
|
//
|
||
|
// Define boot loader disk cache parameters and data structures.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Currently device id - cache header pairing is done using a global
|
||
|
// table. This determines maximum number of entries in this table. We
|
||
|
// really need just two entries, one for LoadDevice, one for
|
||
|
// SystemDevice. Caches for all devices share the same resources
|
||
|
// [e.g. cache blocks and Most Recently Used list etc.]
|
||
|
//
|
||
|
|
||
|
#define BL_DISKCACHE_DEVICE_TABLE_SIZE 2
|
||
|
|
||
|
//
|
||
|
// Size of ranges that are cached. We read & cache fixed size blocks
|
||
|
// from the devices which makes memory management easy, since we can't
|
||
|
// use boot loader's: there is no HeapFree, just HeapAlloc! BLOCK_SIZE
|
||
|
// has to be a power of two for alignment arithmetic to work.
|
||
|
//
|
||
|
|
||
|
#define BL_DISKCACHE_BLOCK_SIZE (32 * 1024)
|
||
|
|
||
|
//
|
||
|
// Maximum number of bytes cached in the disk cache [i.e. maximum size
|
||
|
// disk cache may grow to]. This should be a multiple of BLOCK_SIZE below.
|
||
|
//
|
||
|
|
||
|
#define BL_DISKCACHE_SIZE (64 * BL_DISKCACHE_BLOCK_SIZE)
|
||
|
|
||
|
//
|
||
|
// Maximum number of cache blocks / range entries there can be in the
|
||
|
// cache. There will be a range entry for each block, i.e. it should
|
||
|
// be cache size / block size.
|
||
|
//
|
||
|
|
||
|
#define BL_DISKCACHE_NUM_BLOCKS (BL_DISKCACHE_SIZE / BL_DISKCACHE_BLOCK_SIZE)
|
||
|
|
||
|
//
|
||
|
// Size of the buffer needed for storing maximum number of overlapping
|
||
|
// or distinct range entries for a 64KBs request given BLOCK_SIZE. We
|
||
|
// reserve this on the stack [i.e. buffer is a local variable] in
|
||
|
// BlDiskCacheRead: make sure it is not too big! We base it assuming
|
||
|
// that distincts buffer will be larger [since it is BLCRANGE entries
|
||
|
// instead where as overlaps buffer contains BLCRANGE_ENTRY pointers.]
|
||
|
//
|
||
|
|
||
|
#define BL_DISKCACHE_FIND_RANGES_BUF_SIZE \
|
||
|
(((64 * 1024 / BL_DISKCACHE_BLOCK_SIZE) + 3) * (sizeof(BLCRANGE)))
|
||
|
|
||
|
//
|
||
|
// This is the header for the cache for a particular device. The
|
||
|
// cached ranges on this device are stored in the Ranges list.
|
||
|
//
|
||
|
|
||
|
typedef struct _BL_DISK_SUBCACHE
|
||
|
{
|
||
|
BOOLEAN Initialized;
|
||
|
ULONG DeviceId;
|
||
|
BLCRANGE_LIST Ranges;
|
||
|
} BL_DISK_SUBCACHE, *PBL_DISK_SUBCACHE;
|
||
|
|
||
|
//
|
||
|
// Define structure for the global boot loader diskcache.
|
||
|
//
|
||
|
|
||
|
typedef struct _BL_DISKCACHE
|
||
|
{
|
||
|
//
|
||
|
// Table that contains cache headers. Cache - DeviceId pairing is
|
||
|
// also done using this table.
|
||
|
//
|
||
|
|
||
|
BL_DISK_SUBCACHE DeviceTable[BL_DISKCACHE_DEVICE_TABLE_SIZE];
|
||
|
|
||
|
//
|
||
|
// Most recently used list for cached blocks [range
|
||
|
// entries]. Entries are linked through the UserLink field in the
|
||
|
// BLCRANGE_ENTRY. The least recently used block is at the very
|
||
|
// end. Any entries placed on a cache's range list is also put on
|
||
|
// this list. When removing a range from a cache's range list, the
|
||
|
// callback removes it from this list too. BlDiskCacheRead updates
|
||
|
// this list and prunes it if normal cache entry allocation fails.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY MRUBlockList;
|
||
|
|
||
|
//
|
||
|
// This is where cached data is stored. Its size is
|
||
|
// BL_DISKCACHE_SIZE. It is divided up into BL_DISKCACHE_NUM_BLOCKS
|
||
|
// blocks. Nth block belongs to Nth entry in the EntryBuffer.
|
||
|
//
|
||
|
|
||
|
PUCHAR DataBuffer;
|
||
|
|
||
|
//
|
||
|
// Range entries to be put into the cache's range lists are
|
||
|
// allocated from here. It has BL_DISKCACHE_NUM_BLOCKS elements.
|
||
|
//
|
||
|
|
||
|
PBLCRANGE_ENTRY EntryBuffer;
|
||
|
|
||
|
//
|
||
|
// This array is used for keeping track of the free range entries
|
||
|
// in EntryBuffer. Free range entries get linked up on this list
|
||
|
// using the UserLink field. Once the entry is allocated, the
|
||
|
// UserLink field is usually used to link it up to the MRU list.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY FreeEntryList;
|
||
|
|
||
|
//
|
||
|
// Keep track of whether we are initialized or not.
|
||
|
//
|
||
|
|
||
|
BOOLEAN Initialized;
|
||
|
|
||
|
} BL_DISKCACHE, *PBL_DISKCACHE;
|
||
|
|
||
|
//
|
||
|
// Declare global variables.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// This is the boot loader disk cache with all its bells and whistles.
|
||
|
//
|
||
|
|
||
|
extern BL_DISKCACHE BlDiskCache;
|
||
|
|
||
|
//
|
||
|
// Debug defines. Use these to actively debug the disk cache. These
|
||
|
// are not turned on for checked build, because they would spew out
|
||
|
// too much to the console.
|
||
|
//
|
||
|
|
||
|
#ifdef BL_DISKCACHE_DEBUG
|
||
|
#define DPRINT(_x) DbgPrint _x;
|
||
|
#define DASSERT(_c) do { if (_c) DbgBreakPoint(); } while (0);
|
||
|
#else // BL_DISKCACHE_DEBUG
|
||
|
#define DPRINT(_x)
|
||
|
#define DASSERT(_c)
|
||
|
#endif // BL_DISKCACHE_DEBUG
|
||
|
|
||
|
//
|
||
|
// These two defines are used as the last parameter to BlDiskCacheRead.
|
||
|
// They specify whether any new data read from the disk should be put
|
||
|
// into the disk cache or not. In the boot loader file systems we usually
|
||
|
// choose to cache new data if we are reading metadata, and not choose to
|
||
|
// cache it if we are reading file data.
|
||
|
//
|
||
|
|
||
|
#define CACHE_NEW_DATA (TRUE)
|
||
|
#define DONT_CACHE_NEW_DATA (FALSE)
|
||
|
|
||
|
//
|
||
|
// Useful macros. Be mindful of expression reevaluation as with
|
||
|
// all macros.
|
||
|
//
|
||
|
|
||
|
#define BLCMIN(a,b) (((a) <= (b)) ? (a) : (b))
|
||
|
#define BLCMAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||
|
|
||
|
//
|
||
|
// Cache function prototypes. See ntos\boot\lib\blcache.c for comments
|
||
|
// and implementation.
|
||
|
//
|
||
|
|
||
|
ARC_STATUS
|
||
|
BlDiskCacheInitialize(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
BlDiskCacheUninitialize(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
PBL_DISK_SUBCACHE
|
||
|
BlDiskCacheStartCachingOnDevice(
|
||
|
ULONG DeviceId
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
BlDiskCacheStopCachingOnDevice(
|
||
|
ULONG DeviceId
|
||
|
);
|
||
|
|
||
|
ARC_STATUS
|
||
|
BlDiskCacheRead (
|
||
|
ULONG DeviceId,
|
||
|
PLARGE_INTEGER pOffset,
|
||
|
PVOID Buffer,
|
||
|
ULONG Length,
|
||
|
PULONG pCount,
|
||
|
BOOLEAN CacheNewData
|
||
|
);
|
||
|
|
||
|
ARC_STATUS
|
||
|
BlDiskCacheWrite (
|
||
|
ULONG DeviceId,
|
||
|
PLARGE_INTEGER pOffset,
|
||
|
PVOID Buffer,
|
||
|
ULONG Length,
|
||
|
PULONG pCount
|
||
|
);
|
||
|
|
||
|
#endif // _BLCACHE_H
|