Skip to content

Commit

Permalink
Merge tag 'stable/for-linus-3.4' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/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/
  • Loading branch information
torvalds committed Mar 23, 2012
2 parents 4f5b1af + 16c0cfa commit aab008d
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 121 deletions.
11 changes: 0 additions & 11 deletions Documentation/ABI/testing/sysfs-kernel-mm-cleancache

This file was deleted.

41 changes: 21 additions & 20 deletions Documentation/vm/cleancache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ a negative return value indicates failure. A "put_page" will copy a
the pool id, a file key, and a page index into the file. (The combination
of a pool id, a file key, and an index is sometimes called a "handle".)
A "get_page" will copy the page, if found, from cleancache into kernel memory.
A "flush_page" will ensure the page no longer is present in cleancache;
a "flush_inode" will flush all pages associated with the specified file;
and, when a filesystem is unmounted, a "flush_fs" will flush all pages in
all files specified by the given pool id and also surrender the pool id.
An "invalidate_page" will ensure the page no longer is present in cleancache;
an "invalidate_inode" will invalidate all pages associated with the specified
file; and, when a filesystem is unmounted, an "invalidate_fs" will invalidate
all pages in all files specified by the given pool id and also surrender
the pool id.

An "init_shared_fs", like init_fs, obtains a pool id but tells cleancache
to treat the pool as shared using a 128-bit UUID as a key. On systems
Expand All @@ -62,12 +63,12 @@ of the kernel (e.g. by "tools" that control cleancache). Or a
cleancache implementation can simply disable shared_init by always
returning a negative value.

If a get_page is successful on a non-shared pool, the page is flushed (thus
making cleancache an "exclusive" cache). On a shared pool, the page
is NOT flushed on a successful get_page so that it remains accessible to
If a get_page is successful on a non-shared pool, the page is invalidated
(thus making cleancache an "exclusive" cache). On a shared pool, the page
is NOT invalidated on a successful get_page so that it remains accessible to
other sharers. The kernel is responsible for ensuring coherency between
cleancache (shared or not), the page cache, and the filesystem, using
cleancache flush operations as required.
cleancache invalidate operations as required.

Note that cleancache must enforce put-put-get coherency and get-get
coherency. For the former, if two puts are made to the same handle but
Expand All @@ -77,20 +78,20 @@ if a get for a given handle fails, subsequent gets for that handle will
never succeed unless preceded by a successful put with that handle.

Last, cleancache provides no SMP serialization guarantees; if two
different Linux threads are simultaneously putting and flushing a page
different Linux threads are simultaneously putting and invalidating a page
with the same handle, the results are indeterminate. Callers must
lock the page to ensure serial behavior.

CLEANCACHE PERFORMANCE METRICS

Cleancache monitoring is done by sysfs files in the
/sys/kernel/mm/cleancache directory. The effectiveness of cleancache
If properly configured, monitoring of cleancache is done via debugfs in
the /sys/kernel/debug/mm/cleancache directory. The effectiveness of cleancache
can be measured (across all filesystems) with:

succ_gets - number of gets that were successful
failed_gets - number of gets that failed
puts - number of puts attempted (all "succeed")
flushes - number of flushes attempted
invalidates - number of invalidates attempted

A backend implementation may provide additional metrics.

Expand Down Expand Up @@ -143,7 +144,7 @@ systems.

The core hooks for cleancache in VFS are in most cases a single line
and the minimum set are placed precisely where needed to maintain
coherency (via cleancache_flush operations) between cleancache,
coherency (via cleancache_invalidate operations) between cleancache,
the page cache, and disk. All hooks compile into nothingness if
cleancache is config'ed off and turn into a function-pointer-
compare-to-NULL if config'ed on but no backend claims the ops
Expand Down Expand Up @@ -184,15 +185,15 @@ or for real kernel-addressable RAM, it makes perfect sense for
transcendent memory.

4) Why is non-shared cleancache "exclusive"? And where is the
page "flushed" after a "get"? (Minchan Kim)
page "invalidated" after a "get"? (Minchan Kim)

The main reason is to free up space in transcendent memory and
to avoid unnecessary cleancache_flush calls. If you want inclusive,
to avoid unnecessary cleancache_invalidate calls. If you want inclusive,
the page can be "put" immediately following the "get". If
put-after-get for inclusive becomes common, the interface could
be easily extended to add a "get_no_flush" call.
be easily extended to add a "get_no_invalidate" call.

The flush is done by the cleancache backend implementation.
The invalidate is done by the cleancache backend implementation.

5) What's the performance impact?

Expand Down Expand Up @@ -222,7 +223,7 @@ Some points for a filesystem to consider:
as tmpfs should not enable cleancache)
- To ensure coherency/correctness, the FS must ensure that all
file removal or truncation operations either go through VFS or
add hooks to do the equivalent cleancache "flush" operations
add hooks to do the equivalent cleancache "invalidate" operations
- To ensure coherency/correctness, either inode numbers must
be unique across the lifetime of the on-disk file OR the
FS must provide an "encode_fh" function.
Expand All @@ -243,11 +244,11 @@ If cleancache would use the inode virtual address instead of
inode/filehandle, the pool id could be eliminated. But, this
won't work because cleancache retains pagecache data pages
persistently even when the inode has been pruned from the
inode unused list, and only flushes the data page if the file
inode unused list, and only invalidates the data page if the file
gets removed/truncated. So if cleancache used the inode kva,
there would be potential coherency issues if/when the inode
kva is reused for a different file. Alternately, if cleancache
flushed the pages when the inode kva was freed, much of the value
invalidated the pages when the inode kva was freed, much of the value
of cleancache would be lost because the cache of pages in cleanache
is potentially much larger than the kernel pagecache and is most
useful if the pages survive inode cache removal.
Expand Down
7 changes: 7 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1832,6 +1832,13 @@ L: [email protected] (moderated for non-subscribers)
S: Supported
F: sound/soc/codecs/cs4270*

