]> git.neil.brown.name Git - history.git/commit
[PATCH] invalidate_inode_pages fixes
authorAndrew Morton <akpm@digeo.com>
Tue, 29 Oct 2002 00:22:13 +0000 (16:22 -0800)
committerJens Axboe <axboe@suse.de>
Tue, 29 Oct 2002 00:22:13 +0000 (16:22 -0800)
commitcaa2f8074a57dba5f7c8d3b7ad8db412ca54c3bc
tree5b087081d02b4e1e0497e95154c688adbb879ef6
parent303c9cf648d3e5f648afe89d624cc3e3c8d5ce71
[PATCH] invalidate_inode_pages fixes

Two fixes here.

First:

Fixes a BUG() which occurs if you try to perform O_DIRECT IO against a
blockdev which has an fs mounted on it.  (We should be able to do
that).

What happens is that do_invalidatepage() ends up calling
discard_buffer() on buffers which it couldn't strip.  That clears
buffer_mapped() against useful things like the superblock buffer_head.
The next submit_bh() goes BUG over the write of an unmapped buffer.

So just run try_to_release_page() (aka try_to_free_buffers()) on the
invalidate path.

Second:

The invalidate_inode_pages() functions are best-effort pagecache
shrinkers.  They are used against pages inside i_size and are not
supposed to throw away dirty data.

However it is possible for another CPU to run set_page_dirty() against
one of these pages after invalidate_inode_pages() has decided that it
is clean.  This could happen if someone was performing O_DIRECT IO
against a file which was also mapped with MAP_SHARED.

So recheck the dirty state of the page inside the mapping->page_lock
and back out if the page has just been marked dirty.

This will also prevent the remove_from_page_cache() BUG which will occur
if someone marks the page dirty between the clear_page_dirty() and
remove_from_page_cache() calls in truncate_complete_page().
mm/truncate.c