The patch titled
Subject: writeback: put unused inodes to LRU after writeback completion
has been added to the -mm tree. Its filename is
writeback-put-unused-inodes-to-lru-after-writeback-completion.patch
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/SubmitChecklist when testing your code ***
The -mm tree is included into linux-next and is updated
there every 3-4 working days
------------------------------------------------------
From: Jan Kara <[email protected]>
Subject: writeback: put unused inodes to LRU after writeback completion
Commit 169ebd90 ("writeback: Avoid iput() from flusher thread") removed
iget-iput pair from inode writeback. As a side effect, inodes that are
dirty during iput_final() call won't be ever added to inode LRU
(iput_final() doesn't add dirty inodes to LRU and later when the inode is
cleaned there's noone to add the inode there). Thus inodes are
effectively unreclaimable until someone looks them up again.
Practical effect of this bug is limited by the fact that inodes are pinned
by a dentry for long enough that the inode gets cleaned. But still the
bug can have nasty consequences leading up to OOM conditions under certain
circumstances. Following can easily reproduce the problem:
for (( i = 0; i < 1000; i++ )); do
mkdir $i
for (( j = 0; j < 1000; j++ )); do
touch $i/$j
echo 2 > /proc/sys/vm/drop_caches
done
done
then one needs to run 'sync; ls -lR' to make inodes reclaimable again.
We fix the issue by inserting unused clean inodes into the LRU after
writeback finishes in inode_sync_complete().
Signed-off-by: Jan Kara <[email protected]>
Reported-by: OGAWA Hirofumi <[email protected]>
Cc: Al Viro <[email protected]>
Cc: OGAWA Hirofumi <[email protected]>
Cc: Wu Fengguang <[email protected]>
Cc: Dave Chinner <[email protected]>
Cc: <[email protected]> [3.5+]
Signed-off-by: Andrew Morton <[email protected]>
---
fs/fs-writeback.c | 2 ++
fs/inode.c | 16 ++++++++++++++--
fs/internal.h | 1 +
3 files changed, 17 insertions(+), 2 deletions(-)
diff -puN
fs/fs-writeback.c~writeback-put-unused-inodes-to-lru-after-writeback-completion
fs/fs-writeback.c
---
a/fs/fs-writeback.c~writeback-put-unused-inodes-to-lru-after-writeback-completion
+++ a/fs/fs-writeback.c
@@ -228,6 +228,8 @@ static void requeue_io(struct inode *ino
static void inode_sync_complete(struct inode *inode)
{
inode->i_state &= ~I_SYNC;
+ /* If inode is clean an unused, put it into LRU now... */
+ inode_add_lru(inode);
/* Waiters must see I_SYNC cleared before being woken up */
smp_mb();
wake_up_bit(&inode->i_state, __I_SYNC);
diff -puN
fs/inode.c~writeback-put-unused-inodes-to-lru-after-writeback-completion
fs/inode.c
--- a/fs/inode.c~writeback-put-unused-inodes-to-lru-after-writeback-completion
+++ a/fs/inode.c
@@ -408,6 +408,19 @@ static void inode_lru_list_add(struct in
spin_unlock(&inode->i_sb->s_inode_lru_lock);
}
+/*
+ * Add inode to LRU if needed (inode is unused and clean).
+ *
+ * Needs inode->i_lock held.
+ */
+void inode_add_lru(struct inode *inode)
+{
+ if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
+ !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+ inode_lru_list_add(inode);
+}
+
+
static void inode_lru_list_del(struct inode *inode)
{
spin_lock(&inode->i_sb->s_inode_lru_lock);
@@ -1390,8 +1403,7 @@ static void iput_final(struct inode *ino
if (!drop && (sb->s_flags & MS_ACTIVE)) {
inode->i_state |= I_REFERENCED;
- if (!(inode->i_state & (I_DIRTY|I_SYNC)))
- inode_lru_list_add(inode);
+ inode_add_lru(inode);
spin_unlock(&inode->i_lock);
return;
}
diff -puN
fs/internal.h~writeback-put-unused-inodes-to-lru-after-writeback-completion
fs/internal.h
---
a/fs/internal.h~writeback-put-unused-inodes-to-lru-after-writeback-completion
+++ a/fs/internal.h
@@ -110,6 +110,7 @@ extern int open_check_o_direct(struct fi
* inode.c
*/
extern spinlock_t inode_sb_list_lock;
+extern void inode_add_lru(struct inode *inode);
/*
* fs-writeback.c
_
Patches currently in -mm which might be from [email protected] are
origin.patch
linux-next.patch
writeback-put-unused-inodes-to-lru-after-writeback-completion.patch
fs-change-return-values-from-eacces-to-eperm.patch
mm-add-comment-on-storage-key-dirty-bit-semantics.patch
mm-print-out-information-of-file-affected-by-memory-error.patch
hfsplus-avoid-crash-on-failed-block-map-free.patch
hfsplus-add-on-disk-layout-declarations-related-to-attributes-tree.patch
hfsplus-add-functionality-of-manipulating-by-records-in-attributes-tree.patch
hfsplus-rework-functionality-of-getting-setting-and-deleting-of-extended-attributes.patch
hfsplus-add-support-of-manipulation-by-attributes-file.patch
fat-provide-option-for-setting-timezone-offset.patch
fat-fix-mount-option-parsing.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html