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

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
...@@ -1833,9 +1833,10 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to) ...@@ -1833,9 +1833,10 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
} }
EXPORT_SYMBOL(page_zero_new_buffers); EXPORT_SYMBOL(page_zero_new_buffers);
static int __block_prepare_write(struct inode *inode, struct page *page, int block_prepare_write(struct page *page, unsigned from, unsigned to,
unsigned from, unsigned to, get_block_t *get_block) get_block_t *get_block)
{ {
struct inode *inode = page->mapping->host;
unsigned block_start, block_end; unsigned block_start, block_end;
sector_t block; sector_t block;
int err = 0; int err = 0;
...@@ -1908,10 +1909,13 @@ static int __block_prepare_write(struct inode *inode, struct page *page, ...@@ -1908,10 +1909,13 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (!buffer_uptodate(*wait_bh)) if (!buffer_uptodate(*wait_bh))
err = -EIO; err = -EIO;
} }
if (unlikely(err)) if (unlikely(err)) {
page_zero_new_buffers(page, from, to); page_zero_new_buffers(page, from, to);
ClearPageUptodate(page);
}
return err; return err;
} }
EXPORT_SYMBOL(block_prepare_write);
static int __block_commit_write(struct inode *inode, struct page *page, static int __block_commit_write(struct inode *inode, struct page *page,
unsigned from, unsigned to) unsigned from, unsigned to)
...@@ -1948,6 +1952,15 @@ static int __block_commit_write(struct inode *inode, struct page *page, ...@@ -1948,6 +1952,15 @@ static int __block_commit_write(struct inode *inode, struct page *page,
return 0; 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 * Filesystems implementing the new truncate sequence should use the
* _newtrunc postfix variant which won't incorrectly call vmtruncate. * _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, ...@@ -1958,41 +1971,22 @@ int block_write_begin_newtrunc(struct file *file, struct address_space *mapping,
struct page **pagep, void **fsdata, struct page **pagep, void **fsdata,
get_block_t *get_block) get_block_t *get_block)
{ {
struct inode *inode = mapping->host; pgoff_t index = pos >> PAGE_CACHE_SHIFT;
int status = 0;
struct page *page; struct page *page;
pgoff_t index; int status;
unsigned start, end;
int ownpage = 0;
index = pos >> PAGE_CACHE_SHIFT; page = grab_cache_page_write_begin(mapping, index, flags);
start = pos & (PAGE_CACHE_SIZE - 1); if (!page)
end = start + len; return -ENOMEM;
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));
status = __block_prepare_write(inode, page, start, end, get_block); status = __block_write_begin(page, pos, len, get_block);
if (unlikely(status)) { if (unlikely(status)) {
ClearPageUptodate(page); unlock_page(page);
page_cache_release(page);
if (ownpage) { page = NULL;
unlock_page(page);
page_cache_release(page);
*pagep = NULL;
}
} }
out: *pagep = page;
return status; return status;
} }
EXPORT_SYMBOL(block_write_begin_newtrunc); EXPORT_SYMBOL(block_write_begin_newtrunc);
...@@ -2379,17 +2373,6 @@ int cont_write_begin(struct file *file, struct address_space *mapping, ...@@ -2379,17 +2373,6 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
} }
EXPORT_SYMBOL(cont_write_begin); 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) int block_commit_write(struct page *page, unsigned from, unsigned to)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
......
...@@ -450,8 +450,7 @@ ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child) ...@@ -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) static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{ {
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, return __block_write_begin(page, pos, len, ext2_get_block);
&page, NULL, ext2_get_block);
} }
/* Releases the page */ /* Releases the page */
......
...@@ -1196,8 +1196,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping, ...@@ -1196,8 +1196,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
ret = PTR_ERR(handle); ret = PTR_ERR(handle);
goto out; goto out;
} }
ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, ret = __block_write_begin(page, pos, len, ext3_get_block);
ext3_get_block);
if (ret) if (ret)
goto write_begin_failed; goto write_begin_failed;
......
...@@ -1578,11 +1578,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, ...@@ -1578,11 +1578,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
*pagep = page; *pagep = page;
if (ext4_should_dioread_nolock(inode)) if (ext4_should_dioread_nolock(inode))
ret = block_write_begin(file, mapping, pos, len, flags, pagep, ret = __block_write_begin(page, pos, len, ext4_get_block_write);
fsdata, ext4_get_block_write);
else else
ret = block_write_begin(file, mapping, pos, len, flags, pagep, ret = __block_write_begin(page, pos, len, ext4_get_block);
fsdata, ext4_get_block);
if (!ret && ext4_should_journal_data(inode)) { if (!ret && ext4_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page), ret = walk_page_buffers(handle, page_buffers(page),
...@@ -1593,7 +1591,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, ...@@ -1593,7 +1591,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
unlock_page(page); unlock_page(page);
page_cache_release(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 * outside i_size. Trim these off again. Don't need
* i_size_read because we hold i_mutex. * i_size_read because we hold i_mutex.
* *
...@@ -3185,8 +3183,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, ...@@ -3185,8 +3183,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
} }
*pagep = page; *pagep = page;
ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep);
ext4_da_get_block_prep);
if (ret < 0) { if (ret < 0) {
unlock_page(page); unlock_page(page);
ext4_journal_stop(handle); ext4_journal_stop(handle);
......
...@@ -359,8 +359,7 @@ static int minix_readpage(struct file *file, struct page *page) ...@@ -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) int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{ {
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, return __block_write_begin(page, pos, len, minix_get_block);
&page, NULL, minix_get_block);
} }
static int minix_write_begin(struct file *file, struct address_space *mapping, static int minix_write_begin(struct file *file, struct address_space *mapping,
......
...@@ -83,8 +83,7 @@ static unsigned nilfs_last_byte(struct inode *inode, unsigned long page_nr) ...@@ -83,8 +83,7 @@ static unsigned nilfs_last_byte(struct inode *inode, unsigned long page_nr)
static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to) static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to)
{ {
loff_t pos = page_offset(page) + from; loff_t pos = page_offset(page) + from;
return block_write_begin_newtrunc(NULL, page->mapping, pos, to - from, return __block_write_begin(page, pos, to - from, nilfs_get_block);
0, &page, NULL, nilfs_get_block);
} }
static void nilfs_commit_chunk(struct page *page, static void nilfs_commit_chunk(struct page *page,
......
...@@ -2585,8 +2585,7 @@ static int reiserfs_write_begin(struct file *file, ...@@ -2585,8 +2585,7 @@ static int reiserfs_write_begin(struct file *file,
old_ref = th->t_refcount; old_ref = th->t_refcount;
th->t_refcount++; th->t_refcount++;
} }
ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, ret = __block_write_begin(page, pos, len, reiserfs_get_block);
reiserfs_get_block);
if (ret && reiserfs_transaction_running(inode->i_sb)) { if (ret && reiserfs_transaction_running(inode->i_sb)) {
struct reiserfs_transaction_handle *th = current->journal_info; struct reiserfs_transaction_handle *th = current->journal_info;
/* this gets a little ugly. If reiserfs_get_block returned an /* this gets a little ugly. If reiserfs_get_block returned an
......
...@@ -461,8 +461,7 @@ static int sysv_readpage(struct file *file, struct page *page) ...@@ -461,8 +461,7 @@ static int sysv_readpage(struct file *file, struct page *page)
int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len) int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{ {
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, return __block_write_begin(page, pos, len, get_block);
&page, NULL, get_block);
} }
static int sysv_write_begin(struct file *file, struct address_space *mapping, static int sysv_write_begin(struct file *file, struct address_space *mapping,
......
...@@ -560,8 +560,7 @@ static int ufs_readpage(struct file *file, struct page *page) ...@@ -560,8 +560,7 @@ static int ufs_readpage(struct file *file, struct page *page)
int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len) int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
{ {
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, return __block_write_begin(page, pos, len, ufs_getfrag_block);
&page, NULL, ufs_getfrag_block);
} }
static int ufs_write_begin(struct file *file, struct address_space *mapping, static int ufs_write_begin(struct file *file, struct address_space *mapping,
......
...@@ -209,6 +209,8 @@ int block_write_begin_newtrunc(struct file *, struct address_space *, ...@@ -209,6 +209,8 @@ int block_write_begin_newtrunc(struct file *, struct address_space *,
int block_write_begin(struct file *, struct address_space *, int block_write_begin(struct file *, struct address_space *,
loff_t, unsigned, unsigned, loff_t, unsigned, unsigned,
struct page **, void **, get_block_t*); struct page **, void **, get_block_t*);
int __block_write_begin(struct page *page, loff_t pos, unsigned len,
get_block_t *get_block);
int block_write_end(struct file *, struct address_space *, int block_write_end(struct file *, struct address_space *,
loff_t, unsigned, unsigned, loff_t, unsigned, unsigned,
struct page *, void *); struct page *, void *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment