| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 1 | MOTIVATION | 
|  | 2 |  | 
|  | 3 | Cleancache is a new optional feature provided by the VFS layer that | 
|  | 4 | potentially dramatically increases page cache effectiveness for | 
|  | 5 | many workloads in many environments at a negligible cost. | 
|  | 6 |  | 
|  | 7 | Cleancache can be thought of as a page-granularity victim cache for clean | 
|  | 8 | pages that the kernel's pageframe replacement algorithm (PFRA) would like | 
|  | 9 | to keep around, but can't since there isn't enough memory.  So when the | 
|  | 10 | PFRA "evicts" a page, it first attempts to use cleancache code to | 
|  | 11 | put the data contained in that page into "transcendent memory", memory | 
|  | 12 | that is not directly accessible or addressable by the kernel and is | 
|  | 13 | of unknown and possibly time-varying size. | 
|  | 14 |  | 
|  | 15 | Later, when a cleancache-enabled filesystem wishes to access a page | 
|  | 16 | in a file on disk, it first checks cleancache to see if it already | 
|  | 17 | contains it; if it does, the page of data is copied into the kernel | 
|  | 18 | and a disk access is avoided. | 
|  | 19 |  | 
|  | 20 | Transcendent memory "drivers" for cleancache are currently implemented | 
|  | 21 | in Xen (using hypervisor memory) and zcache (using in-kernel compressed | 
|  | 22 | memory) and other implementations are in development. | 
|  | 23 |  | 
|  | 24 | FAQs are included below. | 
|  | 25 |  | 
|  | 26 | IMPLEMENTATION OVERVIEW | 
|  | 27 |  | 
|  | 28 | A cleancache "backend" that provides transcendent memory registers itself | 
|  | 29 | to the kernel's cleancache "frontend" by calling cleancache_register_ops, | 
|  | 30 | passing a pointer to a cleancache_ops structure with funcs set appropriately. | 
|  | 31 | Note that cleancache_register_ops returns the previous settings so that | 
|  | 32 | chaining can be performed if desired. The functions provided must conform to | 
|  | 33 | certain semantics as follows: | 
|  | 34 |  | 
|  | 35 | Most important, cleancache is "ephemeral".  Pages which are copied into | 
|  | 36 | cleancache have an indefinite lifetime which is completely unknowable | 
|  | 37 | by the kernel and so may or may not still be in cleancache at any later time. | 
|  | 38 | Thus, as its name implies, cleancache is not suitable for dirty pages. | 
|  | 39 | Cleancache has complete discretion over what pages to preserve and what | 
|  | 40 | pages to discard and when. | 
|  | 41 |  | 
|  | 42 | Mounting a cleancache-enabled filesystem should call "init_fs" to obtain a | 
|  | 43 | pool id which, if positive, must be saved in the filesystem's superblock; | 
|  | 44 | a negative return value indicates failure.  A "put_page" will copy a | 
|  | 45 | (presumably about-to-be-evicted) page into cleancache and associate it with | 
|  | 46 | the pool id, a file key, and a page index into the file.  (The combination | 
|  | 47 | of a pool id, a file key, and an index is sometimes called a "handle".) | 
|  | 48 | A "get_page" will copy the page, if found, from cleancache into kernel memory. | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 49 | An "invalidate_page" will ensure the page no longer is present in cleancache; | 
|  | 50 | an "invalidate_inode" will invalidate all pages associated with the specified | 
|  | 51 | file; and, when a filesystem is unmounted, an "invalidate_fs" will invalidate | 
|  | 52 | all pages in all files specified by the given pool id and also surrender | 
|  | 53 | the pool id. | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 54 |  | 
|  | 55 | An "init_shared_fs", like init_fs, obtains a pool id but tells cleancache | 
|  | 56 | to treat the pool as shared using a 128-bit UUID as a key.  On systems | 
|  | 57 | that may run multiple kernels (such as hard partitioned or virtualized | 
|  | 58 | systems) that may share a clustered filesystem, and where cleancache | 
|  | 59 | may be shared among those kernels, calls to init_shared_fs that specify the | 
|  | 60 | same UUID will receive the same pool id, thus allowing the pages to | 
|  | 61 | be shared.  Note that any security requirements must be imposed outside | 
|  | 62 | of the kernel (e.g. by "tools" that control cleancache).  Or a | 
|  | 63 | cleancache implementation can simply disable shared_init by always | 
|  | 64 | returning a negative value. | 
|  | 65 |  | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 66 | If a get_page is successful on a non-shared pool, the page is invalidated | 
|  | 67 | (thus making cleancache an "exclusive" cache).  On a shared pool, the page | 
|  | 68 | is NOT invalidated on a successful get_page so that it remains accessible to | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 69 | other sharers.  The kernel is responsible for ensuring coherency between | 
|  | 70 | cleancache (shared or not), the page cache, and the filesystem, using | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 71 | cleancache invalidate operations as required. | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 72 |  | 
|  | 73 | Note that cleancache must enforce put-put-get coherency and get-get | 
|  | 74 | coherency.  For the former, if two puts are made to the same handle but | 
|  | 75 | with different data, say AAA by the first put and BBB by the second, a | 
|  | 76 | subsequent get can never return the stale data (AAA).  For get-get coherency, | 
|  | 77 | if a get for a given handle fails, subsequent gets for that handle will | 
|  | 78 | never succeed unless preceded by a successful put with that handle. | 
|  | 79 |  | 
|  | 80 | Last, cleancache provides no SMP serialization guarantees; if two | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 81 | different Linux threads are simultaneously putting and invalidating a page | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 82 | with the same handle, the results are indeterminate.  Callers must | 
|  | 83 | lock the page to ensure serial behavior. | 
|  | 84 |  | 
|  | 85 | CLEANCACHE PERFORMANCE METRICS | 
|  | 86 |  | 
| Dan Magenheimer | 417fc2c | 2011-09-21 12:28:04 -0400 | [diff] [blame] | 87 | If properly configured, monitoring of cleancache is done via debugfs in | 
|  | 88 | the /sys/kernel/debug/mm/cleancache directory.  The effectiveness of cleancache | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 89 | can be measured (across all filesystems) with: | 
|  | 90 |  | 
|  | 91 | succ_gets	- number of gets that were successful | 
|  | 92 | failed_gets	- number of gets that failed | 
|  | 93 | puts		- number of puts attempted (all "succeed") | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 94 | invalidates	- number of invalidates attempted | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 95 |  | 
| Masanari Iida | d65657c | 2012-02-08 23:10:14 +0900 | [diff] [blame] | 96 | A backend implementation may provide additional metrics. | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 97 |  | 
|  | 98 | FAQ | 
|  | 99 |  | 
|  | 100 | 1) Where's the value? (Andrew Morton) | 
|  | 101 |  | 
|  | 102 | Cleancache provides a significant performance benefit to many workloads | 
|  | 103 | in many environments with negligible overhead by improving the | 
|  | 104 | effectiveness of the pagecache.  Clean pagecache pages are | 
|  | 105 | saved in transcendent memory (RAM that is otherwise not directly | 
|  | 106 | addressable to the kernel); fetching those pages later avoids "refaults" | 
|  | 107 | and thus disk reads. | 
|  | 108 |  | 
|  | 109 | Cleancache (and its sister code "frontswap") provide interfaces for | 
|  | 110 | this transcendent memory (aka "tmem"), which conceptually lies between | 
|  | 111 | fast kernel-directly-addressable RAM and slower DMA/asynchronous devices. | 
|  | 112 | Disallowing direct kernel or userland reads/writes to tmem | 
|  | 113 | is ideal when data is transformed to a different form and size (such | 
|  | 114 | as with compression) or secretly moved (as might be useful for write- | 
|  | 115 | balancing for some RAM-like devices).  Evicted page-cache pages (and | 
|  | 116 | swap pages) are a great use for this kind of slower-than-RAM-but-much- | 
|  | 117 | faster-than-disk transcendent memory, and the cleancache (and frontswap) | 
|  | 118 | "page-object-oriented" specification provides a nice way to read and | 
|  | 119 | write -- and indirectly "name" -- the pages. | 
|  | 120 |  | 
|  | 121 | In the virtual case, the whole point of virtualization is to statistically | 
|  | 122 | multiplex physical resources across the varying demands of multiple | 
|  | 123 | virtual machines.  This is really hard to do with RAM and efforts to | 
|  | 124 | do it well with no kernel change have essentially failed (except in some | 
|  | 125 | well-publicized special-case workloads).  Cleancache -- and frontswap -- | 
|  | 126 | with a fairly small impact on the kernel, provide a huge amount | 
|  | 127 | of flexibility for more dynamic, flexible RAM multiplexing. | 
|  | 128 | Specifically, the Xen Transcendent Memory backend allows otherwise | 
|  | 129 | "fallow" hypervisor-owned RAM to not only be "time-shared" between multiple | 
|  | 130 | virtual machines, but the pages can be compressed and deduplicated to | 
|  | 131 | optimize RAM utilization.  And when guest OS's are induced to surrender | 
|  | 132 | underutilized RAM (e.g. with "self-ballooning"), page cache pages | 
|  | 133 | are the first to go, and cleancache allows those pages to be | 
|  | 134 | saved and reclaimed if overall host system memory conditions allow. | 
|  | 135 |  | 
|  | 136 | And the identical interface used for cleancache can be used in | 
|  | 137 | physical systems as well.  The zcache driver acts as a memory-hungry | 
|  | 138 | device that stores pages of data in a compressed state.  And | 
|  | 139 | the proposed "RAMster" driver shares RAM across multiple physical | 
|  | 140 | systems. | 
|  | 141 |  | 
|  | 142 | 2) Why does cleancache have its sticky fingers so deep inside the | 
|  | 143 | filesystems and VFS? (Andrew Morton and Christoph Hellwig) | 
|  | 144 |  | 
|  | 145 | The core hooks for cleancache in VFS are in most cases a single line | 
|  | 146 | and the minimum set are placed precisely where needed to maintain | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 147 | coherency (via cleancache_invalidate operations) between cleancache, | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 148 | the page cache, and disk.  All hooks compile into nothingness if | 
|  | 149 | cleancache is config'ed off and turn into a function-pointer- | 
|  | 150 | compare-to-NULL if config'ed on but no backend claims the ops | 
|  | 151 | functions, or to a compare-struct-element-to-negative if a | 
|  | 152 | backend claims the ops functions but a filesystem doesn't enable | 
|  | 153 | cleancache. | 
|  | 154 |  | 
|  | 155 | Some filesystems are built entirely on top of VFS and the hooks | 
|  | 156 | in VFS are sufficient, so don't require an "init_fs" hook; the | 
|  | 157 | initial implementation of cleancache didn't provide this hook. | 
|  | 158 | But for some filesystems (such as btrfs), the VFS hooks are | 
|  | 159 | incomplete and one or more hooks in fs-specific code are required. | 
|  | 160 | And for some other filesystems, such as tmpfs, cleancache may | 
|  | 161 | be counterproductive.  So it seemed prudent to require a filesystem | 
|  | 162 | to "opt in" to use cleancache, which requires adding a hook in | 
|  | 163 | each filesystem.  Not all filesystems are supported by cleancache | 
|  | 164 | only because they haven't been tested.  The existing set should | 
|  | 165 | be sufficient to validate the concept, the opt-in approach means | 
|  | 166 | that untested filesystems are not affected, and the hooks in the | 
|  | 167 | existing filesystems should make it very easy to add more | 
|  | 168 | filesystems in the future. | 
|  | 169 |  | 
|  | 170 | The total impact of the hooks to existing fs and mm files is only | 
|  | 171 | about 40 lines added (not counting comments and blank lines). | 
|  | 172 |  | 
|  | 173 | 3) Why not make cleancache asynchronous and batched so it can | 
|  | 174 | more easily interface with real devices with DMA instead | 
|  | 175 | of copying each individual page? (Minchan Kim) | 
|  | 176 |  | 
|  | 177 | The one-page-at-a-time copy semantics simplifies the implementation | 
|  | 178 | on both the frontend and backend and also allows the backend to | 
|  | 179 | do fancy things on-the-fly like page compression and | 
|  | 180 | page deduplication.  And since the data is "gone" (copied into/out | 
|  | 181 | of the pageframe) before the cleancache get/put call returns, | 
|  | 182 | a great deal of race conditions and potential coherency issues | 
|  | 183 | are avoided.  While the interface seems odd for a "real device" | 
|  | 184 | or for real kernel-addressable RAM, it makes perfect sense for | 
|  | 185 | transcendent memory. | 
|  | 186 |  | 
|  | 187 | 4) Why is non-shared cleancache "exclusive"?  And where is the | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 188 | page "invalidated" after a "get"? (Minchan Kim) | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 189 |  | 
|  | 190 | The main reason is to free up space in transcendent memory and | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 191 | to avoid unnecessary cleancache_invalidate calls.  If you want inclusive, | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 192 | the page can be "put" immediately following the "get".  If | 
|  | 193 | put-after-get for inclusive becomes common, the interface could | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 194 | be easily extended to add a "get_no_invalidate" call. | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 195 |  | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 196 | The invalidate is done by the cleancache backend implementation. | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 197 |  | 
|  | 198 | 5) What's the performance impact? | 
|  | 199 |  | 
|  | 200 | Performance analysis has been presented at OLS'09 and LCA'10. | 
|  | 201 | Briefly, performance gains can be significant on most workloads, | 
|  | 202 | especially when memory pressure is high (e.g. when RAM is | 
|  | 203 | overcommitted in a virtual workload); and because the hooks are | 
|  | 204 | invoked primarily in place of or in addition to a disk read/write, | 
|  | 205 | overhead is negligible even in worst case workloads.  Basically | 
|  | 206 | cleancache replaces I/O with memory-copy-CPU-overhead; on older | 
|  | 207 | single-core systems with slow memory-copy speeds, cleancache | 
|  | 208 | has little value, but in newer multicore machines, especially | 
|  | 209 | consolidated/virtualized machines, it has great value. | 
|  | 210 |  | 
|  | 211 | 6) How do I add cleancache support for filesystem X? (Boaz Harrash) | 
|  | 212 |  | 
|  | 213 | Filesystems that are well-behaved and conform to certain | 
|  | 214 | restrictions can utilize cleancache simply by making a call to | 
|  | 215 | cleancache_init_fs at mount time.  Unusual, misbehaving, or | 
|  | 216 | poorly layered filesystems must either add additional hooks | 
|  | 217 | and/or undergo extensive additional testing... or should just | 
|  | 218 | not enable the optional cleancache. | 
|  | 219 |  | 
|  | 220 | Some points for a filesystem to consider: | 
|  | 221 |  | 
|  | 222 | - The FS should be block-device-based (e.g. a ram-based FS such | 
|  | 223 | as tmpfs should not enable cleancache) | 
|  | 224 | - To ensure coherency/correctness, the FS must ensure that all | 
|  | 225 | file removal or truncation operations either go through VFS or | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 226 | add hooks to do the equivalent cleancache "invalidate" operations | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 227 | - To ensure coherency/correctness, either inode numbers must | 
|  | 228 | be unique across the lifetime of the on-disk file OR the | 
|  | 229 | FS must provide an "encode_fh" function. | 
|  | 230 | - The FS must call the VFS superblock alloc and deactivate routines | 
|  | 231 | or add hooks to do the equivalent cleancache calls done there. | 
|  | 232 | - To maximize performance, all pages fetched from the FS should | 
|  | 233 | go through the do_mpag_readpage routine or the FS should add | 
|  | 234 | hooks to do the equivalent (cf. btrfs) | 
|  | 235 | - Currently, the FS blocksize must be the same as PAGESIZE.  This | 
|  | 236 | is not an architectural restriction, but no backends currently | 
|  | 237 | support anything different. | 
|  | 238 | - A clustered FS should invoke the "shared_init_fs" cleancache | 
|  | 239 | hook to get best performance for some backends. | 
|  | 240 |  | 
|  | 241 | 7) Why not use the KVA of the inode as the key? (Christoph Hellwig) | 
|  | 242 |  | 
|  | 243 | If cleancache would use the inode virtual address instead of | 
|  | 244 | inode/filehandle, the pool id could be eliminated.  But, this | 
|  | 245 | won't work because cleancache retains pagecache data pages | 
|  | 246 | persistently even when the inode has been pruned from the | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 247 | inode unused list, and only invalidates the data page if the file | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 248 | gets removed/truncated.  So if cleancache used the inode kva, | 
|  | 249 | there would be potential coherency issues if/when the inode | 
|  | 250 | kva is reused for a different file.  Alternately, if cleancache | 
| Dan Magenheimer | 3167760 | 2011-09-21 11:56:28 -0400 | [diff] [blame] | 251 | invalidated the pages when the inode kva was freed, much of the value | 
| Dan Magenheimer | 4fe4746 | 2011-05-26 10:00:56 -0600 | [diff] [blame] | 252 | of cleancache would be lost because the cache of pages in cleanache | 
|  | 253 | is potentially much larger than the kernel pagecache and is most | 
|  | 254 | useful if the pages survive inode cache removal. | 
|  | 255 |  | 
|  | 256 | 8) Why is a global variable required? | 
|  | 257 |  | 
|  | 258 | The cleancache_enabled flag is checked in all of the frequently-used | 
|  | 259 | cleancache hooks.  The alternative is a function call to check a static | 
|  | 260 | variable. Since cleancache is enabled dynamically at runtime, systems | 
|  | 261 | that don't enable cleancache would suffer thousands (possibly | 
|  | 262 | tens-of-thousands) of unnecessary function calls per second.  So the | 
|  | 263 | global variable allows cleancache to be enabled by default at compile | 
|  | 264 | time, but have insignificant performance impact when cleancache remains | 
|  | 265 | disabled at runtime. | 
|  | 266 |  | 
|  | 267 | 9) Does cleanache work with KVM? | 
|  | 268 |  | 
|  | 269 | The memory model of KVM is sufficiently different that a cleancache | 
|  | 270 | backend may have less value for KVM.  This remains to be tested, | 
|  | 271 | especially in an overcommitted system. | 
|  | 272 |  | 
|  | 273 | 10) Does cleancache work in userspace?  It sounds useful for | 
|  | 274 | memory hungry caches like web browsers.  (Jamie Lokier) | 
|  | 275 |  | 
|  | 276 | No plans yet, though we agree it sounds useful, at least for | 
|  | 277 | apps that bypass the page cache (e.g. O_DIRECT). | 
|  | 278 |  | 
|  | 279 | Last updated: Dan Magenheimer, April 13 2011 |