Commit 6e1db88d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro
Browse files

introduce __block_write_begin



Split up the block_write_begin implementation - __block_write_begin is a new
trivial wrapper for block_prepare_write that always takes an already
allocated page and can be either called from block_write_begin or filesystem
code that already has a page allocated.  Remove the handling of already
allocated pages from block_write_begin after switching all callers that
do it to __block_write_begin.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f4e420dc
Loading
Loading
Loading
Loading
+26 −43
Original line number Diff line number Diff line
@@ -1833,9 +1833,10 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
}
EXPORT_SYMBOL(page_zero_new_buffers);

static int __block_prepare_write(struct inode *inode, struct page *page,
		unsigned from, unsigned to, get_block_t *get_block)
int block_prepare_write(struct page *page, unsigned from, unsigned to,
		get_block_t *get_block)
{
	struct inode *inode = page->mapping->host;
	unsigned block_start, block_end;
	sector_t block;
	int err = 0;
@@ -1908,10 +1909,13 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
		if (!buffer_uptodate(*wait_bh))
			err = -EIO;
	}
	if (unlikely(err))
	if (unlikely(err)) {
		page_zero_new_buffers(page, from, to);
		ClearPageUptodate(page);
	}
	return err;
}
EXPORT_SYMBOL(block_prepare_write);

static int __block_commit_write(struct inode *inode, struct page *page,
		unsigned from, unsigned to)
@@ -1948,6 +1952,15 @@ static int __block_commit_write(struct inode *inode, struct page *page,
	return 0;
}

int __block_write_begin(struct page *page, loff_t pos, unsigned len,
		get_block_t *get_block)
{
	unsigned start = pos & (PAGE_CACHE_SIZE - 1);

	return block_prepare_write(page, start, start + len, get_block);
}
EXPORT_SYMBOL(__block_write_begin);

/*
 * Filesystems implementing the new truncate sequence should use the
 * _newtrunc postfix variant which won't incorrectly call vmtruncate.
@@ -1958,41 +1971,22 @@ int block_write_begin_newtrunc(struct file *file, struct address_space *mapping,
			struct page **pagep, void **fsdata,
			get_block_t *get_block)
{
	struct inode *inode = mapping->host;
	int status = 0;
	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
	struct page *page;
	pgoff_t index;
	unsigned start, end;
	int ownpage = 0;

	index = pos >> PAGE_CACHE_SHIFT;
	start = pos & (PAGE_CACHE_SIZE - 1);
	end = start + len;
	int status;

	page = *pagep;
	if (page == NULL) {
		ownpage = 1;
	page = grab_cache_page_write_begin(mapping, index, flags);
		if (!page) {
			status = -ENOMEM;
			goto out;
		}
		*pagep = page;
	} else
		BUG_ON(!PageLocked(page));
	if (!page)
		return -ENOMEM;

	status = __block_prepare_write(inode, page, start, end, get_block);
	status = __block_write_begin(page, pos, len, get_block);
	if (unlikely(status)) {
		ClearPageUptodate(page);

		if (ownpage) {
		unlock_page(page);
		page_cache_release(page);
			*pagep = NULL;
		}
		page = NULL;
	}

out:
	*pagep = page;
	return status;
}
EXPORT_SYMBOL(block_write_begin_newtrunc);
@@ -2379,17 +2373,6 @@ out:
}
EXPORT_SYMBOL(cont_write_begin);

int block_prepare_write(struct page *page, unsigned from, unsigned to,
			get_block_t *get_block)
{
	struct inode *inode = page->mapping->host;
	int err = __block_prepare_write(inode, page, from, to, get_block);
	if (err)
		ClearPageUptodate(page);
	return err;
}
EXPORT_SYMBOL(block_prepare_write);

int block_commit_write(struct page *page, unsigned from, unsigned to)
{
	struct inode *inode = page->mapping->host;
+1 −2
Original line number Diff line number Diff line
@@ -450,8 +450,7 @@ ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child)

static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{
	return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0,
					  &page, NULL, ext2_get_block);
	return __block_write_begin(page, pos, len, ext2_get_block);
}

/* Releases the page */
+1 −2
Original line number Diff line number Diff line
@@ -1196,8 +1196,7 @@ retry:
		ret = PTR_ERR(handle);
		goto out;
	}
	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
							ext3_get_block);
	ret = __block_write_begin(page, pos, len, ext3_get_block);
	if (ret)
		goto write_begin_failed;

+4 −7
Original line number Diff line number Diff line
@@ -1578,11 +1578,9 @@ retry:
	*pagep = page;

	if (ext4_should_dioread_nolock(inode))
		ret = block_write_begin(file, mapping, pos, len, flags, pagep,
				fsdata, ext4_get_block_write);
		ret = __block_write_begin(page, pos, len, ext4_get_block_write);
	else
		ret = block_write_begin(file, mapping, pos, len, flags, pagep,
				fsdata, ext4_get_block);
		ret = __block_write_begin(page, pos, len, ext4_get_block);

	if (!ret && ext4_should_journal_data(inode)) {
		ret = walk_page_buffers(handle, page_buffers(page),
@@ -1593,7 +1591,7 @@ retry:
		unlock_page(page);
		page_cache_release(page);
		/*
		 * block_write_begin may have instantiated a few blocks
		 * __block_write_begin may have instantiated a few blocks
		 * outside i_size.  Trim these off again. Don't need
		 * i_size_read because we hold i_mutex.
		 *
@@ -3185,8 +3183,7 @@ retry:
	}
	*pagep = page;

	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
				ext4_da_get_block_prep);
	ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep);
	if (ret < 0) {
		unlock_page(page);
		ext4_journal_stop(handle);
+1 −2
Original line number Diff line number Diff line
@@ -359,8 +359,7 @@ static int minix_readpage(struct file *file, struct page *page)

int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{
	return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0,
					  &page, NULL, minix_get_block);
	return __block_write_begin(page, pos, len, minix_get_block);
}

static int minix_write_begin(struct file *file, struct address_space *mapping,
Loading