Commit cad46d66 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] remove add_to_page_cache_unique()

A tasty patch from Hugh Dickens.  radix_tree_insert() fails if something
was already present at the target index, so that error can be
propagated back through add_to_page_cache().  Hence
add_to_page_cache_unique() is obsolete.

Hugh's patch removes add_to_page_cache_unique() and cleans up a bunch of
stuff.
parent e3339bee
...@@ -268,7 +268,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, ...@@ -268,7 +268,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
prefetchw(&page->flags); prefetchw(&page->flags);
list_del(&page->list); list_del(&page->list);
if (!add_to_page_cache_unique(page, mapping, page->index)) if (!add_to_page_cache(page, mapping, page->index))
bio = do_mpage_readpage(bio, page, bio = do_mpage_readpage(bio, page,
nr_pages - page_idx, nr_pages - page_idx,
&last_block_in_bio, get_block); &last_block_in_bio, get_block);
......
...@@ -52,8 +52,6 @@ extern struct page * read_cache_page(struct address_space *mapping, ...@@ -52,8 +52,6 @@ extern struct page * read_cache_page(struct address_space *mapping,
extern int add_to_page_cache(struct page *page, extern int add_to_page_cache(struct page *page,
struct address_space *mapping, unsigned long index); struct address_space *mapping, unsigned long index);
extern int add_to_page_cache_unique(struct page *page,
struct address_space *mapping, unsigned long index);
static inline void ___add_to_page_cache(struct page *page, static inline void ___add_to_page_cache(struct page *page,
struct address_space *mapping, unsigned long index) struct address_space *mapping, unsigned long index)
......
...@@ -520,8 +520,6 @@ int filemap_fdatawait(struct address_space * mapping) ...@@ -520,8 +520,6 @@ int filemap_fdatawait(struct address_space * mapping)
* This adds a page to the page cache, starting out as locked, unreferenced, * This adds a page to the page cache, starting out as locked, unreferenced,
* not uptodate and with no errors. * not uptodate and with no errors.
* *
* The caller must hold a write_lock on mapping->page_lock.
*
* This function is used for two things: adding newly allocated pagecache * This function is used for two things: adding newly allocated pagecache
* pages and for moving existing anon pages into swapcache. * pages and for moving existing anon pages into swapcache.
* *
...@@ -533,44 +531,20 @@ int filemap_fdatawait(struct address_space * mapping) ...@@ -533,44 +531,20 @@ int filemap_fdatawait(struct address_space * mapping)
* SetPageLocked() is ugly-but-OK there too. The required page state has been * SetPageLocked() is ugly-but-OK there too. The required page state has been
* set up by swap_out_add_to_swap_cache(). * set up by swap_out_add_to_swap_cache().
*/ */
static int __add_to_page_cache(struct page *page, int add_to_page_cache(struct page *page,
struct address_space *mapping, unsigned long offset) struct address_space *mapping, unsigned long offset)
{ {
if (radix_tree_insert(&mapping->page_tree, offset, page) == 0) { int error;
write_lock(&mapping->page_lock);
error = radix_tree_insert(&mapping->page_tree, offset, page);
if (!error) {
SetPageLocked(page); SetPageLocked(page);
ClearPageDirty(page); ClearPageDirty(page);
___add_to_page_cache(page, mapping, offset); ___add_to_page_cache(page, mapping, offset);
page_cache_get(page); page_cache_get(page);
return 0;
} }
return -ENOMEM;
}
int add_to_page_cache(struct page *page,
struct address_space *mapping, unsigned long offset)
{
write_lock(&mapping->page_lock);
if (__add_to_page_cache(page, mapping, offset) < 0)
goto nomem;
write_unlock(&mapping->page_lock);
lru_cache_add(page);
return 0;
nomem:
write_unlock(&mapping->page_lock);
return -ENOMEM;
}
int add_to_page_cache_unique(struct page *page,
struct address_space *mapping, unsigned long offset)
{
struct page *alias;
int error = -EEXIST;
write_lock(&mapping->page_lock);
if (!(alias = radix_tree_lookup(&mapping->page_tree, offset)))
error = __add_to_page_cache(page, mapping, offset);
write_unlock(&mapping->page_lock); write_unlock(&mapping->page_lock);
if (!error) if (!error)
lru_cache_add(page); lru_cache_add(page);
return error; return error;
...@@ -587,17 +561,11 @@ static int page_cache_read(struct file * file, unsigned long offset) ...@@ -587,17 +561,11 @@ static int page_cache_read(struct file * file, unsigned long offset)
struct page *page; struct page *page;
int error; int error;
read_lock(&mapping->page_lock);
page = radix_tree_lookup(&mapping->page_tree, offset);
read_unlock(&mapping->page_lock);
if (page)
return 0;
page = page_cache_alloc(mapping); page = page_cache_alloc(mapping);
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
error = add_to_page_cache_unique(page, mapping, offset); error = add_to_page_cache(page, mapping, offset);
if (!error) { if (!error) {
error = mapping->a_ops->readpage(file, page); error = mapping->a_ops->readpage(file, page);
page_cache_release(page); page_cache_release(page);
...@@ -759,28 +727,31 @@ struct page *find_trylock_page(struct address_space *mapping, unsigned long offs ...@@ -759,28 +727,31 @@ struct page *find_trylock_page(struct address_space *mapping, unsigned long offs
return page; return page;
} }
/* /**
* Must be called with the mapping lock held for writing. * find_lock_page - locate, pin and lock a pagecache page
* Will return with it held for writing, but it may be dropped *
* while locking the page. * @mapping - the address_space to search
* @offset - the page index
*
* Locates the desired pagecache page, locks it, increments its reference
* count and returns its address.
*
* Returns zero if the page was not present. find_lock_page() may sleep.
*/ */
static struct page *__find_lock_page(struct address_space *mapping, struct page *find_lock_page(struct address_space *mapping,
unsigned long offset) unsigned long offset)
{ {
struct page *page; struct page *page;
/* read_lock(&mapping->page_lock);
* We scan the hash list read-only. Addition to and removal from
* the hash-list needs a held write-lock.
*/
repeat: repeat:
page = radix_tree_lookup(&mapping->page_tree, offset); page = radix_tree_lookup(&mapping->page_tree, offset);
if (page) { if (page) {
page_cache_get(page); page_cache_get(page);
if (TestSetPageLocked(page)) { if (TestSetPageLocked(page)) {
write_unlock(&mapping->page_lock); read_unlock(&mapping->page_lock);
lock_page(page); lock_page(page);
write_lock(&mapping->page_lock); read_lock(&mapping->page_lock);
/* Has the page been truncated while we slept? */ /* Has the page been truncated while we slept? */
if (page->mapping != mapping || page->index != offset) { if (page->mapping != mapping || page->index != offset) {
...@@ -790,34 +761,7 @@ static struct page *__find_lock_page(struct address_space *mapping, ...@@ -790,34 +761,7 @@ static struct page *__find_lock_page(struct address_space *mapping,
} }
} }
} }
return page; read_unlock(&mapping->page_lock);
}
/**
* find_lock_page - locate, pin and lock a pagecache page
*
* @mapping - the address_space to search
* @offset - the page index
*
* Locates the desired pagecache page, locks it, increments its reference
* count and returns its address.
*
* Returns zero if the page was not present. find_lock_page() may sleep.
*/
/*
* The write_lock is unfortunate, but __find_lock_page() requires that on
* behalf of find_or_create_page(). We could just clone __find_lock_page() -
* one for find_lock_page(), one for find_or_create_page()...
*/
struct page *find_lock_page(struct address_space *mapping,
unsigned long offset)
{
struct page *page;
write_lock(&mapping->page_lock);
page = __find_lock_page(mapping, offset);
write_unlock(&mapping->page_lock);
return page; return page;
} }
...@@ -842,32 +786,25 @@ struct page *find_lock_page(struct address_space *mapping, ...@@ -842,32 +786,25 @@ struct page *find_lock_page(struct address_space *mapping,
struct page *find_or_create_page(struct address_space *mapping, struct page *find_or_create_page(struct address_space *mapping,
unsigned long index, unsigned int gfp_mask) unsigned long index, unsigned int gfp_mask)
{ {
struct page *page; struct page *page, *cached_page = NULL;
int err;
repeat:
page = find_lock_page(mapping, index); page = find_lock_page(mapping, index);
if (!page) { if (!page) {
struct page *newpage = alloc_page(gfp_mask); if (!cached_page) {
if (newpage) { cached_page = alloc_page(gfp_mask);
write_lock(&mapping->page_lock); if (!cached_page)
page = __find_lock_page(mapping, index); return NULL;
if (likely(!page)) {
page = newpage;
if (__add_to_page_cache(page, mapping, index)) {
write_unlock(&mapping->page_lock);
page_cache_release(page);
page = NULL;
goto out;
}
newpage = NULL;
}
write_unlock(&mapping->page_lock);
if (newpage == NULL)
lru_cache_add(page);
else
page_cache_release(newpage);
} }
err = add_to_page_cache(cached_page, mapping, index);
if (!err) {
page = cached_page;
cached_page = NULL;
} else if (err == -EEXIST)
goto repeat;
} }
out: if (cached_page)
page_cache_release(cached_page);
return page; return page;
} }
...@@ -901,7 +838,7 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) ...@@ -901,7 +838,7 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
return NULL; return NULL;
} }
page = alloc_pages(mapping->gfp_mask & ~__GFP_FS, 0); page = alloc_pages(mapping->gfp_mask & ~__GFP_FS, 0);
if (page && add_to_page_cache_unique(page, mapping, index)) { if (page && add_to_page_cache(page, mapping, index)) {
page_cache_release(page); page_cache_release(page);
page = NULL; page = NULL;
} }
...@@ -968,18 +905,16 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * ...@@ -968,18 +905,16 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
/* /*
* Try to find the data in the page cache.. * Try to find the data in the page cache..
*/ */
find_page:
write_lock(&mapping->page_lock); read_lock(&mapping->page_lock);
page = radix_tree_lookup(&mapping->page_tree, index); page = radix_tree_lookup(&mapping->page_tree, index);
if (!page) { if (!page) {
write_unlock(&mapping->page_lock); read_unlock(&mapping->page_lock);
handle_ra_thrashing(filp); handle_ra_thrashing(filp);
write_lock(&mapping->page_lock);
goto no_cached_page; goto no_cached_page;
} }
found_page:
page_cache_get(page); page_cache_get(page);
write_unlock(&mapping->page_lock); read_unlock(&mapping->page_lock);
if (!PageUptodate(page)) if (!PageUptodate(page))
goto page_not_up_to_date; goto page_not_up_to_date;
...@@ -1059,40 +994,23 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * ...@@ -1059,40 +994,23 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
/* /*
* Ok, it wasn't cached, so we need to create a new * Ok, it wasn't cached, so we need to create a new
* page.. * page..
*
* We get here with the page cache lock held.
*/ */
if (!cached_page) { if (!cached_page) {
write_unlock(&mapping->page_lock);
cached_page = page_cache_alloc(mapping); cached_page = page_cache_alloc(mapping);
if (!cached_page) { if (!cached_page) {
desc->error = -ENOMEM; desc->error = -ENOMEM;
break; break;
} }
/*
* Somebody may have added the page while we
* dropped the page cache lock. Check for that.
*/
write_lock(&mapping->page_lock);
page = radix_tree_lookup(&mapping->page_tree, index);
if (page)
goto found_page;
} }
error = add_to_page_cache(cached_page, mapping, index);
/* if (error) {
* Ok, add the new page to the hash-queues... if (error == -EEXIST)
*/ goto find_page;
if (__add_to_page_cache(cached_page, mapping, index) < 0) { desc->error = error;
write_unlock(&mapping->page_lock);
desc->error = -ENOMEM;
break; break;
} }
page = cached_page; page = cached_page;
write_unlock(&mapping->page_lock);
lru_cache_add(page);
cached_page = NULL; cached_page = NULL;
goto readpage; goto readpage;
} }
...@@ -1875,7 +1793,7 @@ struct page *__read_cache_page(struct address_space *mapping, ...@@ -1875,7 +1793,7 @@ struct page *__read_cache_page(struct address_space *mapping,
if (!cached_page) if (!cached_page)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
err = add_to_page_cache_unique(cached_page, mapping, index); err = add_to_page_cache(cached_page, mapping, index);
if (err == -EEXIST) if (err == -EEXIST)
goto repeat; goto repeat;
if (err < 0) { if (err < 0) {
...@@ -1948,7 +1866,7 @@ static inline struct page * __grab_cache_page(struct address_space *mapping, ...@@ -1948,7 +1866,7 @@ static inline struct page * __grab_cache_page(struct address_space *mapping,
if (!*cached_page) if (!*cached_page)
return NULL; return NULL;
} }
err = add_to_page_cache_unique(*cached_page, mapping, index); err = add_to_page_cache(*cached_page, mapping, index);
if (err == -EEXIST) if (err == -EEXIST)
goto repeat; goto repeat;
if (err == 0) { if (err == 0) {
......
...@@ -43,7 +43,7 @@ read_pages(struct file *file, struct address_space *mapping, ...@@ -43,7 +43,7 @@ read_pages(struct file *file, struct address_space *mapping,
for (page_idx = 0; page_idx < nr_pages; page_idx++) { for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, list); struct page *page = list_entry(pages->prev, struct page, list);
list_del(&page->list); list_del(&page->list);
if (!add_to_page_cache_unique(page, mapping, page->index)) if (!add_to_page_cache(page, mapping, page->index))
mapping->a_ops->readpage(file, page); mapping->a_ops->readpage(file, page);
page_cache_release(page); page_cache_release(page);
} }
......
...@@ -75,8 +75,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry) ...@@ -75,8 +75,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry)
INC_CACHE_INFO(noent_race); INC_CACHE_INFO(noent_race);
return -ENOENT; return -ENOENT;
} }
error = add_to_page_cache(page, &swapper_space, entry.val);
error = add_to_page_cache_unique(page, &swapper_space, entry.val);
if (error != 0) { if (error != 0) {
swap_free(entry); swap_free(entry);
if (error == -EEXIST) if (error == -EEXIST)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment