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: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
f4e420dc42
commit
6e1db88d53
69
fs/buffer.c
69
fs/buffer.c
|
@ -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;
|
||||
int status;
|
||||
|
||||
index = pos >> PAGE_CACHE_SHIFT;
|
||||
start = pos & (PAGE_CACHE_SIZE - 1);
|
||||
end = start + len;
|
||||
page = grab_cache_page_write_begin(mapping, index, flags);
|
||||
if (!page)
|
||||
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)) {
|
||||
ClearPageUptodate(page);
|
||||
|
||||
if (ownpage) {
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
*pagep = NULL;
|
||||
}
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
page = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
*pagep = page;
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(block_write_begin_newtrunc);
|
||||
|
@ -2379,17 +2373,6 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
|
|||
}
|
||||
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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1196,8 +1196,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
|
|||
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;
|
||||
|
||||
|
|
|
@ -1578,11 +1578,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
|||
*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 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
|||
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 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
|
|||
}
|
||||
*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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
loff_t pos = page_offset(page) + from;
|
||||
return block_write_begin_newtrunc(NULL, page->mapping, pos, to - from,
|
||||
0, &page, NULL, nilfs_get_block);
|
||||
return __block_write_begin(page, pos, to - from, nilfs_get_block);
|
||||
}
|
||||
|
||||
static void nilfs_commit_chunk(struct page *page,
|
||||
|
|
|
@ -2585,8 +2585,7 @@ static int reiserfs_write_begin(struct file *file,
|
|||
old_ref = th->t_refcount;
|
||||
th->t_refcount++;
|
||||
}
|
||||
ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
reiserfs_get_block);
|
||||
ret = __block_write_begin(page, pos, len, reiserfs_get_block);
|
||||
if (ret && reiserfs_transaction_running(inode->i_sb)) {
|
||||
struct reiserfs_transaction_handle *th = current->journal_info;
|
||||
/* 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)
|
|||
|
||||
int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
{
|
||||
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0,
|
||||
&page, NULL, get_block);
|
||||
return __block_write_begin(page, pos, len, get_block);
|
||||
}
|
||||
|
||||
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)
|
|||
|
||||
int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
{
|
||||
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0,
|
||||
&page, NULL, ufs_getfrag_block);
|
||||
return __block_write_begin(page, pos, len, ufs_getfrag_block);
|
||||
}
|
||||
|
||||
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 *,
|
|||
int block_write_begin(struct file *, struct address_space *,
|
||||
loff_t, unsigned, unsigned,
|
||||
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 *,
|
||||
loff_t, unsigned, unsigned,
|
||||
struct page *, void *);
|
||||
|
|
Loading…
Reference in New Issue
Block a user