root/fs/drop_caches.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. drop_pagecache_sb
  2. drop_caches_sysctl_handler

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Implement the manual drop-all-pagecache function
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/mm.h>
   8 #include <linux/fs.h>
   9 #include <linux/writeback.h>
  10 #include <linux/sysctl.h>
  11 #include <linux/gfp.h>
  12 #include "internal.h"
  13 
  14 /* A global variable is a bit ugly, but it keeps the code simple */
  15 int sysctl_drop_caches;
  16 
  17 static void drop_pagecache_sb(struct super_block *sb, void *unused)
  18 {
  19         struct inode *inode, *toput_inode = NULL;
  20 
  21         spin_lock(&sb->s_inode_list_lock);
  22         list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
  23                 spin_lock(&inode->i_lock);
  24                 /*
  25                  * We must skip inodes in unusual state. We may also skip
  26                  * inodes without pages but we deliberately won't in case
  27                  * we need to reschedule to avoid softlockups.
  28                  */
  29                 if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
  30                     (inode->i_mapping->nrpages == 0 && !need_resched())) {
  31                         spin_unlock(&inode->i_lock);
  32                         continue;
  33                 }
  34                 __iget(inode);
  35                 spin_unlock(&inode->i_lock);
  36                 spin_unlock(&sb->s_inode_list_lock);
  37 
  38                 invalidate_mapping_pages(inode->i_mapping, 0, -1);
  39                 iput(toput_inode);
  40                 toput_inode = inode;
  41 
  42                 cond_resched();
  43                 spin_lock(&sb->s_inode_list_lock);
  44         }
  45         spin_unlock(&sb->s_inode_list_lock);
  46         iput(toput_inode);
  47 }
  48 
  49 int drop_caches_sysctl_handler(struct ctl_table *table, int write,
  50         void __user *buffer, size_t *length, loff_t *ppos)
  51 {
  52         int ret;
  53 
  54         ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
  55         if (ret)
  56                 return ret;
  57         if (write) {
  58                 static int stfu;
  59 
  60                 if (sysctl_drop_caches & 1) {
  61                         iterate_supers(drop_pagecache_sb, NULL);
  62                         count_vm_event(DROP_PAGECACHE);
  63                 }
  64                 if (sysctl_drop_caches & 2) {
  65                         drop_slab();
  66                         count_vm_event(DROP_SLAB);
  67                 }
  68                 if (!stfu) {
  69                         pr_info("%s (%d): drop_caches: %d\n",
  70                                 current->comm, task_pid_nr(current),
  71                                 sysctl_drop_caches);
  72                 }
  73                 stfu |= sysctl_drop_caches & 4;
  74         }
  75         return 0;
  76 }

/* [<][>][^][v][top][bottom][index][help] */