69 lines
		
	
	
	
		
			1.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			69 lines
		
	
	
	
		
			1.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * 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>
 | ||
|  | 
 | ||
|  | /* 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) | ||
|  | { | ||
|  | 	struct inode *inode; | ||
|  | 
 | ||
|  | 	spin_lock(&inode_lock); | ||
|  | 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | ||
|  | 		if (inode->i_state & (I_FREEING|I_WILL_FREE)) | ||
|  | 			continue; | ||
|  | 		invalidate_inode_pages(inode->i_mapping); | ||
|  | 	} | ||
|  | 	spin_unlock(&inode_lock); | ||
|  | } | ||
|  | 
 | ||
|  | void drop_pagecache(void) | ||
|  | { | ||
|  | 	struct super_block *sb; | ||
|  | 
 | ||
|  | 	spin_lock(&sb_lock); | ||
|  | restart: | ||
|  | 	list_for_each_entry(sb, &super_blocks, s_list) { | ||
|  | 		sb->s_count++; | ||
|  | 		spin_unlock(&sb_lock); | ||
|  | 		down_read(&sb->s_umount); | ||
|  | 		if (sb->s_root) | ||
|  | 			drop_pagecache_sb(sb); | ||
|  | 		up_read(&sb->s_umount); | ||
|  | 		spin_lock(&sb_lock); | ||
|  | 		if (__put_super_and_need_restart(sb)) | ||
|  | 			goto restart; | ||
|  | 	} | ||
|  | 	spin_unlock(&sb_lock); | ||
|  | } | ||
|  | 
 | ||
|  | void drop_slab(void) | ||
|  | { | ||
|  | 	int nr_objects; | ||
|  | 
 | ||
|  | 	do { | ||
|  | 		nr_objects = shrink_slab(1000, GFP_KERNEL, 1000); | ||
|  | 	} while (nr_objects > 10); | ||
|  | } | ||
|  | 
 | ||
|  | int drop_caches_sysctl_handler(ctl_table *table, int write, | ||
|  | 	struct file *file, void __user *buffer, size_t *length, loff_t *ppos) | ||
|  | { | ||
|  | 	proc_dointvec_minmax(table, write, file, buffer, length, ppos); | ||
|  | 	if (write) { | ||
|  | 		if (sysctl_drop_caches & 1) | ||
|  | 			drop_pagecache(); | ||
|  | 		if (sysctl_drop_caches & 2) | ||
|  | 			drop_slab(); | ||
|  | 	} | ||
|  | 	return 0; | ||
|  | } |