Commit b79a8408 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix the kupdate function

Juggle dirty pages and dirty inodes and dirty superblocks and various
different writeback modes and livelock avoidance and fairness to recover from
the loss of mapping->io_pages.
parent 1d7d3304
...@@ -147,12 +147,6 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) ...@@ -147,12 +147,6 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
inode->i_state |= I_LOCK; inode->i_state |= I_LOCK;
inode->i_state &= ~I_DIRTY; inode->i_state &= ~I_DIRTY;
/*
* smp_rmb(); note: if you remove write_lock below, you must add this.
* mark_inode_dirty doesn't take spinlock, make sure that inode is not
* read speculatively by this cpu before &= ~I_DIRTY -- mikulas
*/
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
ret = do_writepages(mapping, wbc); ret = do_writepages(mapping, wbc);
...@@ -170,18 +164,46 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) ...@@ -170,18 +164,46 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
spin_lock(&inode_lock); spin_lock(&inode_lock);
inode->i_state &= ~I_LOCK; inode->i_state &= ~I_LOCK;
if (!(inode->i_state & I_FREEING)) { if (!(inode->i_state & I_FREEING)) {
if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { if (!(inode->i_state & I_DIRTY) &&
/* Redirtied */ mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
inode->i_state |= I_DIRTY_PAGES; /*
inode->dirtied_when = jiffies; * We didn't write back all the pages. Redirty the
list_move(&inode->i_list, &sb->s_dirty); * inode. It is still on sb->s_dirty.
*/
if (wbc->for_kupdate) {
/*
* For the kupdate function we leave the inode
* where it is on sb_dirty so it will get more
* writeout as soon as the queue becomes
* uncongested.
*/
inode->i_state |= I_DIRTY_PAGES;
} else {
/*
* Otherwise fully redirty the inode so that
* other inodes on this superblock will get some
* writeout. Otherwise heavy writing to one
* file would indefinitely suspend writeout of
* all the other files.
*/
inode->i_state |= I_DIRTY_PAGES;
inode->dirtied_when = jiffies;
list_move(&inode->i_list, &sb->s_dirty);
}
} else if (inode->i_state & I_DIRTY) { } else if (inode->i_state & I_DIRTY) {
/* Redirtied */ /*
inode->dirtied_when = jiffies; * Someone redirtied the inode while were writing back
list_move(&inode->i_list, &sb->s_dirty); * the pages: nothing to do.
*/
} else if (atomic_read(&inode->i_count)) { } else if (atomic_read(&inode->i_count)) {
/*
* The inode is clean, inuse
*/
list_move(&inode->i_list, &inode_in_use); list_move(&inode->i_list, &inode_in_use);
} else { } else {
/*
* The inode is clean, unused
*/
list_move(&inode->i_list, &inode_unused); list_move(&inode->i_list, &inode_unused);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment