/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * User Land Cache Manager * * A user land cache manager. */ #ifndef _CACHE_H_ #define _CACHE_H_ #include <stdint.h> /* Different values for initializing cache */ enum { /* Default sizes */ DefaultCacheBlockSize = 0x8000, /* 32K */ DefaultCacheBlocks = 1024, DefaultCacheSize = (DefaultCacheBlockSize * DefaultCacheBlocks), /* 32MBytes */ /* Minimum allowed sizes */ MinCacheBlockSize = 0x8000, /* 32K */ MinCacheBlocks = 1024, MinCacheSize = (MinCacheBlockSize * MinCacheBlocks), /* 32MBytes */ /* Maximum allowed sizes */ MaxCacheBlockSize = 0x8000, /* 32K */ #ifdef __LP64__ MaxCacheBlocks = 0x18000, #else MaxCacheBlocks = 0x8000, #endif /* MaxCacheSize will be 3G for 64-bit, and 1G for 32-bit */ MaxCacheSize = ((unsigned)MaxCacheBlockSize * MaxCacheBlocks), CacheHashSize = 257, /* prime number */ }; /* * Some nice lowercase shortcuts. */ #define EOK 0 #define BUF_SPAN 0x80000000 /* Buffer spans several cache blocks */ typedef struct LRUNode_t { struct LRUNode_t * Next; /* Next node in the LRU */ struct LRUNode_t * Prev; /* Previous node in the LRU */ } LRUNode_t; typedef struct LRU_t { LRUNode_t Head; /* Dummy node for the head of the LRU */ LRUNode_t Busy; /* List of busy nodes */ } LRU_t; #define MAXBUFS 48 /* * Buf_t * * Buffer structure exchanged between the cache and client. It contains the * data buffer with the requested data, as well as housekeeping information * that the cache needs. */ typedef struct Buf_t { struct Buf_t * Next; /* Next active buffer */ struct Buf_t * Prev; /* Previous active buffer */ uint32_t Flags; /* Buffer flags */ uint64_t Offset; /* Start offset of the buffer */ uint32_t Length; /* Size of the buffer in bytes */ void * Buffer; /* Buffer */ } Buf_t; /* * Tag_t * * The cache tag structure is a header for a cache buffer. It contains a * pointer to the cache block and housekeeping information. The type of LRU * algorithm can be swapped out easily. * * NOTE: The LRU field must be the first field, so we can easily cast between * the two. */ typedef struct Tag_t { LRUNode_t LRU; /* LRU specific data, must be first! */ struct Tag_t * Next; /* Next tag in hash chain */ struct Tag_t * Prev; /* Previous tag in hash chain */ uint32_t Flags; uint32_t Refs; /* Reference count */ uint64_t Offset; /* Offset of the buffer */ void * Buffer; /* Cache page */ } Tag_t; /* Tag_t.Flags bit settings */ enum { kLazyWrite = 0x00000001, /* only write this page when evicting or forced */ kLockWrite = 0x00000002, /* Never evict this page -- will not work with writing yet! */ }; /* * Cache_t * * The main cache data structure. The cache manages access between an open * file and the cache client program. * * NOTE: The LRU field must be the first field, so we can easily cast between * the two. */ typedef struct Cache_t { LRU_t LRU; /* LRU replacement data structure */ int FD_R; /* File descriptor (read-only) */ int FD_W; /* File descriptor (write-only) */ uint32_t DevBlockSize; /* Device block size */ Tag_t ** Hash; /* Lookup hash table (move to front) */ uint32_t HashSize; /* Size of the hash table */ uint32_t BlockSize; /* Size of the cache page */ void * FreeHead; /* Head of the free list */ uint32_t FreeSize; /* Size of the free list */ Buf_t * ActiveBufs; /* List of active buffers */ Buf_t * FreeBufs; /* List of free buffers */ uint32_t ReqRead; /* Number of read requests */ uint32_t ReqWrite; /* Number of write requests */ uint32_t DiskRead; /* Number of actual disk reads */ uint32_t DiskWrite; /* Number of actual disk writes */ uint32_t Span; /* Requests that spanned cache blocks */ } Cache_t; extern Cache_t fscache; /* * CalculateCacheSizes * * Determine the cache size values (block size and total blocks) that should * be used to initialize the cache. */ void CalculateCacheSizes(uint64_t userCacheSize, uint32_t *calcBlockSize, uint32_t *calcTotalBlocks, char debug); /* * CacheInit * * Initializes the cache for use. */ int CacheInit (Cache_t *cache, int fdRead, int fdWrite, uint32_t devBlockSize, uint32_t cacheBlockSize, uint32_t cacheSize, uint32_t hashSize, int preTouch); /* * CacheDestroy * * Shutdown the cache. */ int CacheDestroy (Cache_t *cache); /* * CacheRead * * Reads a range of bytes from the cache, returning a pointer to a buffer * containing the requested bytes. * * NOTE: The returned buffer may directly refer to a cache block, or an * anonymous buffer. Do not make any assumptions about the nature of * the returned buffer, except that it is contiguous. */ int CacheRead (Cache_t *cache, uint64_t start, uint32_t len, Buf_t **buf); /* * CacheWrite * * Writes a buffer through the cache. */ int CacheWrite ( Cache_t *cache, Buf_t *buf, int age, uint32_t writeOptions ); /* * CacheRelease * * Releases a clean buffer. * * NOTE: We don't verify whether it's dirty or not. */ int CacheRelease (Cache_t *cache, Buf_t *buf, int age); /* CacheRemove * * Disposes of a particular tag and buffer. */ int CacheRemove (Cache_t *cache, Tag_t *tag); /* * CacheEvict * * Only dispose of the buffer, leave the tag intact. */ int CacheEvict (Cache_t *cache, Tag_t *tag); /* * CacheFlush * * Write out any blocks that are marked for lazy write. */ int CacheFlush( Cache_t *cache ); /* CacheCopyDiskBlocks * * Perform direct disk block copy from from_offset to to_offset of given length. */ int CacheCopyDiskBlocks (Cache_t *cache, uint64_t from_offset, uint64_t to_offset, uint32_t len); /* CacheWriteBufferToDisk * * Write data on disk starting at given offset for upto write_len. * The data from given buffer upto buf_len is written to the disk starting * at given offset. If the amount of data written on disk is greater than * the length of buffer, all the remaining data is written as zeros. * * If no buffer is provided or if length of buffer is zero, the function * writes zeros on disk from offset upto write_len bytes. */ int CacheWriteBufferToDisk (Cache_t *cache, uint64_t offset, uint32_t write_len, u_char *buffer, uint32_t buf_len); #endif