mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
Revert "ceph: don't truncate dirty pages in invalidate work thread"
This reverts commit c9af9fb68e
.
We need to block and truncate all pages in order to reliably invalidate
them. Otherwise, we could:
- have some uptodate pages in the cache
- queue an invalidate
- write(2) locks some pages
- invalidate_work skips them
- write(2) only overwrites part of the page
- page now dirty and uptodate
-> partial leakage of invalidated data
It's not entirely clear why we started skipping locked pages in the first
place. I just ran this through fsx and didn't see any problems.
Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
parent
80db8bea6a
commit
83eaea22bd
1 changed files with 1 additions and 45 deletions
|
@ -9,7 +9,6 @@
|
|||
#include <linux/namei.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pagevec.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "mds_client.h"
|
||||
|
@ -1363,49 +1362,6 @@ void ceph_queue_invalidate(struct inode *inode)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* invalidate any pages that are not dirty or under writeback. this
|
||||
* includes pages that are clean and mapped.
|
||||
*/
|
||||
static void ceph_invalidate_nondirty_pages(struct address_space *mapping)
|
||||
{
|
||||
struct pagevec pvec;
|
||||
pgoff_t next = 0;
|
||||
int i;
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
|
||||
for (i = 0; i < pagevec_count(&pvec); i++) {
|
||||
struct page *page = pvec.pages[i];
|
||||
pgoff_t index;
|
||||
int skip_page =
|
||||
(PageDirty(page) || PageWriteback(page));
|
||||
|
||||
if (!skip_page)
|
||||
skip_page = !trylock_page(page);
|
||||
|
||||
/*
|
||||
* We really shouldn't be looking at the ->index of an
|
||||
* unlocked page. But we're not allowed to lock these
|
||||
* pages. So we rely upon nobody altering the ->index
|
||||
* of this (pinned-by-us) page.
|
||||
*/
|
||||
index = page->index;
|
||||
if (index > next)
|
||||
next = index;
|
||||
next++;
|
||||
|
||||
if (skip_page)
|
||||
continue;
|
||||
|
||||
generic_error_remove_page(mapping, page);
|
||||
unlock_page(page);
|
||||
}
|
||||
pagevec_release(&pvec);
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalidate inode pages in a worker thread. (This can't be done
|
||||
* in the message handler context.)
|
||||
|
@ -1429,7 +1385,7 @@ static void ceph_invalidate_work(struct work_struct *work)
|
|||
orig_gen = ci->i_rdcache_gen;
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
ceph_invalidate_nondirty_pages(inode->i_mapping);
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (orig_gen == ci->i_rdcache_gen &&
|
||||
|
|
Loading…
Reference in a new issue