FreeDOS Disk Buffers: BUFFERS=, Dirty Metadata, and Cache Tuning
Tune FreeDOS kernel disk buffers using HMA rules, dirty-sector lifecycle, replacement behavior, safe testing, and the distinction from LBACACHE.
FreeDOS’s BUFFERS= setting controls the kernel’s own disk-sector buffer pool. It is a different layer from a resident BIOS-level read cache such as LBACACHE: the kernel buffers sectors used by DOS block and filesystem operations, including FAT and directory metadata, while a BIOS-hooking cache observes a lower-level disk interface. Confusing the two leads to misleading benchmark results and unsafe assumptions about which writes have reached the device.
This guide explains the FreeDOS-specific BUFFERS configuration, how the kernel cache selects and flushes sector buffers, and how to tune it without treating a larger number as automatic speed or durability. Details below are grounded in the FreeDOS kernel’s current configuration notes and source; another DOS-compatible kernel may implement different rules.
What a kernel disk buffer represents
FreeDOS’s block cache associates a buffer with a disk unit and block number, tracks whether its contents are valid or dirty, and links buffers in a replacement structure. A cache hit returns a previously read sector and updates its recency position. On a miss, the kernel selects a reusable buffer, flushes it if needed, reads the requested block unless the caller is overwriting it, and records the new unit and block identity.
This is sector-oriented state inside the DOS filesystem path. FAT copies and directory entries can be marked dirty as metadata changes, then written through the block-device layer. The buffer cache does not add a journal, atomic transaction, or power-loss rollback. A write reported complete at the DOS or BIOS boundary is not proof that a physical drive’s own volatile cache has committed it to nonvolatile media.
The cache matters disproportionately for small metadata operations. Opening, searching, creating, renaming, or closing files may revisit directory sectors and allocation tables. Repeated access to a working set that fits in cache can avoid repeated device reads; a one-pass large sequential transfer may benefit much less. Measure the workload instead of using a peak sequential-throughput benchmark to justify the setting for a different access pattern.
FreeDOS BUFFERS syntax and memory placement
The kernel configuration documentation describes BUFFERS=nn[,m], where the primary value is from 1 through 99 and the optional secondary value is from 1 through 8. FreeDOS ignores the secondary-buffer option for compatibility; it does not provide the MS-DOS-style read-ahead behavior associated with that field. A sample such as BUFFERS=20 requests at least twenty primary buffers, not a universally recommended optimum.
BUFFERS=20
FreeDOS stores disk buffers in the High Memory Area when possible. If the requested count does not consume available HMA space, additional unused HMA space can be used for more buffers until another component claims that area. The documented negative form, such as BUFFERS=-10, disables that extra-HMA expansion and uses the stated count. This is a FreeDOS-specific policy; validate the installed kernel’s docs/config.txt and boot output before copying the syntax to another DOS system.
BUFFERSHIGH currently behaves like BUFFERS in FreeDOS. The kernel’s configuration notes explain that the buffers can already use HMA and that this option does not place them in UMBs; it mainly provides a compatibility spelling and note to the operator. Do not infer from the word HIGH that a particular number of buffers will be moved into a UMB or that MEM will report a particular memory delta.
Changing the pool has a memory tradeoff. More buffers consume more memory that may otherwise serve the kernel, drivers, TSRs, or applications. On a machine that runs protected-mode programs or allocates XMS for caching, extra memory assigned to a DOS buffer pool can compete indirectly with those workloads even when it resides in HMA. Preserve a minimal boot configuration so a bad memory-layout change does not eliminate the recovery path.
Dirty buffers and flush behavior
A sector buffer becomes dirty when a filesystem or kernel operation changes its contents. FreeDOS source has explicit buffer flags for validity, data, FAT, directory, and dirty state. When a replacement buffer is needed, the kernel flushes a dirty victim before reading another sector into it. A per-device flush walks the buffer list and writes matching dirty buffers; a global flush writes dirty buffers and invalidates the cache entries.
The FAT layer uses these operations during metadata updates. In the directory-update path, FreeDOS copies changed fields into the directory sector, marks it dirty, and flushes buffers for that device. Other operations have their own ordering and lower-level driver behavior. The correct operational conclusion is not “every write is immediately durable,” but “the kernel has defined flush paths whose success still depends on the lower storage stack.” An I/O error can cause the kernel to invalidate cache state; check the actual status and device diagnostics rather than assuming the dirty flag means data is safely retained.
This is also why abrupt power-off, reset, or VM termination is not a valid way to finish a write test. Use the application’s close/commit sequence and the system’s supported shutdown path. If a DOS utility performs raw BIOS writes or a driver bypasses the kernel’s filesystem path, its interactions with the cache may differ; do not assume every disk writer updates cached copies unless the relevant interface and driver document that behavior.
Kernel buffers versus LBACACHE
LBACACHE is a separate resident component that hooks BIOS disk operations and is documented as a read cache that does not defer physical writes. FreeDOS BUFFERS belongs to the kernel block-cache path and can contain dirty metadata that must be flushed. The two components therefore have different visibility, replacement, memory, and failure behavior even though both can reduce repeated reads.
Do not stack caches simply because each appears to improve a benchmark. A lower layer may see activity the upper layer does not, and raw disk access can bypass the kernel’s metadata path. For a first tuning pass, compare the default kernel pool without LBACACHE against one deliberately chosen BUFFERS setting. Only then evaluate an external cache as a separate variable, preserving a cache-free recovery profile for imaging, partitioning, and repair work.
A controlled tuning and acceptance procedure
- Record the exact FreeDOS kernel build, FDCONFIG.SYS or CONFIG.SYS, memory-manager lines, cache TSRs, disk controller, and storage image or device.
- Save a known-good boot configuration and copy the test volume or VM disk. Do not benchmark on the only copy of valuable data.
- Measure the actual task at the current setting: directory-heavy package operations, repeated metadata lookups, or the real application workflow. Include completion time, failures, and available conventional/XMS memory where relevant.
- Change only BUFFERS=. Reboot through the same configuration, confirm the intended line was processed, and repeat the same workload with the same input state.
- Test create, rename, close, reboot, and reopen on disposable files. Compare content hashes and directory state after a normal shutdown. A faster result with missing metadata or a checksum mismatch is a failure.
- Keep the smallest configuration that produces a repeatable benefit without reducing application memory or startup reliability below the workload’s requirement.
Avoid conclusions from one timing run. DOS workloads are sensitive to emulated controller settings, cache warmth, fragmented files, and the order in which a benchmark is executed. Run cold and repeated passes separately, and record the boot profile so a later operator can reproduce the result. If a test changes the disk, restore the same snapshot or image before the next comparison.
For diagnosis, establish which layer is actually slow: kernel sector traffic, BIOS/device-driver requests, physical media, or application behavior. BUFFERS cannot repair filesystem corruption, a failing device, an inaccurate clock, or an application’s repeated whole-disk scan. Increasing buffers can even hide a repeated-read pattern in a warm benchmark while doing nothing for cold startup or write-heavy workloads.
Operational rules
Use BUFFERS= only after measuring the target workload and checking the memory cost. Treat secondary buffers and BUFFERSHIGH as documented compatibility behavior rather than promises of prefetching or UMB allocation. Keep the kernel cache distinct from LBACACHE and any other TSR. Preserve a cache-free rescue profile, shut down cleanly, and verify actual files after writes. Most importantly, regard flushing as a boundary in the software stack, not a durability guarantee that can override a volatile controller cache or a power failure.
The most reliable configuration is not the one with the largest cache count. It is the one whose buffers match the access pattern, whose memory placement is understood, and whose complete device path has been tested for both performance and data integrity.
Related:
- LBACACHE on FreeDOS: Sector Caching Without Gambling with Writes
- FAT12 and FAT16 Internals: The Filesystem Behind FreeDOS
Sources: