示例#1
0
/**
 * 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();
	}
}
示例#2
0
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);
      }
    }
  } 
}
示例#3
0
/*
 * 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 */
}
示例#4
0
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;
}