Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72c50887 authored by Peng Tao's avatar Peng Tao Committed by Trond Myklebust
Browse files

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: default avatarPeng Tao <peng_tao@emc.com>
Signed-off-by: default avatarBenny Halevy <bhalevy@tonian.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 60c52e3a
Loading
Loading
Loading
Loading
+54 −24
Original line number Diff line number Diff line
@@ -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);