Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 69625
b: refs/heads/master
c: eb2be18
h: refs/heads/master
i:
  69623: 462d8a6
v: v3
  • Loading branch information
Nick Piggin authored and Linus Torvalds committed Oct 16, 2007
1 parent 3cd1b13 commit 8c0f42c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 113 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 64649a58919e66ec21792dbb6c48cb3da22cbd7f
refs/heads/master: eb2be189317d031895b5ca534fbf735eb546158b
10 changes: 2 additions & 8 deletions trunk/fs/mpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,31 +379,25 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
struct bio *bio = NULL;
unsigned page_idx;
sector_t last_block_in_bio = 0;
struct pagevec lru_pvec;
struct buffer_head map_bh;
unsigned long first_logical_block = 0;

clear_buffer_mapped(&map_bh);
pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, lru);

prefetchw(&page->flags);
list_del(&page->lru);
if (!add_to_page_cache(page, mapping,
if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
&last_block_in_bio, &map_bh,
&first_logical_block,
get_block);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
} else {
page_cache_release(page);
}
page_cache_release(page);
}
pagevec_lru_add(&lru_pvec);
BUG_ON(!list_empty(pages));
if (bio)
mpage_bio_submit(READ, bio);
Expand Down
143 changes: 55 additions & 88 deletions trunk/mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,27 +666,22 @@ EXPORT_SYMBOL(find_lock_page);
struct page *find_or_create_page(struct address_space *mapping,
pgoff_t index, gfp_t gfp_mask)
{
struct page *page, *cached_page = NULL;
struct page *page;
int err;
repeat:
page = find_lock_page(mapping, index);
if (!page) {
if (!cached_page) {
cached_page =
__page_cache_alloc(gfp_mask);
if (!cached_page)
return NULL;
page = __page_cache_alloc(gfp_mask);
if (!page)
return NULL;
err = add_to_page_cache_lru(page, mapping, index, gfp_mask);
if (unlikely(err)) {
page_cache_release(page);
page = NULL;
if (err == -EEXIST)
goto repeat;
}
err = add_to_page_cache_lru(cached_page, mapping,
index, gfp_mask);
if (!err) {
page = cached_page;
cached_page = NULL;
} else if (err == -EEXIST)
goto repeat;
}
if (cached_page)
page_cache_release(cached_page);
return page;
}
EXPORT_SYMBOL(find_or_create_page);
Expand Down Expand Up @@ -872,10 +867,8 @@ void do_generic_mapping_read(struct address_space *mapping,
pgoff_t prev_index;
unsigned long offset; /* offset into pagecache page */
unsigned int prev_offset;
struct page *cached_page;
int error;

cached_page = NULL;
index = *ppos >> PAGE_CACHE_SHIFT;
prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
Expand Down Expand Up @@ -1031,23 +1024,20 @@ void do_generic_mapping_read(struct address_space *mapping,
* Ok, it wasn't cached, so we need to create a new
* page..
*/
if (!cached_page) {
cached_page = page_cache_alloc_cold(mapping);
if (!cached_page) {
desc->error = -ENOMEM;
goto out;
}
page = page_cache_alloc_cold(mapping);
if (!page) {
desc->error = -ENOMEM;
goto out;
}
error = add_to_page_cache_lru(cached_page, mapping,
error = add_to_page_cache_lru(page, mapping,
index, GFP_KERNEL);
if (error) {
page_cache_release(page);
if (error == -EEXIST)
goto find_page;
desc->error = error;
goto out;
}
page = cached_page;
cached_page = NULL;
goto readpage;
}

Expand All @@ -1057,8 +1047,6 @@ void do_generic_mapping_read(struct address_space *mapping,
ra->prev_pos |= prev_offset;

*ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
if (filp)
file_accessed(filp);
}
Expand Down Expand Up @@ -1502,35 +1490,28 @@ static struct page *__read_cache_page(struct address_space *mapping,
int (*filler)(void *,struct page*),
void *data)
{
struct page *page, *cached_page = NULL;
struct page *page;
int err;
repeat:
page = find_get_page(mapping, index);
if (!page) {
if (!cached_page) {
cached_page = page_cache_alloc_cold(mapping);
if (!cached_page)
return ERR_PTR(-ENOMEM);
}
err = add_to_page_cache_lru(cached_page, mapping,
index, GFP_KERNEL);
if (err == -EEXIST)
goto repeat;
if (err < 0) {
page = page_cache_alloc_cold(mapping);
if (!page)
return ERR_PTR(-ENOMEM);
err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
if (unlikely(err)) {
page_cache_release(page);
if (err == -EEXIST)
goto repeat;
/* Presumably ENOMEM for radix tree node */
page_cache_release(cached_page);
return ERR_PTR(err);
}
page = cached_page;
cached_page = NULL;
err = filler(data, page);
if (err < 0) {
page_cache_release(page);
page = ERR_PTR(err);
}
}
if (cached_page)
page_cache_release(cached_page);
return page;
}

Expand Down Expand Up @@ -1606,40 +1587,6 @@ struct page *read_cache_page(struct address_space *mapping,
}
EXPORT_SYMBOL(read_cache_page);

/*
* If the page was newly created, increment its refcount and add it to the
* caller's lru-buffering pagevec. This function is specifically for
* generic_file_write().
*/
static inline struct page *
__grab_cache_page(struct address_space *mapping, unsigned long index,
struct page **cached_page, struct pagevec *lru_pvec)
{
int err;
struct page *page;
repeat:
page = find_lock_page(mapping, index);
if (!page) {
if (!*cached_page) {
*cached_page = page_cache_alloc(mapping);
if (!*cached_page)
return NULL;
}
err = add_to_page_cache(*cached_page, mapping,
index, GFP_KERNEL);
if (err == -EEXIST)
goto repeat;
if (err == 0) {
page = *cached_page;
page_cache_get(page);
if (!pagevec_add(lru_pvec, page))
__pagevec_lru_add(lru_pvec);
*cached_page = NULL;
}
}
return page;
}

/*
* The logic we want is
*
Expand Down Expand Up @@ -1832,6 +1779,33 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
}
EXPORT_SYMBOL(generic_file_direct_write);

/*
* Find or create a page at the given pagecache position. Return the locked
* page. This function is specifically for buffered writes.
*/
static struct page *__grab_cache_page(struct address_space *mapping,
pgoff_t index)
{
int status;
struct page *page;
repeat:
page = find_lock_page(mapping, index);
if (likely(page))
return page;

page = page_cache_alloc(mapping);
if (!page)
return NULL;
status = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
if (unlikely(status)) {
page_cache_release(page);
if (status == -EEXIST)
goto repeat;
return NULL;
}
return page;
}

ssize_t
generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos, loff_t *ppos,
Expand All @@ -1842,15 +1816,10 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
const struct address_space_operations *a_ops = mapping->a_ops;
struct inode *inode = mapping->host;
long status = 0;
struct page *page;
struct page *cached_page = NULL;
struct pagevec lru_pvec;
const struct iovec *cur_iov = iov; /* current iovec */
size_t iov_offset = 0; /* offset in the current iovec */
char __user *buf;

pagevec_init(&lru_pvec, 0);

/*
* handle partial DIO write. Adjust cur_iov if needed.
*/
Expand All @@ -1862,6 +1831,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
}

do {
struct page *page;
pgoff_t index; /* Pagecache index for current page */
unsigned long offset; /* Offset into pagecache page */
unsigned long maxlen; /* Bytes remaining in current iovec */
Expand All @@ -1888,7 +1858,8 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
fault_in_pages_readable(buf, maxlen);
#endif

page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);

page = __grab_cache_page(mapping, index);
if (!page) {
status = -ENOMEM;
break;
Expand Down Expand Up @@ -1956,9 +1927,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
} while (count);
*ppos = pos;

if (cached_page)
page_cache_release(cached_page);

/*
* For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
*/
Expand All @@ -1978,7 +1946,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
if (unlikely(file->f_flags & O_DIRECT) && written)
status = filemap_write_and_wait(mapping);

pagevec_lru_add(&lru_pvec);
return written ? written : status;
}
EXPORT_SYMBOL(generic_file_buffered_write);
Expand Down
24 changes: 8 additions & 16 deletions trunk/mm/readahead.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,25 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
int (*filler)(void *, struct page *), void *data)
{
struct page *page;
struct pagevec lru_pvec;
int ret = 0;

pagevec_init(&lru_pvec, 0);

while (!list_empty(pages)) {
page = list_to_page(pages);
list_del(&page->lru);
if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
if (add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
page_cache_release(page);
continue;
}
page_cache_release(page);

ret = filler(data, page);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
if (ret) {
if (unlikely(ret)) {
put_pages_list(pages);
break;
}
task_io_account_read(PAGE_CACHE_SIZE);
}
pagevec_lru_add(&lru_pvec);
return ret;
}

Expand All @@ -89,7 +86,6 @@ static int read_pages(struct address_space *mapping, struct file *filp,
struct list_head *pages, unsigned nr_pages)
{
unsigned page_idx;
struct pagevec lru_pvec;
int ret;

if (mapping->a_ops->readpages) {
Expand All @@ -99,19 +95,15 @@ static int read_pages(struct address_space *mapping, struct file *filp,
goto out;
}

pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
if (!add_to_page_cache(page, mapping,
if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
mapping->a_ops->readpage(filp, page);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
} else
page_cache_release(page);
}
page_cache_release(page);
}
pagevec_lru_add(&lru_pvec);
ret = 0;
out:
return ret;
Expand Down

0 comments on commit 8c0f42c

Please sign in to comment.