CLEANCACHE API
M: Konrad Rzeszutek Wilk <[email protected]>
L: [email protected]
S: Maintained
F: mm/cleancache.c
F: include/linux/cleancache.h

CLK API
M: Russell King <[email protected]>
F: include/linux/clk.h
Expand Down
10 changes: 5 additions & 5 deletions drivers/staging/zcache/zcache-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1811,9 +1811,9 @@ static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
static struct cleancache_ops zcache_cleancache_ops = {
.put_page = zcache_cleancache_put_page,
.get_page = zcache_cleancache_get_page,
.flush_page = zcache_cleancache_flush_page,
.flush_inode = zcache_cleancache_flush_inode,
.flush_fs = zcache_cleancache_flush_fs,
.invalidate_page = zcache_cleancache_flush_page,
.invalidate_inode = zcache_cleancache_flush_inode,
.invalidate_fs = zcache_cleancache_flush_fs,
.init_shared_fs = zcache_cleancache_init_shared_fs,
.init_fs = zcache_cleancache_init_fs
};
Expand Down Expand Up @@ -1921,8 +1921,8 @@ static void zcache_frontswap_init(unsigned ignored)
static struct frontswap_ops zcache_frontswap_ops = {
.put_page = zcache_frontswap_put_page,
.get_page = zcache_frontswap_get_page,
.flush_page = zcache_frontswap_flush_page,
.flush_area = zcache_frontswap_flush_area,
.invalidate_page = zcache_frontswap_flush_page,
.invalidate_area = zcache_frontswap_flush_area,
.init = zcache_frontswap_init
};

Expand Down
10 changes: 5 additions & 5 deletions drivers/xen/tmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ __setup("nocleancache", no_cleancache);
static struct cleancache_ops tmem_cleancache_ops = {
.put_page = tmem_cleancache_put_page,
.get_page = tmem_cleancache_get_page,
.flush_page = tmem_cleancache_flush_page,
.flush_inode = tmem_cleancache_flush_inode,
.flush_fs = tmem_cleancache_flush_fs,
.invalidate_page = tmem_cleancache_flush_page,
.invalidate_inode = tmem_cleancache_flush_inode,
.invalidate_fs = tmem_cleancache_flush_fs,
.init_shared_fs = tmem_cleancache_init_shared_fs,
.init_fs = tmem_cleancache_init_fs
};
Expand Down Expand Up @@ -369,8 +369,8 @@ __setup("nofrontswap", no_frontswap);
static struct frontswap_ops tmem_frontswap_ops = {
.put_page = tmem_frontswap_put_page,
.get_page = tmem_frontswap_get_page,
.flush_page = tmem_frontswap_flush_page,
.flush_area = tmem_frontswap_flush_area,
.invalidate_page = tmem_frontswap_flush_page,
.invalidate_area = tmem_frontswap_flush_area,
.init = tmem_frontswap_init
};
#endif
Expand Down
2 changes: 1 addition & 1 deletion fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void invalidate_bdev(struct block_device *bdev)
/* 99% of the time, we don't need to flush the cleancache on the bdev.
* But, for the strange corners, lets be cautious
*/
cleancache_flush_inode(mapping);
cleancache_invalidate_inode(mapping);
}
EXPORT_SYMBOL(invalidate_bdev);

Expand Down
2 changes: 1 addition & 1 deletion fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ void deactivate_locked_super(struct super_block *s)
{
struct file_system_type *fs = s->s_type;
if (atomic_dec_and_test(&s->s_active)) {
cleancache_flush_fs(s);
cleancache_invalidate_fs(s);
fs->kill_sb(s);

/* caches are now gone, we can safely kill the shrinker now */
Expand Down
24 changes: 12 additions & 12 deletions include/linux/cleancache.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ struct cleancache_ops {
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);
void (*invalidate_page)(int, struct cleancache_filekey, pgoff_t);
void (*invalidate_inode)(int, struct cleancache_filekey);
void (*invalidate_fs)(int);
};

extern struct cleancache_ops
Expand All @@ -39,9 +39,9 @@ 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 void __cleancache_invalidate_page(struct address_space *, struct page *);
extern void __cleancache_invalidate_inode(struct address_space *);
extern void __cleancache_invalidate_fs(struct super_block *);
extern int cleancache_enabled;

#ifdef CONFIG_CLEANCACHE
Expand Down Expand Up @@ -99,24 +99,24 @@ static inline void cleancache_put_page(struct page *page)
__cleancache_put_page(page);
}

static inline void cleancache_flush_page(struct address_space *mapping,
static inline void cleancache_invalidate_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);
__cleancache_invalidate_page(mapping, page);
}

static inline void cleancache_flush_inode(struct address_space *mapping)
static inline void cleancache_invalidate_inode(struct address_space *mapping)
{
if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping))
__cleancache_flush_inode(mapping);
__cleancache_invalidate_inode(mapping);
}

static inline void cleancache_flush_fs(struct super_block *sb)
static inline void cleancache_invalidate_fs(struct super_block *sb)
{
if (cleancache_enabled)
__cleancache_flush_fs(sb);
__cleancache_invalidate_fs(sb);
}

#endif /* _LINUX_CLEANCACHE_H */
Loading

0 comments on commit aab008d

Please sign in to comment.