Skip to content

Commit

Permalink
Revert "ceph: don't truncate dirty pages in invalidate work thread"
Browse files Browse the repository at this point in the history
This reverts commit c9af9fb.

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 <[email protected]>
  • Loading branch information
liewegas committed Oct 25, 2011
1 parent 80db8be commit 83eaea2
Showing 1 changed file with 1 addition and 45 deletions.
46 changes: 1 addition & 45 deletions fs/ceph/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.)
Expand All @@ -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 &&
Expand Down

0 comments on commit 83eaea2

Please sign in to comment.