Commit d7339071 authored by Hans Reiser's avatar Hans Reiser Committed by Linus Torvalds

[PATCH] reiser4: vfs: add truncate_inode_pages_range()

This patch makes truncate_inode_pages_range from truncate_inode_pages.
truncate_inode_pages became a one-liner call to truncate_inode_pages_range.

Reiser4 needs truncate_inode_pages_ranges because it tries to keep
correspondence between existences of metadata pointing to data pages and pages
to which those metadata point to.  So, when metadata of certain part of file
is removed from filesystem tree, only pages of corresponding range are to be
truncated.

(Needed by the madvise(MADV_REMOVE) patch)
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 900b2b46
No related merge requests found
...@@ -896,6 +896,8 @@ extern unsigned long do_brk(unsigned long, unsigned long); ...@@ -896,6 +896,8 @@ extern unsigned long do_brk(unsigned long, unsigned long);
/* filemap.c */ /* filemap.c */
extern unsigned long page_unuse(struct page *); extern unsigned long page_unuse(struct page *);
extern void truncate_inode_pages(struct address_space *, loff_t); extern void truncate_inode_pages(struct address_space *, loff_t);
extern void truncate_inode_pages_range(struct address_space *,
loff_t lstart, loff_t lend);
/* generic vm_area_ops exported for stackable file systems */ /* generic vm_area_ops exported for stackable file systems */
extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *); extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
......
...@@ -82,12 +82,15 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) ...@@ -82,12 +82,15 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
} }
/** /**
* truncate_inode_pages - truncate *all* the pages from an offset * truncate_inode_pages - truncate range of pages specified by start and
* end byte offsets
* @mapping: mapping to truncate * @mapping: mapping to truncate
* @lstart: offset from which to truncate * @lstart: offset from which to truncate
* @lend: offset to which to truncate
* *
* Truncate the page cache at a set offset, removing the pages that are beyond * Truncate the page cache, removing the pages that are between
* that offset (and zeroing out partial pages). * specified offsets (and zeroing out partial page
* (if lstart is not page aligned)).
* *
* Truncate takes two passes - the first pass is nonblocking. It will not * Truncate takes two passes - the first pass is nonblocking. It will not
* block on page locks and it will not block on writeback. The second pass * block on page locks and it will not block on writeback. The second pass
...@@ -101,12 +104,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) ...@@ -101,12 +104,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
* We pass down the cache-hot hint to the page freeing code. Even if the * We pass down the cache-hot hint to the page freeing code. Even if the
* mapping is large, it is probably the case that the final pages are the most * mapping is large, it is probably the case that the final pages are the most
* recently touched, and freeing happens in ascending file offset order. * recently touched, and freeing happens in ascending file offset order.
*
* Called under (and serialised by) inode->i_sem.
*/ */
void truncate_inode_pages(struct address_space *mapping, loff_t lstart) void truncate_inode_pages_range(struct address_space *mapping,
loff_t lstart, loff_t lend)
{ {
const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
pgoff_t end;
const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
struct pagevec pvec; struct pagevec pvec;
pgoff_t next; pgoff_t next;
...@@ -115,13 +118,22 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) ...@@ -115,13 +118,22 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
if (mapping->nrpages == 0) if (mapping->nrpages == 0)
return; return;
BUG_ON((lend & (PAGE_CACHE_SIZE - 1)) != (PAGE_CACHE_SIZE - 1));
end = (lend >> PAGE_CACHE_SHIFT);
pagevec_init(&pvec, 0); pagevec_init(&pvec, 0);
next = start; next = start;
while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { while (next <= end &&
pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
for (i = 0; i < pagevec_count(&pvec); i++) { for (i = 0; i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i]; struct page *page = pvec.pages[i];
pgoff_t page_index = page->index; pgoff_t page_index = page->index;
if (page_index > end) {
next = page_index;
break;
}
if (page_index > next) if (page_index > next)
next = page_index; next = page_index;
next++; next++;
...@@ -157,9 +169,15 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) ...@@ -157,9 +169,15 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
next = start; next = start;
continue; continue;
} }
if (pvec.pages[0]->index > end) {
pagevec_release(&pvec);
break;
}
for (i = 0; i < pagevec_count(&pvec); i++) { for (i = 0; i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i]; struct page *page = pvec.pages[i];
if (page->index > end)
break;
lock_page(page); lock_page(page);
wait_on_page_writeback(page); wait_on_page_writeback(page);
if (page->index > next) if (page->index > next)
...@@ -171,7 +189,19 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) ...@@ -171,7 +189,19 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
pagevec_release(&pvec); pagevec_release(&pvec);
} }
} }
EXPORT_SYMBOL(truncate_inode_pages_range);
/**
* truncate_inode_pages - truncate *all* the pages from an offset
* @mapping: mapping to truncate
* @lstart: offset from which to truncate
*
* Called under (and serialised by) inode->i_sem.
*/
void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
{
truncate_inode_pages_range(mapping, lstart, (loff_t)-1);
}
EXPORT_SYMBOL(truncate_inode_pages); EXPORT_SYMBOL(truncate_inode_pages);
/** /**
......
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