pnfsblock: move find lock page logic out of bl_write_pagelist

Also avoid unnecessary lock_page if page is handled by others.

Signed-off-by: Peng Tao <peng_tao@emc.com>
Signed-off-by: Benny Halevy <bhalevy@tonian.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Peng Tao 2012-01-12 23:18:42 +08:00 committed by Trond Myklebust
parent 60c52e3a72
commit 72c5088799

View File

@ -490,6 +490,55 @@ init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read)
return ret;
}
/* Find or create a zeroing page marked being writeback.
* Return ERR_PTR on error, NULL to indicate skip this page and page itself
* to indicate write out.
*/
static struct page *
bl_find_get_zeroing_page(struct inode *inode, pgoff_t index,
struct pnfs_block_extent *cow_read)
{
struct page *page;
int locked = 0;
page = find_get_page(inode->i_mapping, index);
if (page)
goto check_page;
page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
if (unlikely(!page)) {
dprintk("%s oom\n", __func__);
return ERR_PTR(-ENOMEM);
}
locked = 1;
check_page:
/* PageDirty: Other will write this out
* PageWriteback: Other is writing this out
* PageUptodate: It was read before
*/
if (PageDirty(page) || PageWriteback(page)) {
print_page(page);
if (locked)
unlock_page(page);
page_cache_release(page);
return NULL;
}
if (!locked) {
lock_page(page);
locked = 1;
goto check_page;
}
if (!PageUptodate(page)) {
/* New page, readin or zero it */
init_page_for_write(page, cow_read);
}
set_page_writeback(page);
unlock_page(page);
return page;
}
static enum pnfs_try_status
bl_write_pagelist(struct nfs_write_data *wdata, int sync)
{
@ -549,32 +598,13 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
dprintk("%s zero %dth page: index %lu isect %llu\n",
__func__, npg_zero, index,
(unsigned long long)isect);
page =
find_or_create_page(wdata->inode->i_mapping, index,
GFP_NOFS);
if (!page) {
dprintk("%s oom\n", __func__);
wdata->pnfs_error = -ENOMEM;
page = bl_find_get_zeroing_page(wdata->inode, index,
cow_read);
if (unlikely(IS_ERR(page))) {
wdata->pnfs_error = PTR_ERR(page);
goto out;
}
/* PageDirty: Other will write this out
* PageWriteback: Other is writing this out
* PageUptodate: It was read before
* sector_initialized: already written out
*/
if (PageDirty(page) || PageWriteback(page)) {
print_page(page);
unlock_page(page);
page_cache_release(page);
} else if (page == NULL)
goto next_page;
}
if (!PageUptodate(page)) {
/* New page, readin or zero it */
init_page_for_write(page, cow_read);
}
set_page_writeback(page);
unlock_page(page);
ret = bl_mark_sectors_init(be->be_inval, isect,
PAGE_CACHE_SECTORS);