introduce __block_write_begin
Christoph Hellwig [Fri, 4 Jun 2010 09:29:57 +0000 (11:29 +0200)]
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>

fs/buffer.c
fs/ext2/dir.c
fs/ext3/inode.c
fs/ext4/inode.c
fs/minix/inode.c
fs/nilfs2/dir.c
fs/reiserfs/inode.c
fs/sysv/itree.c
fs/ufs/inode.c
include/linux/buffer_head.h

index 14529ec..c319c49 100644 (file)
@@ -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 = *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));
+       page = grab_cache_page_write_begin(mapping, index, flags);
+       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;
-               }
+               unlock_page(page);
+               page_cache_release(page);
+               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;
index 6b946ba..7641098 100644 (file)
@@ -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 */
index a66f3fe..5c6f07e 100644 (file)
@@ -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;
 
index d6a7701..3da3c96 100644 (file)
@@ -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);
index f4abe45..6b29e73 100644 (file)
@@ -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,
index fc2bcfa..d14e3b9 100644 (file)
@@ -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,
index 4c1fb54..045729f 100644 (file)
@@ -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
index 4068f48..82a005c 100644 (file)
@@ -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,
index a9555b1..45ce323 100644 (file)
@@ -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,
index 7638647..accc9f8 100644 (file)
@@ -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 *);