forked from Minki/linux
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:
parent
60c52e3a72
commit
72c5088799
@ -490,6 +490,55 @@ cleanup:
|
||||
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 @@ fill_invalid_ext:
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user