diff options
author | Kevin | 2014-11-15 09:58:27 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 09:58:27 +0800 |
commit | 392e8802486cb573b916e746010e141a75f507e6 (patch) | |
tree | 50029aca02c81f087b90336e670b44e510782330 /ANDROID_3.4.5/fs/drop_caches.c | |
download | FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.tar.gz FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.tar.bz2 FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.zip |
init android origin source code
Diffstat (limited to 'ANDROID_3.4.5/fs/drop_caches.c')
-rw-r--r-- | ANDROID_3.4.5/fs/drop_caches.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/fs/drop_caches.c b/ANDROID_3.4.5/fs/drop_caches.c new file mode 100644 index 00000000..c00e055b --- /dev/null +++ b/ANDROID_3.4.5/fs/drop_caches.c @@ -0,0 +1,67 @@ +/* + * Implement the manual drop-all-pagecache function + */ + +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/fs.h> +#include <linux/writeback.h> +#include <linux/sysctl.h> +#include <linux/gfp.h> +#include "internal.h" + +/* A global variable is a bit ugly, but it keeps the code simple */ +int sysctl_drop_caches; + +static void drop_pagecache_sb(struct super_block *sb, void *unused) +{ + struct inode *inode, *toput_inode = NULL; + + spin_lock(&inode_sb_list_lock); + list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { + spin_lock(&inode->i_lock); + if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || + (inode->i_mapping->nrpages == 0)) { + spin_unlock(&inode->i_lock); + continue; + } + __iget(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&inode_sb_list_lock); + invalidate_mapping_pages(inode->i_mapping, 0, -1); + iput(toput_inode); + toput_inode = inode; + spin_lock(&inode_sb_list_lock); + } + spin_unlock(&inode_sb_list_lock); + iput(toput_inode); +} + +static void drop_slab(void) +{ + int nr_objects; + struct shrink_control shrink = { + .gfp_mask = GFP_KERNEL, + }; + + do { + nr_objects = shrink_slab(&shrink, 1000, 1000); + } while (nr_objects > 10); +} + +int drop_caches_sysctl_handler(ctl_table *table, int write, + void __user *buffer, size_t *length, loff_t *ppos) +{ + int ret; + + ret = proc_dointvec_minmax(table, write, buffer, length, ppos); + if (ret) + return ret; + if (write) { + if (sysctl_drop_caches & 1) + iterate_supers(drop_pagecache_sb, NULL); + if (sysctl_drop_caches & 2) + drop_slab(); + } + return 0; +} |