[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20101216220457.GA3450@barrios-desktop>
Date: Fri, 17 Dec 2010 07:04:57 +0900
From: Minchan Kim <minchan.kim@...il.com>
To: Miklos Szeredi <miklos@...redi.hu>
Cc: akpm@...ux-foundation.org, linux-fsdevel@...r.kernel.org,
linux-mm@...ck.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] mm: add replace_page_cache_page() function
On Thu, Dec 16, 2010 at 12:59:58PM +0100, Miklos Szeredi wrote:
> On Thu, 16 Dec 2010, Minchan Kim wrote:
> > > +int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
> > > +{
> > > + ?? ?? ?? int error;
> > > +
> > > + ?? ?? ?? VM_BUG_ON(!PageLocked(old));
> > > + ?? ?? ?? VM_BUG_ON(!PageLocked(new));
> > > + ?? ?? ?? VM_BUG_ON(new->mapping);
> > > +
> > > + ?? ?? ?? error = mem_cgroup_cache_charge(new, current->mm,
> > > + ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? gfp_mask & GFP_RECLAIM_MASK);
> > > + ?? ?? ?? if (error)
> > > + ?? ?? ?? ?? ?? ?? ?? goto out;
> > > +
> > > + ?? ?? ?? error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
> > > + ?? ?? ?? if (error == 0) {
> > > + ?? ?? ?? ?? ?? ?? ?? struct address_space *mapping = old->mapping;
> > > + ?? ?? ?? ?? ?? ?? ?? pgoff_t offset = old->index;
> > > +
> > > + ?? ?? ?? ?? ?? ?? ?? page_cache_get(new);
> > > + ?? ?? ?? ?? ?? ?? ?? new->mapping = mapping;
> > > + ?? ?? ?? ?? ?? ?? ?? new->index = offset;
> > > +
> > > + ?? ?? ?? ?? ?? ?? ?? spin_lock_irq(&mapping->tree_lock);
> > > + ?? ?? ?? ?? ?? ?? ?? __remove_from_page_cache(old);
> > > + ?? ?? ?? ?? ?? ?? ?? error = radix_tree_insert(&mapping->page_tree, offset, new);
> > > + ?? ?? ?? ?? ?? ?? ?? BUG_ON(error);
> > > + ?? ?? ?? ?? ?? ?? ?? mapping->nrpages++;
> > > + ?? ?? ?? ?? ?? ?? ?? __inc_zone_page_state(new, NR_FILE_PAGES);
> > > + ?? ?? ?? ?? ?? ?? ?? if (PageSwapBacked(new))
> > > + ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? __inc_zone_page_state(new, NR_SHMEM);
> > > + ?? ?? ?? ?? ?? ?? ?? spin_unlock_irq(&mapping->tree_lock);
> > > + ?? ?? ?? ?? ?? ?? ?? radix_tree_preload_end();
> > > + ?? ?? ?? ?? ?? ?? ?? mem_cgroup_uncharge_cache_page(old);
> > > + ?? ?? ?? ?? ?? ?? ?? page_cache_release(old);
> >
> > Why do you release reference of old?
>
> That's the page cache reference we release. Just like we acquire the
> page cache reference for "new" above.
I mean current page cache handling semantic and page reference counting semantic
is separeated. For example, remove_from_page_cache doesn't drop the reference of page.
That's because we need more works after drop the page from page cache.
Look at shmem_writepage, truncate_complete_page.
You makes the general API and caller might need works before the old page
is free. So how about this?
err = replace_page_cache_page(oldpage, newpage, GFP_KERNEL);
if (err) {
...
}
page_cache_release(oldpage); /* drop ref of page cache */
>
> I suspect it's historic that page_cache_release() doesn't drop the
> page cache ref.
Sorry I can't understand your words.
>
> Thanks for the review.
>
> Miklos
--
Kind regards,
Minchan Kim
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists