// NEW CODE implementing a simple disk i/o multiplexing layer #ifndef _DISKIO_H #define _DISKIO_H #include "sched.h" // TODO: Replace BSIZE references in old code with this and/or make it flexible #define DISKIO_BLOCK_SIZE 4096 typedef struct diskio_buffer diskio_buffer_t; typedef struct diskio_cache diskio_cache_t; // NOTE: This still resembles the old structure but will probably be changed // as different options/backends/etc. are added. struct diskio_buffer { diskio_cache_t* owner; unsigned int referencecount; int padding; int isvalid; int isdisk; // Is this a buffer owned by the disk (rather than the fs code??) unsigned int device; unsigned int blocknumber; sched_sleeplock_t lock; // Least-recently-used list: diskio_buffer_t* previous; diskio_buffer_t* next; // Block data unsigned char* data; // TODO: Flexible buffers }; // The diskio_cache structure should fit in a page, so it must be limited in // to a few hundred buffer references for now: #define DISKIO_CACHE_MAXBUFFERS 500 struct diskio_cache { sched_spinlock_t spin; diskio_buffer_t* leastrecentlist; unsigned long long buffercount; unsigned long long blocksize; diskio_buffer_t* buffers[DISKIO_CACHE_MAXBUFFERS]; }; // These are the internal allocation functions, a cache pre-allocates a number // of buffer structures (each representing 1 disk block) then re-allocates them // on demand from it's internal list. diskio_buffer_t* diskio_buffer_alloc(diskio_cache_t* owner, unsigned long long blocksize); void diskio_buffer_free(diskio_buffer_t* buffer); diskio_cache_t* diskio_cache_alloc(unsigned long long buffercount, unsigned long long blocksize); void diskio_cache_free(diskio_cache_t* cache); // These are the internal read/write functions which link to any I/O multiplexing void diskio_performread(diskio_buffer_t* buffer); void diskio_performwrite(diskio_buffer_t* buffer); // Performs a logical write of a buffered block through it's associated cache, // checks that the buffer is already locked and writes it to the disk. void diskio_buffer_write(diskio_buffer_t* buffer); // Performs a logical read of a buffered block through a cache, returning it in // locked form with the given block. diskio_buffer_t* diskio_buffer_read(diskio_cache_t* cache, unsigned int device, unsigned int blocknumber); // (Re-)allocates a buffer from the cache for a given device and block number // combination, but does NOT attempt to read the block from disk. Returns an // existing or newly repurposed buffer from the cache in a locked state. diskio_buffer_t* diskio_buffer_get_noread(diskio_cache_t* cache, unsigned int device, unsigned int blocknumber); void diskio_buffer_release(diskio_buffer_t* buffer); void diskio_buffer_reference(diskio_buffer_t* buffer); void diskio_buffer_dereference(diskio_buffer_t* buffer); // Used internally for reads/writes to ramdisk devices void diskio_ramdisk_rw(diskio_buffer_t* buffer, int wr); struct drives; // Defined properly in drives.h // Called to mount any available ramdisk images on the given drives structure. void diskio_mountallramdisks(struct drives* drives); // From ifndef at top of file: #endif