drop_caches.c 1.3 KB

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