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) 16 { 17 struct inode *inode; 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_WILL_FREE)) 22 continue; 23 __invalidate_mapping_pages(inode->i_mapping, 0, -1, true); 24 } 25 spin_unlock(&inode_lock); 26 } 27 28 void drop_pagecache(void) 29 { 30 struct super_block *sb; 31 32 spin_lock(&sb_lock); 33 restart: 34 list_for_each_entry(sb, &super_blocks, s_list) { 35 sb->s_count++; 36 spin_unlock(&sb_lock); 37 down_read(&sb->s_umount); 38 if (sb->s_root) 39 drop_pagecache_sb(sb); 40 up_read(&sb->s_umount); 41 spin_lock(&sb_lock); 42 if (__put_super_and_need_restart(sb)) 43 goto restart; 44 } 45 spin_unlock(&sb_lock); 46 } 47 48 void drop_slab(void) 49 { 50 int nr_objects; 51 52 do { 53 nr_objects = shrink_slab(1000, GFP_KERNEL, 1000); 54 } while (nr_objects > 10); 55 } 56 57 int drop_caches_sysctl_handler(ctl_table *table, int write, 58 struct file *file, void __user *buffer, size_t *length, loff_t *ppos) 59 { 60 proc_dointvec_minmax(table, write, file, buffer, length, ppos); 61 if (write) { 62 if (sysctl_drop_caches & 1) 63 drop_pagecache(); 64 if (sysctl_drop_caches & 2) 65 drop_slab(); 66 } 67 return 0; 68 } 69