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:
committed by
Trond Myklebust
parent
60c52e3a72
commit
72c5088799
@@ -490,6 +490,55 @@ cleanup:
|
|||||||
return ret;
|
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
|
static enum pnfs_try_status
|
||||||
bl_write_pagelist(struct nfs_write_data *wdata, int sync)
|
bl_write_pagelist(struct nfs_write_data *wdata, int sync)
|
||||||
{
|
{
|
||||||
@@ -549,32 +598,13 @@ fill_invalid_ext:
|
|||||||
dprintk("%s zero %dth page: index %lu isect %llu\n",
|
dprintk("%s zero %dth page: index %lu isect %llu\n",
|
||||||
__func__, npg_zero, index,
|
__func__, npg_zero, index,
|
||||||
(unsigned long long)isect);
|
(unsigned long long)isect);
|
||||||
page =
|
page = bl_find_get_zeroing_page(wdata->inode, index,
|
||||||
find_or_create_page(wdata->inode->i_mapping, index,
|
cow_read);
|
||||||
GFP_NOFS);
|
if (unlikely(IS_ERR(page))) {
|
||||||
if (!page) {
|
wdata->pnfs_error = PTR_ERR(page);
|
||||||
dprintk("%s oom\n", __func__);
|
|
||||||
wdata->pnfs_error = -ENOMEM;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
} else if (page == NULL)
|
||||||
|
|
||||||
/* 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);
|
|
||||||
goto next_page;
|
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,
|
ret = bl_mark_sectors_init(be->be_inval, isect,
|
||||||
PAGE_CACHE_SECTORS);
|
PAGE_CACHE_SECTORS);
|
||||||
|
Reference in New Issue
Block a user