Cleancache: core ops functions and configuration
Subsystems (3)
PATCH v5 3/8 Cleancache: core ops functions and configuration
[PATCH V5 3/8] Cleancache: core ops functions and configuration
Cleancache core ops functions and configuration
Credits: Cleancache_ops design derived from Jeremy Fitzhardinge design for tmem; sysfs code modelled after mm/ksm.c
Note that CONFIG_CLEANCACHE defaults to on; all hooks devolve to a compare-function-pointer-to-NULL so performance impact should be negligible, but can be reduced to zero impact if config'ed off.
Signed-off-by Dan Magenheimer <[email protected]>
Diffstat:
include/linux/cleancache.h | 118 +++++++++ mm/Kconfig | 22 + mm/Makefile | 1 mm/cleancache.c | 258 +++++++++++++++++++++ 4 files changed, 399 insertions(+)
include/linux/cleancache.h +118 -0
@@ -0,0 +1,118 @@ +#ifndef _LINUX_CLEANCACHE_H +#define _LINUX_CLEANCACHE_H + +#include <linux/fs.h> +#include <linux/exportfs.h> +#include <linux/mm.h> + +#define CLEANCACHE_KEY_MAX 6 + +/* +* cleancache requires every file with a page in cleancache to have a +* unique key unless/until the file is removed/truncated. For some +* filesystems, the inode number is unique, but for "modern" filesystems +* an exportable filehandle is required (see exportfs.h) +*/ +struct cleancache_filekey { +union { +ino_t ino; +__u32 fh[CLEANCACHE_KEY_MAX ]; +u32 key[CLEANCACHE_KEY_MAX ]; + } u; +}; + +struct cleancache_ops { +int (*init_fs)(size_t ); +int (*init_shared_fs)(char *uuid,size_t ); +int (*get_page)(int ,struct cleancache_filekey , +pgoff_t ,struct page *); +void (*put_page)(int ,struct cleancache_filekey , +pgoff_t ,struct page *); +void (*flush_page)(int ,struct cleancache_filekey ,pgoff_t ); +void (*flush_inode)(int ,struct cleancache_filekey ); +void (*flush_fs)(int ); +}; + +extern struct cleancache_ops +cleancache_register_ops (struct cleancache_ops *ops); +extern void __cleancache_init_fs (struct super_block *); +extern void __cleancache_init_shared_fs (char *,struct super_block *); +extern int __cleancache_get_page (struct page *); +extern void __cleancache_put_page (struct page *); +extern void __cleancache_flush_page (struct address_space *,struct page *); +extern void __cleancache_flush_inode (struct address_space *); +extern void __cleancache_flush_fs (struct super_block *); +extern int cleancache_enabled; + +#ifdef CONFIG_CLEANCACHE +#define cleancache_fs_enabled (_page) \ + (_page->mapping->host->i_sb->cleancache_poolid >= 0) +#define cleancache_fs_enabled_mapping (_mapping) \ + (mapping->host->i_sb->cleancache_poolid >= 0) +#else +#define cleancache_enabled (0) +#define cleancache_fs_enabled (_page) (0) +#define cleancache_fs_enabled_mapping (_page) (0) +#endif + +/* +* The shim layer provided by these inline functions allows the compiler +* to reduce all cleancache hooks to nothingness if CONFIG_CLEANCACHE +* is disabled, to a single global variable check if CONFIG_CLEANCACHE +* is enabled but no cleancache "backend" has dynamically enabled it, +* and, for the most frequent cleancache ops, to a single global variable +* check plus a superblock element comparison if CONFIG_CLEANCACHE is enabled +* and a cleancache backend has dynamically enabled cleancache, but the +* filesystem referenced by that cleancache op has not enabled cleancache. +* As a result, CONFIG_CLEANCACHE can be enabled by default with essentially +* no measurable performance impact. +*/ + +static inline void cleancache_init_fs (struct super_block *sb) +{ +if (cleancache_enabled) +__cleancache_init_fs (sb); +} + +static inline void cleancache_init_shared_fs (char *uuid,struct super_block *sb) +{ +if (cleancache_enabled) +__cleancache_init_shared_fs (uuid, sb); +} + +static inline int cleancache_get_page (struct page *page) +{ +int ret =-1 ; + +if (cleancache_enabled &&cleancache_fs_enabled (page)) + ret =__cleancache_get_page (page); +return ret; +} + +static inline void cleancache_put_page (struct page *page) +{ +if (cleancache_enabled &&cleancache_fs_enabled (page)) +__cleancache_put_page (page); +} + +static inline void cleancache_flush_page (struct address_space *mapping, +struct page *page) +{ +/* careful... page->mapping is NULL sometimes when this is called */ +if (cleancache_enabled &&cleancache_fs_enabled_mapping (mapping)) +__cleancache_flush_page (mapping, page); +} + +static inline void cleancache_flush_inode (struct address_space *mapping) +{ +if (cleancache_enabled &&cleancache_fs_enabled_mapping (mapping)) +__cleancache_flush_inode (mapping); +} + +static inline void cleancache_flush_fs (struct super_block *sb) +{ +if (cleancache_enabled) +__cleancache_flush_fs (sb); +} + +#endif /* _LINUX_CLEANCACHE_H */
mm/cleancache.c +258 -0
258 lines not on this page · raw message
mm/Kconfig +22 -0
@@ -301,3 +301,25 @@ config NOMMU_INITIAL_TRIM_EXCESS of 1 says that all excess pages should be trimmed. See Documentation/nommu-mmap.txt for more information. + +config CLEANCACHE + bool "Enable cleancache pseudo-RAM driver to cache clean pages" + default y + help + Cleancache can be thought of as a page-granularity victim cache + for clean pages that the kernel's pageframe replacement algorithm + (PFRA) would like to keep around, but can't since there isn't enough + memory. So when the PFRA "evicts" a page, it first attempts to put + it into a synchronous concurrency-safe page-oriented pseudo-RAM + device (such as Xen's Transcendent Memory, aka "tmem") which is not + directly accessible or addressable by the kernel and is of unknown + (and possibly time-varying) size. And when a cleancache-enabled + filesystem wishes to access a page in a file on disk, it first + checks cleancache to see if it already contains it; if it does, + the page is copied into the kernel and a disk access is avoided. + When a pseudo-RAM device is available, a significant I/O reduction + may be achieved. When none is available, all cleancache calls + are reduced to a single pointer-compare-against-NULL resulting + in a negligible performance hit. + + If unsure, say Y to enable cleancache
mm/Makefile +1 -0
@@ -47,3 +47,4 @@ obj-$(CONFIG_MEMORY_FAILURE) += memory-f obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o +obj-$(CONFIG_CLEANCACHE) += cleancache.o