/** * invalidate_inode_pages2 - remove all unmapped pages from an address_space * @mapping - the address_space * * invalidate_inode_pages2() is like truncate_inode_pages(), except for the case * where the page is seen to be mapped into process pagetables. In that case, * the page is marked clean but is left attached to its address_space. * * The page is also marked not uptodate so that a subsequent pagefault will * perform I/O to bringthe page's contents back into sync with its backing * store. * * FIXME: invalidate_inode_pages2() is probably trivially livelockable. */ void invalidate_inode_pages2(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]; lock_page(page); if (page->mapping == mapping) { /* truncate race? */ wait_on_page_writeback(page); next = page->index + 1; if (page_mapped(page)) { clear_page_dirty(page); ClearPageUptodate(page); } else { if (!invalidate_complete_page(mapping, page)) { clear_page_dirty(page); ClearPageUptodate(page); } } } unlock_page(page); } pagevec_release(&pvec); cond_resched(); } }
static void unmap_buffers(struct page *page, loff_t pos) { struct buffer_head *bh ; struct buffer_head *head ; struct buffer_head *next ; unsigned long tail_index ; unsigned long cur_index ; if (page) { if (page_has_buffers(page)) { tail_index = pos & (PAGE_CACHE_SIZE - 1) ; cur_index = 0 ; head = page_buffers(page) ; bh = head ; do { next = bh->b_this_page ; /* we want to unmap the buffers that contain the tail, and ** all the buffers after it (since the tail must be at the ** end of the file). We don't want to unmap file data ** before the tail, since it might be dirty and waiting to ** reach disk */ cur_index += bh->b_size ; if (cur_index > tail_index) { reiserfs_unmap_buffer(bh) ; } bh = next ; } while (bh != head) ; if ( PAGE_SIZE == bh->b_size ) { clear_page_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(). * * 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 * its lock, b) when a concurrent invalidate_inode_pages got there first and * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space. */ static void truncate_complete_page(struct address_space *mapping, struct page *page) { if (page->mapping != mapping) return; if (PagePrivate(page)) do_invalidatepage(page, 0); clear_page_dirty(page); ClearPageUptodate(page); ClearPageMappedToDisk(page); remove_from_page_cache(page); page_cache_release(page); /* pagecache ref */ }
static int fuse_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) { int err; size_t nres; unsigned count = to - offset; struct inode *inode = page->mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); loff_t pos = page_offset(page) + offset; struct fuse_req *req; if (is_bad_inode(inode)) return -EIO; req = fuse_get_request(fc); if (!req) return -EINTR; req->num_pages = 1; req->pages[0] = page; req->page_offset = offset; nres = fuse_send_write(req, file, inode, pos, count); err = req->out.h.error; fuse_put_request(fc, req); if (!err && nres != count) err = -EIO; if (!err) { pos += count; if (pos > i_size_read(inode)) i_size_write(inode, pos); if (offset == 0 && to == PAGE_CACHE_SIZE) { clear_page_dirty(page); SetPageUptodate(page); } } fuse_invalidate_attr(inode); return err; }