vfs: keep inodes with page cache off the inode shrinker LRU
[sfrench/cifs-2.6.git] / fs / inode.c
index ed0cab8a32db109c6851ddcf567d8de83d1c5c22..a49695f57e1eaa2f047c93b77f40f9269ea32aa5 100644 (file)
@@ -428,11 +428,20 @@ void ihold(struct inode *inode)
 }
 EXPORT_SYMBOL(ihold);
 
-static void inode_lru_list_add(struct inode *inode)
+static void __inode_add_lru(struct inode *inode, bool rotate)
 {
+       if (inode->i_state & (I_DIRTY_ALL | I_SYNC | I_FREEING | I_WILL_FREE))
+               return;
+       if (atomic_read(&inode->i_count))
+               return;
+       if (!(inode->i_sb->s_flags & SB_ACTIVE))
+               return;
+       if (!mapping_shrinkable(&inode->i_data))
+               return;
+
        if (list_lru_add(&inode->i_sb->s_inode_lru, &inode->i_lru))
                this_cpu_inc(nr_unused);
-       else
+       else if (rotate)
                inode->i_state |= I_REFERENCED;
 }
 
@@ -443,16 +452,11 @@ static void inode_lru_list_add(struct inode *inode)
  */
 void inode_add_lru(struct inode *inode)
 {
-       if (!(inode->i_state & (I_DIRTY_ALL | I_SYNC |
-                               I_FREEING | I_WILL_FREE)) &&
-           !atomic_read(&inode->i_count) && inode->i_sb->s_flags & SB_ACTIVE)
-               inode_lru_list_add(inode);
+       __inode_add_lru(inode, false);
 }
 
-
 static void inode_lru_list_del(struct inode *inode)
 {
-
        if (list_lru_del(&inode->i_sb->s_inode_lru, &inode->i_lru))
                this_cpu_dec(nr_unused);
 }
@@ -728,10 +732,6 @@ again:
 /*
  * Isolate the inode from the LRU in preparation for freeing it.
  *
- * Any inodes which are pinned purely because of attached pagecache have their
- * pagecache removed.  If the inode has metadata buffers attached to
- * mapping->private_list then try to remove them.
- *
  * If the inode has the I_REFERENCED flag set, then it means that it has been
  * used recently - the flag is set in iput_final(). When we encounter such an
  * inode, clear the flag and move it to the back of the LRU so it gets another
@@ -747,31 +747,39 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
        struct inode    *inode = container_of(item, struct inode, i_lru);
 
        /*
-        * we are inverting the lru lock/inode->i_lock here, so use a trylock.
-        * If we fail to get the lock, just skip it.
+        * We are inverting the lru lock/inode->i_lock here, so use a
+        * trylock. If we fail to get the lock, just skip it.
         */
        if (!spin_trylock(&inode->i_lock))
                return LRU_SKIP;
 
        /*
-        * Referenced or dirty inodes are still in use. Give them another pass
-        * through the LRU as we canot reclaim them now.
+        * Inodes can get referenced, redirtied, or repopulated while
+        * they're already on the LRU, and this can make them
+        * unreclaimable for a while. Remove them lazily here; iput,
+        * sync, or the last page cache deletion will requeue them.
         */
        if (atomic_read(&inode->i_count) ||
-           (inode->i_state & ~I_REFERENCED)) {
+           (inode->i_state & ~I_REFERENCED) ||
+           !mapping_shrinkable(&inode->i_data)) {
                list_lru_isolate(lru, &inode->i_lru);
                spin_unlock(&inode->i_lock);
                this_cpu_dec(nr_unused);
                return LRU_REMOVED;
        }
 
-       /* recently referenced inodes get one more pass */
+       /* Recently referenced inodes get one more pass */
        if (inode->i_state & I_REFERENCED) {
                inode->i_state &= ~I_REFERENCED;
                spin_unlock(&inode->i_lock);
                return LRU_ROTATE;
        }
 
+       /*
+        * On highmem systems, mapping_shrinkable() permits dropping
+        * page cache in order to free up struct inodes: lowmem might
+        * be under pressure before the cache inside the highmem zone.
+        */
        if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) {
                __iget(inode);
                spin_unlock(&inode->i_lock);
@@ -1638,7 +1646,7 @@ static void iput_final(struct inode *inode)
        if (!drop &&
            !(inode->i_state & I_DONTCACHE) &&
            (sb->s_flags & SB_ACTIVE)) {
-               inode_add_lru(inode);
+               __inode_add_lru(inode, true);
                spin_unlock(&inode->i_lock);
                return;
        }