/** * nilfs_copy_back_pages -- copy back pages to original cache from shadow cache * @dmap: destination page cache * @smap: source page cache * * No pages must no be added to the cache during this process. * This must be ensured by the caller. */ void nilfs_copy_back_pages(struct address_space *dmap, struct address_space *smap) { struct pagevec pvec; unsigned int i, n; pgoff_t index = 0; int err; pagevec_init(&pvec); repeat: n = pagevec_lookup(&pvec, smap, &index); if (!n) return; for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i], *dpage; pgoff_t offset = page->index; lock_page(page); dpage = find_lock_page(dmap, offset); if (dpage) { /* override existing page on the destination cache */ WARN_ON(PageDirty(dpage)); nilfs_copy_page(dpage, page, 0); unlock_page(dpage); put_page(dpage); } else { struct page *page2; /* move the page to the destination cache */ spin_lock_irq(&smap->tree_lock); page2 = radix_tree_delete(&smap->page_tree, offset); WARN_ON(page2 != page); smap->nrpages--; spin_unlock_irq(&smap->tree_lock); spin_lock_irq(&dmap->tree_lock); err = radix_tree_insert(&dmap->page_tree, offset, page); if (unlikely(err < 0)) { WARN_ON(err == -EEXIST); page->mapping = NULL; put_page(page); /* for cache */ } else { page->mapping = dmap; dmap->nrpages++; if (PageDirty(page)) radix_tree_tag_set(&dmap->page_tree, offset, PAGECACHE_TAG_DIRTY); } spin_unlock_irq(&dmap->tree_lock); } unlock_page(page); } pagevec_release(&pvec); cond_resched(); goto repeat; }
int nilfs_copy_dirty_pages(struct address_space *dmap, struct address_space *smap) { struct pagevec pvec; unsigned int i; pgoff_t index = 0; int err = 0; pagevec_init(&pvec, 0); repeat: if (!pagevec_lookup_tag(&pvec, smap, &index, PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE)) return 0; for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i], *dpage; lock_page(page); if (unlikely(!PageDirty(page))) NILFS_PAGE_BUG(page, "inconsistent dirty state"); dpage = grab_cache_page(dmap, page->index); if (unlikely(!dpage)) { /* No empty page is added to the page cache */ err = -ENOMEM; unlock_page(page); break; } if (unlikely(!page_has_buffers(page))) NILFS_PAGE_BUG(page, "found empty page in dat page cache"); nilfs_copy_page(dpage, page, 1); __set_page_dirty_nobuffers(dpage); unlock_page(dpage); page_cache_release(dpage); unlock_page(page); } pagevec_release(&pvec); cond_resched(); if (likely(!err)) goto repeat; return err; }