diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 22:52:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 22:52:47 -0400 |
commit | aab008db8063364dc3c8ccf4981c21124866b395 (patch) | |
tree | 72914203f4decb023efdaabd0301a62d742dfa8c | |
parent | 4f5b1affdda3e0c48cac674182f52004137b0ffc (diff) | |
parent | 16c0cfa425b8e1488f7a1873bd112a7a099325f0 (diff) |
Merge tag 'stable/for-linus-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm
Pull cleancache changes from Konrad Rzeszutek Wilk:
"This has some patches for the cleancache API that should have been
submitted a _long_ time ago. They are basically cleanups:
- rename of flush to invalidate
- moving reporting of statistics into debugfs
- use __read_mostly as necessary.
Oh, and also the MAINTAINERS file change. The files (except the
MAINTAINERS file) have been in #linux-next for months now. The late
addition of MAINTAINERS file is a brain-fart on my side - didn't
realize I needed that just until I was typing this up - and I based
that patch on v3.3 - so the tree is on top of v3.3."
* tag 'stable/for-linus-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm:
MAINTAINERS: Adding cleancache API to the list.
mm: cleancache: Use __read_mostly as appropiate.
mm: cleancache: report statistics via debugfs instead of sysfs.
mm: zcache/tmem/cleancache: s/flush/invalidate/
mm: cleancache: s/flush/invalidate/
-rw-r--r-- | Documentation/ABI/testing/sysfs-kernel-mm-cleancache | 11 | ||||
-rw-r--r-- | Documentation/vm/cleancache.txt | 41 | ||||
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/staging/zcache/zcache-main.c | 10 | ||||
-rw-r--r-- | drivers/xen/tmem.c | 10 | ||||
-rw-r--r-- | fs/block_dev.c | 2 | ||||
-rw-r--r-- | fs/super.c | 2 | ||||
-rw-r--r-- | include/linux/cleancache.h | 24 | ||||
-rw-r--r-- | mm/cleancache.c | 98 | ||||
-rw-r--r-- | mm/filemap.c | 2 | ||||
-rw-r--r-- | mm/truncate.c | 10 |
11 files changed, 96 insertions, 121 deletions
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-cleancache b/Documentation/ABI/testing/sysfs-kernel-mm-cleancache deleted file mode 100644 index 662ae646ea12..000000000000 --- a/Documentation/ABI/testing/sysfs-kernel-mm-cleancache +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | What: /sys/kernel/mm/cleancache/ | ||
2 | Date: April 2011 | ||
3 | Contact: Dan Magenheimer <dan.magenheimer@oracle.com> | ||
4 | Description: | ||
5 | /sys/kernel/mm/cleancache/ contains a number of files which | ||
6 | record a count of various cleancache operations | ||
7 | (sum across all filesystems): | ||
8 | succ_gets | ||
9 | failed_gets | ||
10 | puts | ||
11 | flushes | ||
diff --git a/Documentation/vm/cleancache.txt b/Documentation/vm/cleancache.txt index d5c615af10ba..142fbb0f325a 100644 --- a/Documentation/vm/cleancache.txt +++ b/Documentation/vm/cleancache.txt | |||
@@ -46,10 +46,11 @@ a negative return value indicates failure. A "put_page" will copy a | |||
46 | the pool id, a file key, and a page index into the file. (The combination | 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".) | 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. | 48 | A "get_page" will copy the page, if found, from cleancache into kernel memory. |
49 | A "flush_page" will ensure the page no longer is present in cleancache; | 49 | An "invalidate_page" will ensure the page no longer is present in cleancache; |
50 | a "flush_inode" will flush all pages associated with the specified file; | 50 | an "invalidate_inode" will invalidate all pages associated with the specified |
51 | and, when a filesystem is unmounted, a "flush_fs" will flush all pages in | 51 | file; and, when a filesystem is unmounted, an "invalidate_fs" will invalidate |
52 | all files specified by the given pool id and also surrender the pool id. | 52 | all pages in all files specified by the given pool id and also surrender |
53 | the pool id. | ||
53 | 54 | ||
54 | An "init_shared_fs", like init_fs, obtains a pool id but tells cleancache | 55 | An "init_shared_fs", like init_fs, obtains a pool id but tells cleancache |
55 | to treat the pool as shared using a 128-bit UUID as a key. On systems | 56 | to treat the pool as shared using a 128-bit UUID as a key. On systems |
@@ -62,12 +63,12 @@ of the kernel (e.g. by "tools" that control cleancache). Or a | |||
62 | cleancache implementation can simply disable shared_init by always | 63 | cleancache implementation can simply disable shared_init by always |
63 | returning a negative value. | 64 | returning a negative value. |
64 | 65 | ||
65 | If a get_page is successful on a non-shared pool, the page is flushed (thus | 66 | If a get_page is successful on a non-shared pool, the page is invalidated |
66 | making cleancache an "exclusive" cache). On a shared pool, the page | 67 | (thus making cleancache an "exclusive" cache). On a shared pool, the page |
67 | is NOT flushed on a successful get_page so that it remains accessible to | 68 | is NOT invalidated on a successful get_page so that it remains accessible to |
68 | other sharers. The kernel is responsible for ensuring coherency between | 69 | other sharers. The kernel is responsible for ensuring coherency between |
69 | cleancache (shared or not), the page cache, and the filesystem, using | 70 | cleancache (shared or not), the page cache, and the filesystem, using |
70 | cleancache flush operations as required. | 71 | cleancache invalidate operations as required. |
71 | 72 | ||
72 | Note that cleancache must enforce put-put-get coherency and get-get | 73 | Note that cleancache must enforce put-put-get coherency and get-get |
73 | coherency. For the former, if two puts are made to the same handle but | 74 | coherency. For the former, if two puts are made to the same handle but |
@@ -77,20 +78,20 @@ if a get for a given handle fails, subsequent gets for that handle will | |||
77 | never succeed unless preceded by a successful put with that handle. | 78 | never succeed unless preceded by a successful put with that handle. |
78 | 79 | ||
79 | Last, cleancache provides no SMP serialization guarantees; if two | 80 | Last, cleancache provides no SMP serialization guarantees; if two |
80 | different Linux threads are simultaneously putting and flushing a page | 81 | different Linux threads are simultaneously putting and invalidating a page |
81 | with the same handle, the results are indeterminate. Callers must | 82 | with the same handle, the results are indeterminate. Callers must |
82 | lock the page to ensure serial behavior. | 83 | lock the page to ensure serial behavior. |
83 | 84 | ||
84 | CLEANCACHE PERFORMANCE METRICS | 85 | CLEANCACHE PERFORMANCE METRICS |
85 | 86 | ||
86 | Cleancache monitoring is done by sysfs files in the | 87 | If properly configured, monitoring of cleancache is done via debugfs in |
87 | /sys/kernel/mm/cleancache directory. The effectiveness of cleancache | 88 | the /sys/kernel/debug/mm/cleancache directory. The effectiveness of cleancache |
88 | can be measured (across all filesystems) with: | 89 | can be measured (across all filesystems) with: |
89 | 90 | ||
90 | succ_gets - number of gets that were successful | 91 | succ_gets - number of gets that were successful |
91 | failed_gets - number of gets that failed | 92 | failed_gets - number of gets that failed |
92 | puts - number of puts attempted (all "succeed") | 93 | puts - number of puts attempted (all "succeed") |
93 | flushes - number of flushes attempted | 94 | invalidates - number of invalidates attempted |
94 | 95 | ||
95 | A backend implementation may provide additional metrics. | 96 | A backend implementation may provide additional metrics. |
96 | 97 | ||
@@ -143,7 +144,7 @@ systems. | |||
143 | 144 | ||
144 | The core hooks for cleancache in VFS are in most cases a single line | 145 | The core hooks for cleancache in VFS are in most cases a single line |
145 | and the minimum set are placed precisely where needed to maintain | 146 | and the minimum set are placed precisely where needed to maintain |
146 | coherency (via cleancache_flush operations) between cleancache, | 147 | coherency (via cleancache_invalidate operations) between cleancache, |
147 | the page cache, and disk. All hooks compile into nothingness if | 148 | the page cache, and disk. All hooks compile into nothingness if |
148 | cleancache is config'ed off and turn into a function-pointer- | 149 | cleancache is config'ed off and turn into a function-pointer- |
149 | compare-to-NULL if config'ed on but no backend claims the ops | 150 | compare-to-NULL if config'ed on but no backend claims the ops |
@@ -184,15 +185,15 @@ or for real kernel-addressable RAM, it makes perfect sense for | |||
184 | transcendent memory. | 185 | transcendent memory. |
185 | 186 | ||
186 | 4) Why is non-shared cleancache "exclusive"? And where is the | 187 | 4) Why is non-shared cleancache "exclusive"? And where is the |
187 | page "flushed" after a "get"? (Minchan Kim) | 188 | page "invalidated" after a "get"? (Minchan Kim) |
188 | 189 | ||
189 | The main reason is to free up space in transcendent memory and | 190 | The main reason is to free up space in transcendent memory and |
190 | to avoid unnecessary cleancache_flush calls. If you want inclusive, | 191 | to avoid unnecessary cleancache_invalidate calls. If you want inclusive, |
191 | the page can be "put" immediately following the "get". If | 192 | the page can be "put" immediately following the "get". If |
192 | put-after-get for inclusive becomes common, the interface could | 193 | put-after-get for inclusive becomes common, the interface could |
193 | be easily extended to add a "get_no_flush" call. | 194 | be easily extended to add a "get_no_invalidate" call. |
194 | 195 | ||
195 | The flush is done by the cleancache backend implementation. | 196 | The invalidate is done by the cleancache backend implementation. |
196 | 197 | ||
197 | 5) What's the performance impact? | 198 | 5) What's the performance impact? |
198 | 199 | ||
@@ -222,7 +223,7 @@ Some points for a filesystem to consider: | |||
222 | as tmpfs should not enable cleancache) | 223 | as tmpfs should not enable cleancache) |
223 | - To ensure coherency/correctness, the FS must ensure that all | 224 | - To ensure coherency/correctness, the FS must ensure that all |
224 | file removal or truncation operations either go through VFS or | 225 | file removal or truncation operations either go through VFS or |
225 | add hooks to do the equivalent cleancache "flush" operations | 226 | add hooks to do the equivalent cleancache "invalidate" operations |
226 | - To ensure coherency/correctness, either inode numbers must | 227 | - To ensure coherency/correctness, either inode numbers must |
227 | be unique across the lifetime of the on-disk file OR the | 228 | be unique across the lifetime of the on-disk file OR the |
228 | FS must provide an "encode_fh" function. | 229 | FS must provide an "encode_fh" function. |
@@ -243,11 +244,11 @@ If cleancache would use the inode virtual address instead of | |||
243 | inode/filehandle, the pool id could be eliminated. But, this | 244 | inode/filehandle, the pool id could be eliminated. But, this |
244 | won't work because cleancache retains pagecache data pages | 245 | won't work because cleancache retains pagecache data pages |
245 | persistently even when the inode has been pruned from the | 246 | persistently even when the inode has been pruned from the |
246 | inode unused list, and only flushes the data page if the file | 247 | inode unused list, and only invalidates the data page if the file |
247 | gets removed/truncated. So if cleancache used the inode kva, | 248 | gets removed/truncated. So if cleancache used the inode kva, |
248 | there would be potential coherency issues if/when the inode | 249 | there would be potential coherency issues if/when the inode |
249 | kva is reused for a different file. Alternately, if cleancache | 250 | kva is reused for a different file. Alternately, if cleancache |
250 | flushed the pages when the inode kva was freed, much of the value | 251 | invalidated the pages when the inode kva was freed, much of the value |
251 | of cleancache would be lost because the cache of pages in cleanache | 252 | of cleancache would be lost because the cache of pages in cleanache |
252 | is potentially much larger than the kernel pagecache and is most | 253 | is potentially much larger than the kernel pagecache and is most |
253 | useful if the pages survive inode cache removal. | 254 | useful if the pages survive inode cache removal. |
diff --git a/MAINTAINERS b/MAINTAINERS index 58f60356f071..922a674974a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1832,6 +1832,13 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) | |||
1832 | S: Supported | 1832 | S: Supported |
1833 | F: sound/soc/codecs/cs4270* | 1833 | F: sound/soc/codecs/cs4270* |
1834 | 1834 | ||
1835 | CLEANCACHE API | ||
1836 | M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | ||
1837 | L: linux-kernel@vger.kernel.org | ||
1838 | S: Maintained | ||
1839 | F: mm/cleancache.c | ||
1840 | F: include/linux/cleancache.h | ||
1841 | |||
1835 | CLK API | 1842 | CLK API |
1836 | M: Russell King <linux@arm.linux.org.uk> | 1843 | M: Russell King <linux@arm.linux.org.uk> |
1837 | F: include/linux/clk.h | 1844 | F: include/linux/clk.h |
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index ed2c800b3a7e..2734dacacbaf 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c | |||
@@ -1811,9 +1811,9 @@ static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) | |||
1811 | static struct cleancache_ops zcache_cleancache_ops = { | 1811 | static struct cleancache_ops zcache_cleancache_ops = { |
1812 | .put_page = zcache_cleancache_put_page, | 1812 | .put_page = zcache_cleancache_put_page, |
1813 | .get_page = zcache_cleancache_get_page, | 1813 | .get_page = zcache_cleancache_get_page, |
1814 | .flush_page = zcache_cleancache_flush_page, | 1814 | .invalidate_page = zcache_cleancache_flush_page, |
1815 | .flush_inode = zcache_cleancache_flush_inode, | 1815 | .invalidate_inode = zcache_cleancache_flush_inode, |
1816 | .flush_fs = zcache_cleancache_flush_fs, | 1816 | .invalidate_fs = zcache_cleancache_flush_fs, |
1817 | .init_shared_fs = zcache_cleancache_init_shared_fs, | 1817 | .init_shared_fs = zcache_cleancache_init_shared_fs, |
1818 | .init_fs = zcache_cleancache_init_fs | 1818 | .init_fs = zcache_cleancache_init_fs |
1819 | }; | 1819 | }; |
@@ -1921,8 +1921,8 @@ static void zcache_frontswap_init(unsigned ignored) | |||
1921 | static struct frontswap_ops zcache_frontswap_ops = { | 1921 | static struct frontswap_ops zcache_frontswap_ops = { |
1922 | .put_page = zcache_frontswap_put_page, | 1922 | .put_page = zcache_frontswap_put_page, |
1923 | .get_page = zcache_frontswap_get_page, | 1923 | .get_page = zcache_frontswap_get_page, |
1924 | .flush_page = zcache_frontswap_flush_page, | 1924 | .invalidate_page = zcache_frontswap_flush_page, |
1925 | .flush_area = zcache_frontswap_flush_area, | 1925 | .invalidate_area = zcache_frontswap_flush_area, |
1926 | .init = zcache_frontswap_init | 1926 | .init = zcache_frontswap_init |
1927 | }; | 1927 | }; |
1928 | 1928 | ||
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index d369965e8f8a..17d9e37beba4 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c | |||
@@ -242,9 +242,9 @@ __setup("nocleancache", no_cleancache); | |||
242 | static struct cleancache_ops tmem_cleancache_ops = { | 242 | static struct cleancache_ops tmem_cleancache_ops = { |
243 | .put_page = tmem_cleancache_put_page, | 243 | .put_page = tmem_cleancache_put_page, |
244 | .get_page = tmem_cleancache_get_page, | 244 | .get_page = tmem_cleancache_get_page, |
245 | .flush_page = tmem_cleancache_flush_page, | 245 | .invalidate_page = tmem_cleancache_flush_page, |
246 | .flush_inode = tmem_cleancache_flush_inode, | 246 | .invalidate_inode = tmem_cleancache_flush_inode, |
247 | .flush_fs = tmem_cleancache_flush_fs, | 247 | .invalidate_fs = tmem_cleancache_flush_fs, |
248 | .init_shared_fs = tmem_cleancache_init_shared_fs, | 248 | .init_shared_fs = tmem_cleancache_init_shared_fs, |
249 | .init_fs = tmem_cleancache_init_fs | 249 | .init_fs = tmem_cleancache_init_fs |
250 | }; | 250 | }; |
@@ -369,8 +369,8 @@ __setup("nofrontswap", no_frontswap); | |||
369 | static struct frontswap_ops tmem_frontswap_ops = { | 369 | static struct frontswap_ops tmem_frontswap_ops = { |
370 | .put_page = tmem_frontswap_put_page, | 370 | .put_page = tmem_frontswap_put_page, |
371 | .get_page = tmem_frontswap_get_page, | 371 | .get_page = tmem_frontswap_get_page, |
372 | .flush_page = tmem_frontswap_flush_page, | 372 | .invalidate_page = tmem_frontswap_flush_page, |
373 | .flush_area = tmem_frontswap_flush_area, | 373 | .invalidate_area = tmem_frontswap_flush_area, |
374 | .init = tmem_frontswap_init | 374 | .init = tmem_frontswap_init |
375 | }; | 375 | }; |
376 | #endif | 376 | #endif |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5e9f198f7712..a9ff3000b83d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -109,7 +109,7 @@ void invalidate_bdev(struct block_device *bdev) | |||
109 | /* 99% of the time, we don't need to flush the cleancache on the bdev. | 109 | /* 99% of the time, we don't need to flush the cleancache on the bdev. |
110 | * But, for the strange corners, lets be cautious | 110 | * But, for the strange corners, lets be cautious |
111 | */ | 111 | */ |
112 | cleancache_flush_inode(mapping); | 112 | cleancache_invalidate_inode(mapping); |
113 | } | 113 | } |
114 | EXPORT_SYMBOL(invalidate_bdev); | 114 | EXPORT_SYMBOL(invalidate_bdev); |
115 | 115 | ||
diff --git a/fs/super.c b/fs/super.c index d90e900a8a0e..7fcb1354c554 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -251,7 +251,7 @@ void deactivate_locked_super(struct super_block *s) | |||
251 | { | 251 | { |
252 | struct file_system_type *fs = s->s_type; | 252 | struct file_system_type *fs = s->s_type; |
253 | if (atomic_dec_and_test(&s->s_active)) { | 253 | if (atomic_dec_and_test(&s->s_active)) { |
254 | cleancache_flush_fs(s); | 254 | cleancache_invalidate_fs(s); |
255 | fs->kill_sb(s); | 255 | fs->kill_sb(s); |
256 | 256 | ||
257 | /* caches are now gone, we can safely kill the shrinker now */ | 257 | /* caches are now gone, we can safely kill the shrinker now */ |
diff --git a/include/linux/cleancache.h b/include/linux/cleancache.h index 04ffb2e6c9d0..42e55deee757 100644 --- a/include/linux/cleancache.h +++ b/include/linux/cleancache.h | |||
@@ -28,9 +28,9 @@ struct cleancache_ops { | |||
28 | pgoff_t, struct page *); | 28 | pgoff_t, struct page *); |
29 | void (*put_page)(int, struct cleancache_filekey, | 29 | void (*put_page)(int, struct cleancache_filekey, |
30 | pgoff_t, struct page *); | 30 | pgoff_t, struct page *); |
31 | void (*flush_page)(int, struct cleancache_filekey, pgoff_t); | 31 | void (*invalidate_page)(int, struct cleancache_filekey, pgoff_t); |
32 | void (*flush_inode)(int, struct cleancache_filekey); | 32 | void (*invalidate_inode)(int, struct cleancache_filekey); |
33 | void (*flush_fs)(int); | 33 | void (*invalidate_fs)(int); |
34 | }; | 34 | }; |
35 | 35 | ||
36 | extern struct cleancache_ops | 36 | extern struct cleancache_ops |
@@ -39,9 +39,9 @@ extern void __cleancache_init_fs(struct super_block *); | |||
39 | extern void __cleancache_init_shared_fs(char *, struct super_block *); | 39 | extern void __cleancache_init_shared_fs(char *, struct super_block *); |
40 | extern int __cleancache_get_page(struct page *); | 40 | extern int __cleancache_get_page(struct page *); |
41 | extern void __cleancache_put_page(struct page *); | 41 | extern void __cleancache_put_page(struct page *); |
42 | extern void __cleancache_flush_page(struct address_space *, struct page *); | 42 | extern void __cleancache_invalidate_page(struct address_space *, struct page *); |
43 | extern void __cleancache_flush_inode(struct address_space *); | 43 | extern void __cleancache_invalidate_inode(struct address_space *); |
44 | extern void __cleancache_flush_fs(struct super_block *); | 44 | extern void __cleancache_invalidate_fs(struct super_block *); |
45 | extern int cleancache_enabled; | 45 | extern int cleancache_enabled; |
46 | 46 | ||
47 | #ifdef CONFIG_CLEANCACHE | 47 | #ifdef CONFIG_CLEANCACHE |
@@ -99,24 +99,24 @@ static inline void cleancache_put_page(struct page *page) | |||
99 | __cleancache_put_page(page); | 99 | __cleancache_put_page(page); |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline void cleancache_flush_page(struct address_space *mapping, | 102 | static inline void cleancache_invalidate_page(struct address_space *mapping, |
103 | struct page *page) | 103 | struct page *page) |
104 | { | 104 | { |
105 | /* careful... page->mapping is NULL sometimes when this is called */ | 105 | /* careful... page->mapping is NULL sometimes when this is called */ |
106 | if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) | 106 | if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) |
107 | __cleancache_flush_page(mapping, page); | 107 | __cleancache_invalidate_page(mapping, page); |
108 | } | 108 | } |
109 | 109 | ||
110 | static inline void cleancache_flush_inode(struct address_space *mapping) | 110 | static inline void cleancache_invalidate_inode(struct address_space *mapping) |
111 | { | 111 | { |
112 | if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) | 112 | if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) |
113 | __cleancache_flush_inode(mapping); | 113 | __cleancache_invalidate_inode(mapping); |
114 | } | 114 | } |
115 | 115 | ||
116 | static inline void cleancache_flush_fs(struct super_block *sb) | 116 | static inline void cleancache_invalidate_fs(struct super_block *sb) |
117 | { | 117 | { |
118 | if (cleancache_enabled) | 118 | if (cleancache_enabled) |
119 | __cleancache_flush_fs(sb); | 119 | __cleancache_invalidate_fs(sb); |
120 | } | 120 | } |
121 | 121 | ||
122 | #endif /* _LINUX_CLEANCACHE_H */ | 122 | #endif /* _LINUX_CLEANCACHE_H */ |
diff --git a/mm/cleancache.c b/mm/cleancache.c index bcaae4c2a770..5646c740f613 100644 --- a/mm/cleancache.c +++ b/mm/cleancache.c | |||
@@ -15,29 +15,34 @@ | |||
15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
16 | #include <linux/exportfs.h> | 16 | #include <linux/exportfs.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/debugfs.h> | ||
18 | #include <linux/cleancache.h> | 19 | #include <linux/cleancache.h> |
19 | 20 | ||
20 | /* | 21 | /* |
21 | * This global enablement flag may be read thousands of times per second | 22 | * This global enablement flag may be read thousands of times per second |
22 | * by cleancache_get/put/flush even on systems where cleancache_ops | 23 | * by cleancache_get/put/invalidate even on systems where cleancache_ops |
23 | * is not claimed (e.g. cleancache is config'ed on but remains | 24 | * is not claimed (e.g. cleancache is config'ed on but remains |
24 | * disabled), so is preferred to the slower alternative: a function | 25 | * disabled), so is preferred to the slower alternative: a function |
25 | * call that checks a non-global. | 26 | * call that checks a non-global. |
26 | */ | 27 | */ |
27 | int cleancache_enabled; | 28 | int cleancache_enabled __read_mostly; |
28 | EXPORT_SYMBOL(cleancache_enabled); | 29 | EXPORT_SYMBOL(cleancache_enabled); |
29 | 30 | ||
30 | /* | 31 | /* |
31 | * cleancache_ops is set by cleancache_ops_register to contain the pointers | 32 | * cleancache_ops is set by cleancache_ops_register to contain the pointers |
32 | * to the cleancache "backend" implementation functions. | 33 | * to the cleancache "backend" implementation functions. |
33 | */ | 34 | */ |
34 | static struct cleancache_ops cleancache_ops; | 35 | static struct cleancache_ops cleancache_ops __read_mostly; |
35 | 36 | ||
36 | /* useful stats available in /sys/kernel/mm/cleancache */ | 37 | /* |
37 | static unsigned long cleancache_succ_gets; | 38 | * Counters available via /sys/kernel/debug/frontswap (if debugfs is |
38 | static unsigned long cleancache_failed_gets; | 39 | * properly configured. These are for information only so are not protected |
39 | static unsigned long cleancache_puts; | 40 | * against increment races. |
40 | static unsigned long cleancache_flushes; | 41 | */ |
42 | static u64 cleancache_succ_gets; | ||
43 | static u64 cleancache_failed_gets; | ||
44 | static u64 cleancache_puts; | ||
45 | static u64 cleancache_invalidates; | ||
41 | 46 | ||
42 | /* | 47 | /* |
43 | * register operations for cleancache, returning previous thus allowing | 48 | * register operations for cleancache, returning previous thus allowing |
@@ -148,10 +153,11 @@ void __cleancache_put_page(struct page *page) | |||
148 | EXPORT_SYMBOL(__cleancache_put_page); | 153 | EXPORT_SYMBOL(__cleancache_put_page); |
149 | 154 | ||
150 | /* | 155 | /* |
151 | * Flush any data from cleancache associated with the poolid and the | 156 | * Invalidate any data from cleancache associated with the poolid and the |
152 | * page's inode and page index so that a subsequent "get" will fail. | 157 | * page's inode and page index so that a subsequent "get" will fail. |
153 | */ | 158 | */ |
154 | void __cleancache_flush_page(struct address_space *mapping, struct page *page) | 159 | void __cleancache_invalidate_page(struct address_space *mapping, |
160 | struct page *page) | ||
155 | { | 161 | { |
156 | /* careful... page->mapping is NULL sometimes when this is called */ | 162 | /* careful... page->mapping is NULL sometimes when this is called */ |
157 | int pool_id = mapping->host->i_sb->cleancache_poolid; | 163 | int pool_id = mapping->host->i_sb->cleancache_poolid; |
@@ -160,85 +166,57 @@ void __cleancache_flush_page(struct address_space *mapping, struct page *page) | |||
160 | if (pool_id >= 0) { | 166 | if (pool_id >= 0) { |
161 | VM_BUG_ON(!PageLocked(page)); | 167 | VM_BUG_ON(!PageLocked(page)); |
162 | if (cleancache_get_key(mapping->host, &key) >= 0) { | 168 | if (cleancache_get_key(mapping->host, &key) >= 0) { |
163 | (*cleancache_ops.flush_page)(pool_id, key, page->index); | 169 | (*cleancache_ops.invalidate_page)(pool_id, |
164 | cleancache_flushes++; | 170 | key, page->index); |
171 | cleancache_invalidates++; | ||
165 | } | 172 | } |
166 | } | 173 | } |
167 | } | 174 | } |
168 | EXPORT_SYMBOL(__cleancache_flush_page); | 175 | EXPORT_SYMBOL(__cleancache_invalidate_page); |
169 | 176 | ||
170 | /* | 177 | /* |
171 | * Flush all data from cleancache associated with the poolid and the | 178 | * Invalidate all data from cleancache associated with the poolid and the |
172 | * mappings's inode so that all subsequent gets to this poolid/inode | 179 | * mappings's inode so that all subsequent gets to this poolid/inode |
173 | * will fail. | 180 | * will fail. |
174 | */ | 181 | */ |
175 | void __cleancache_flush_inode(struct address_space *mapping) | 182 | void __cleancache_invalidate_inode(struct address_space *mapping) |
176 | { | 183 | { |
177 | int pool_id = mapping->host->i_sb->cleancache_poolid; | 184 | int pool_id = mapping->host->i_sb->cleancache_poolid; |
178 | struct cleancache_filekey key = { .u.key = { 0 } }; | 185 | struct cleancache_filekey key = { .u.key = { 0 } }; |
179 | 186 | ||
180 | if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0) | 187 | if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0) |
181 | (*cleancache_ops.flush_inode)(pool_id, key); | 188 | (*cleancache_ops.invalidate_inode)(pool_id, key); |
182 | } | 189 | } |
183 | EXPORT_SYMBOL(__cleancache_flush_inode); | 190 | EXPORT_SYMBOL(__cleancache_invalidate_inode); |
184 | 191 | ||
185 | /* | 192 | /* |
186 | * Called by any cleancache-enabled filesystem at time of unmount; | 193 | * Called by any cleancache-enabled filesystem at time of unmount; |
187 | * note that pool_id is surrendered and may be reutrned by a subsequent | 194 | * note that pool_id is surrendered and may be reutrned by a subsequent |
188 | * cleancache_init_fs or cleancache_init_shared_fs | 195 | * cleancache_init_fs or cleancache_init_shared_fs |
189 | */ | 196 | */ |
190 | void __cleancache_flush_fs(struct super_block *sb) | 197 | void __cleancache_invalidate_fs(struct super_block *sb) |
191 | { | 198 | { |
192 | if (sb->cleancache_poolid >= 0) { | 199 | if (sb->cleancache_poolid >= 0) { |
193 | int old_poolid = sb->cleancache_poolid; | 200 | int old_poolid = sb->cleancache_poolid; |
194 | sb->cleancache_poolid = -1; | 201 | sb->cleancache_poolid = -1; |
195 | (*cleancache_ops.flush_fs)(old_poolid); | 202 | (*cleancache_ops.invalidate_fs)(old_poolid); |
196 | } | 203 | } |
197 | } | 204 | } |
198 | EXPORT_SYMBOL(__cleancache_flush_fs); | 205 | EXPORT_SYMBOL(__cleancache_invalidate_fs); |
199 | |||
200 | #ifdef CONFIG_SYSFS | ||
201 | |||
202 | /* see Documentation/ABI/xxx/sysfs-kernel-mm-cleancache */ | ||
203 | |||
204 | #define CLEANCACHE_SYSFS_RO(_name) \ | ||
205 | static ssize_t cleancache_##_name##_show(struct kobject *kobj, \ | ||
206 | struct kobj_attribute *attr, char *buf) \ | ||
207 | { \ | ||
208 | return sprintf(buf, "%lu\n", cleancache_##_name); \ | ||
209 | } \ | ||
210 | static struct kobj_attribute cleancache_##_name##_attr = { \ | ||
211 | .attr = { .name = __stringify(_name), .mode = 0444 }, \ | ||
212 | .show = cleancache_##_name##_show, \ | ||
213 | } | ||
214 | |||
215 | CLEANCACHE_SYSFS_RO(succ_gets); | ||
216 | CLEANCACHE_SYSFS_RO(failed_gets); | ||
217 | CLEANCACHE_SYSFS_RO(puts); | ||
218 | CLEANCACHE_SYSFS_RO(flushes); | ||
219 | |||
220 | static struct attribute *cleancache_attrs[] = { | ||
221 | &cleancache_succ_gets_attr.attr, | ||
222 | &cleancache_failed_gets_attr.attr, | ||
223 | &cleancache_puts_attr.attr, | ||
224 | &cleancache_flushes_attr.attr, | ||
225 | NULL, | ||
226 | }; | ||
227 | |||
228 | static struct attribute_group cleancache_attr_group = { | ||
229 | .attrs = cleancache_attrs, | ||
230 | .name = "cleancache", | ||
231 | }; | ||
232 | |||
233 | #endif /* CONFIG_SYSFS */ | ||
234 | 206 | ||
235 | static int __init init_cleancache(void) | 207 | static int __init init_cleancache(void) |
236 | { | 208 | { |
237 | #ifdef CONFIG_SYSFS | 209 | #ifdef CONFIG_DEBUG_FS |
238 | int err; | 210 | struct dentry *root = debugfs_create_dir("cleancache", NULL); |
239 | 211 | if (root == NULL) | |
240 | err = sysfs_create_group(mm_kobj, &cleancache_attr_group); | 212 | return -ENXIO; |
241 | #endif /* CONFIG_SYSFS */ | 213 | debugfs_create_u64("succ_gets", S_IRUGO, root, &cleancache_succ_gets); |
214 | debugfs_create_u64("failed_gets", S_IRUGO, | ||
215 | root, &cleancache_failed_gets); | ||
216 | debugfs_create_u64("puts", S_IRUGO, root, &cleancache_puts); | ||
217 | debugfs_create_u64("invalidates", S_IRUGO, | ||
218 | root, &cleancache_invalidates); | ||
219 | #endif | ||
242 | return 0; | 220 | return 0; |
243 | } | 221 | } |
244 | module_init(init_cleancache) | 222 | module_init(init_cleancache) |
diff --git a/mm/filemap.c b/mm/filemap.c index 843042045dc9..c3811bc6b9e3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -122,7 +122,7 @@ void __delete_from_page_cache(struct page *page) | |||
122 | if (PageUptodate(page) && PageMappedToDisk(page)) | 122 | if (PageUptodate(page) && PageMappedToDisk(page)) |
123 | cleancache_put_page(page); | 123 | cleancache_put_page(page); |
124 | else | 124 | else |
125 | cleancache_flush_page(mapping, page); | 125 | cleancache_invalidate_page(mapping, page); |
126 | 126 | ||
127 | radix_tree_delete(&mapping->page_tree, page->index); | 127 | radix_tree_delete(&mapping->page_tree, page->index); |
128 | page->mapping = NULL; | 128 | page->mapping = NULL; |
diff --git a/mm/truncate.c b/mm/truncate.c index a188058582e0..18aded3a89fc 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
@@ -52,7 +52,7 @@ void do_invalidatepage(struct page *page, unsigned long offset) | |||
52 | static inline void truncate_partial_page(struct page *page, unsigned partial) | 52 | static inline void truncate_partial_page(struct page *page, unsigned partial) |
53 | { | 53 | { |
54 | zero_user_segment(page, partial, PAGE_CACHE_SIZE); | 54 | zero_user_segment(page, partial, PAGE_CACHE_SIZE); |
55 | cleancache_flush_page(page->mapping, page); | 55 | cleancache_invalidate_page(page->mapping, page); |
56 | if (page_has_private(page)) | 56 | if (page_has_private(page)) |
57 | do_invalidatepage(page, partial); | 57 | do_invalidatepage(page, partial); |
58 | } | 58 | } |
@@ -213,7 +213,7 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
213 | pgoff_t end; | 213 | pgoff_t end; |
214 | int i; | 214 | int i; |
215 | 215 | ||
216 | cleancache_flush_inode(mapping); | 216 | cleancache_invalidate_inode(mapping); |
217 | if (mapping->nrpages == 0) | 217 | if (mapping->nrpages == 0) |
218 | return; | 218 | return; |
219 | 219 | ||
@@ -292,7 +292,7 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
292 | mem_cgroup_uncharge_end(); | 292 | mem_cgroup_uncharge_end(); |
293 | index++; | 293 | index++; |
294 | } | 294 | } |
295 | cleancache_flush_inode(mapping); | 295 | cleancache_invalidate_inode(mapping); |
296 | } | 296 | } |
297 | EXPORT_SYMBOL(truncate_inode_pages_range); | 297 | EXPORT_SYMBOL(truncate_inode_pages_range); |
298 | 298 | ||
@@ -444,7 +444,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
444 | int ret2 = 0; | 444 | int ret2 = 0; |
445 | int did_range_unmap = 0; | 445 | int did_range_unmap = 0; |
446 | 446 | ||
447 | cleancache_flush_inode(mapping); | 447 | cleancache_invalidate_inode(mapping); |
448 | pagevec_init(&pvec, 0); | 448 | pagevec_init(&pvec, 0); |
449 | index = start; | 449 | index = start; |
450 | while (index <= end && pagevec_lookup(&pvec, mapping, index, | 450 | while (index <= end && pagevec_lookup(&pvec, mapping, index, |
@@ -500,7 +500,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
500 | cond_resched(); | 500 | cond_resched(); |
501 | index++; | 501 | index++; |
502 | } | 502 | } |
503 | cleancache_flush_inode(mapping); | 503 | cleancache_invalidate_inode(mapping); |
504 | return ret; | 504 | return ret; |
505 | } | 505 | } |
506 | EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); | 506 | EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); |