1 /* 2 * Implement the manual drop-all-pagecache function 3 */ 4 5 #include <linux/kernel.h> 6 #include <linux/mm.h> 7 #include <linux/fs.h> 8 #include <linux/writeback.h> 9 #include <linux/sysctl.h> 10 #include <linux/gfp.h> 11 12 /* A global variable is a bit ugly, but it keeps the code simple */ 13 int sysctl_drop_caches; 14 15 static void drop_pagecache_sb(struct super_block *sb, void *unused) 16 { 17 struct inode *inode, *toput_inode = NULL; 18 19 spin_lock(&inode_lock); 20 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 21 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) 22 continue; 23 if (inode->i_mapping->nrpages == 0) 24 continue; 25 __iget(inode); 26 spin_unlock(&inode_lock); 27 invalidate_mapping_pages(inode->i_mapping, 0, -1); 28 iput(toput_inode); 29 toput_inode = inode; 30 spin_lock(&inode_lock); 31 } 32 spin_unlock(&inode_lock); 33 iput(toput_inode); 34 } 35 36 static void drop_slab(void) 37 { 38 int nr_objects; 39 40 do { 41 nr_objects = shrink_slab(1000, GFP_KERNEL, 1000); 42 } while (nr_objects > 10); 43 } 44 45 int drop_caches_sysctl_handler(ctl_table *table, int write, 46 void __user *buffer, size_t *length, loff_t *ppos) 47 { 48 proc_dointvec_minmax(table, write, buffer, length, ppos); 49 if (write) { 50 if (sysctl_drop_caches & 1) 51 iterate_supers(drop_pagecache_sb, NULL); 52 if (sysctl_drop_caches & 2) 53 drop_slab(); 54 } 55 return 0; 56 } 57