The kernel maintains a buffer cache registry. That is, the kernel maintains a mapping between disk block numbers and pages that contain those disk blocks. Applications control the content of this cache by allocat ing physical pages, reading and writing data into these pages, and registering them in the cache. Remember that physical pages are reference counted and when the last user process unmaps a page that page can be reused. In order to reuse buffers even if no application is currently mapping the buffer the kernel remembers whether a page contains a buffer or not and tries to delay reusing pages containing buffers for as long as possible.
The buffer cache is currently somewhat schizophrantic. One set of interfaces for reading and writing blocks from disk through the cache exists that does not use XN and another exists that does use XN. Avoid using the non-XN calls. These exist purely for compatibility and will soon be removed.
Further muddying things is the fact that the buffer cache uses 64 bit numbers for block numbers but the disk code only uses 32 bit numbers. Thus, there are some duplicate interfaces that take one size or another. Hopefully this will all get cleaned up soon.
The buffer cache is used to cache all filesystem blocks, both disk and network based. Thus, NFS encodes NFS handle and file offset information into the device and block numbers it caches it's blocks under while real disk devices use their actual device and block numbers for caching blocks.
Each buffer has a user-settable dirty flag. This is so a cleaning demon can periodically go through the buffer cache and start asynch write-backs on all dirty buffers.