X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=mm%2Ftruncate.c;h=c35c49e54fb6527eae91cb02177fc2b05a00abad;hb=bcf11cbeccd7d981d68567942ba6ec184890bc29;hp=7c994f2d614519df007e16eb93f1a8a393589a2e;hpb=02b2318e07f98a7cdf7089a4457a8d62424aa824;p=linux-2.6-block.git diff --git a/mm/truncate.c b/mm/truncate.c index 7c994f2d6145..c35c49e54fb6 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -20,7 +21,7 @@ /** - * do_invalidatepage - invalidate part of all of a page + * do_invalidatepage - invalidate part or all of a page * @page: the page which is affected * @offset: the index of the truncation point * @@ -47,7 +48,7 @@ void do_invalidatepage(struct page *page, unsigned long offset) static inline void truncate_partial_page(struct page *page, unsigned partial) { - zero_user_page(page, partial, PAGE_CACHE_SIZE - partial, KM_USER0); + zero_user_segment(page, partial, PAGE_CACHE_SIZE); if (PagePrivate(page)) do_invalidatepage(page, partial); } @@ -72,6 +73,8 @@ void cancel_dirty_page(struct page *page, unsigned int account_size) struct address_space *mapping = page->mapping; if (mapping && mapping_cap_account_dirty(mapping)) { dec_zone_page_state(page, NR_FILE_DIRTY); + dec_bdi_stat(mapping->backing_dev_info, + BDI_RECLAIMABLE); if (account_size) task_io_account_cancelled_write(account_size); } @@ -81,8 +84,8 @@ EXPORT_SYMBOL(cancel_dirty_page); /* * If truncate cannot remove the fs-private metadata from the page, the page - * becomes anonymous. It will be left on the LRU and may even be mapped into - * user pagetables if we're racing with filemap_nopage(). + * becomes orphaned. It will be left on the LRU and may even be mapped into + * user pagetables if we're racing with filemap_fault(). * * We need to bale out if page->mapping is no longer equal to the original * mapping. This happens a) when the VM reclaimed the page while we waited on @@ -95,14 +98,14 @@ truncate_complete_page(struct address_space *mapping, struct page *page) if (page->mapping != mapping) return; - cancel_dirty_page(page, PAGE_CACHE_SIZE); - if (PagePrivate(page)) do_invalidatepage(page, 0); + cancel_dirty_page(page, PAGE_CACHE_SIZE); + + remove_from_page_cache(page); ClearPageUptodate(page); ClearPageMappedToDisk(page); - remove_from_page_cache(page); page_cache_release(page); /* pagecache ref */ } @@ -192,6 +195,11 @@ void truncate_inode_pages_range(struct address_space *mapping, unlock_page(page); continue; } + if (page_mapped(page)) { + unmap_mapping_range(mapping, + (loff_t)page_index<index<index > next) next = page->index; next++; @@ -405,7 +418,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, break; } wait_on_page_writeback(page); - while (page_mapped(page)) { + if (page_mapped(page)) { if (!did_range_unmap) { /* * Zap the rest of the file in one hit. @@ -425,6 +438,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, PAGE_CACHE_SIZE, 0); } } + BUG_ON(page_mapped(page)); ret = do_launder_page(mapping, page); if (ret == 0 && !invalidate_complete_page2(mapping, page)) ret = -EIO;