drop_caches.c 1.7 KB

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