diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-04 05:29:57 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:32 -0400 |
commit | 6e1db88d536adcbbfe562b2d4b7d6425784fff12 (patch) | |
tree | 8cfcb5a6190722db6249b2e4978f39247975abcf | |
parent | f4e420dc423148fba637af1ab618fa8896dfb2d6 (diff) |
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>
-rw-r--r-- | fs/buffer.c | 69 | ||||
-rw-r--r-- | fs/ext2/dir.c | 3 | ||||
-rw-r--r-- | fs/ext3/inode.c | 3 | ||||
-rw-r--r-- | fs/ext4/inode.c | 11 | ||||
-rw-r--r-- | fs/minix/inode.c | 3 | ||||
-rw-r--r-- | fs/nilfs2/dir.c | 3 | ||||
-rw-r--r-- | fs/reiserfs/inode.c | 3 | ||||
-rw-r--r-- | fs/sysv/itree.c | 3 | ||||
-rw-r--r-- | fs/ufs/inode.c | 3 | ||||
-rw-r--r-- | include/linux/buffer_head.h | 2 |
10 files changed, 39 insertions, 64 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 14529ec759b9..c319c49da511 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1833,9 +1833,10 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to) | |||
1833 | } | 1833 | } |
1834 | EXPORT_SYMBOL(page_zero_new_buffers); | 1834 | EXPORT_SYMBOL(page_zero_new_buffers); |
1835 | 1835 | ||
1836 | static int __block_prepare_write(struct inode *inode, struct page *page, | 1836 | int block_prepare_write(struct page *page, unsigned from, unsigned to, |
1837 | unsigned from, unsigned to, get_block_t *get_block) | 1837 | get_block_t *get_block) |
1838 | { | 1838 | { |
1839 | struct inode *inode = page->mapping->host; | ||
1839 | unsigned block_start, block_end; | 1840 | unsigned block_start, block_end; |
1840 | sector_t block; | 1841 | sector_t block; |
1841 | int err = 0; | 1842 | int err = 0; |
@@ -1908,10 +1909,13 @@ static int __block_prepare_write(struct inode *inode, struct page *page, | |||
1908 | if (!buffer_uptodate(*wait_bh)) | 1909 | if (!buffer_uptodate(*wait_bh)) |
1909 | err = -EIO; | 1910 | err = -EIO; |
1910 | } | 1911 | } |
1911 | if (unlikely(err)) | 1912 | if (unlikely(err)) { |
1912 | page_zero_new_buffers(page, from, to); | 1913 | page_zero_new_buffers(page, from, to); |
1914 | ClearPageUptodate(page); | ||
1915 | } | ||
1913 | return err; | 1916 | return err; |
1914 | } | 1917 | } |
1918 | EXPORT_SYMBOL(block_prepare_write); | ||
1915 | 1919 | ||
1916 | static int __block_commit_write(struct inode *inode, struct page *page, | 1920 | static int __block_commit_write(struct inode *inode, struct page *page, |
1917 | unsigned from, unsigned to) | 1921 | unsigned from, unsigned to) |
@@ -1948,6 +1952,15 @@ static int __block_commit_write(struct inode *inode, struct page *page, | |||
1948 | return 0; | 1952 | return 0; |
1949 | } | 1953 | } |
1950 | 1954 | ||
1955 | int __block_write_begin(struct page *page, loff_t pos, unsigned len, | ||
1956 | get_block_t *get_block) | ||
1957 | { | ||
1958 | unsigned start = pos & (PAGE_CACHE_SIZE - 1); | ||
1959 | |||
1960 | return block_prepare_write(page, start, start + len, get_block); | ||
1961 | } | ||
1962 | EXPORT_SYMBOL(__block_write_begin); | ||
1963 | |||
1951 | /* | 1964 | /* |
1952 | * Filesystems implementing the new truncate sequence should use the | 1965 | * Filesystems implementing the new truncate sequence should use the |
1953 | * _newtrunc postfix variant which won't incorrectly call vmtruncate. | 1966 | * _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 | struct page **pagep, void **fsdata, | 1971 | struct page **pagep, void **fsdata, |
1959 | get_block_t *get_block) | 1972 | get_block_t *get_block) |
1960 | { | 1973 | { |
1961 | struct inode *inode = mapping->host; | 1974 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
1962 | int status = 0; | ||
1963 | struct page *page; | 1975 | struct page *page; |
1964 | pgoff_t index; | 1976 | int status; |
1965 | unsigned start, end; | ||
1966 | int ownpage = 0; | ||
1967 | 1977 | ||
1968 | index = pos >> PAGE_CACHE_SHIFT; | 1978 | page = grab_cache_page_write_begin(mapping, index, flags); |
1969 | start = pos & (PAGE_CACHE_SIZE - 1); | 1979 | if (!page) |
1970 | end = start + len; | 1980 | return -ENOMEM; |
1971 | |||
1972 | page = *pagep; | ||
1973 | if (page == NULL) { | ||
1974 | ownpage = 1; | ||
1975 | page = grab_cache_page_write_begin(mapping, index, flags); | ||
1976 | if (!page) { | ||
1977 | status = -ENOMEM; | ||
1978 | goto out; | ||
1979 | } | ||
1980 | *pagep = page; | ||
1981 | } else | ||
1982 | BUG_ON(!PageLocked(page)); | ||
1983 | 1981 | ||
1984 | status = __block_prepare_write(inode, page, start, end, get_block); | 1982 | status = __block_write_begin(page, pos, len, get_block); |
1985 | if (unlikely(status)) { | 1983 | if (unlikely(status)) { |
1986 | ClearPageUptodate(page); | 1984 | unlock_page(page); |
1987 | 1985 | page_cache_release(page); | |
1988 | if (ownpage) { | 1986 | page = NULL; |
1989 | unlock_page(page); | ||
1990 | page_cache_release(page); | ||
1991 | *pagep = NULL; | ||
1992 | } | ||
1993 | } | 1987 | } |
1994 | 1988 | ||
1995 | out: | 1989 | *pagep = page; |
1996 | return status; | 1990 | return status; |
1997 | } | 1991 | } |
1998 | EXPORT_SYMBOL(block_write_begin_newtrunc); | 1992 | EXPORT_SYMBOL(block_write_begin_newtrunc); |
@@ -2379,17 +2373,6 @@ out: | |||
2379 | } | 2373 | } |
2380 | EXPORT_SYMBOL(cont_write_begin); | 2374 | EXPORT_SYMBOL(cont_write_begin); |
2381 | 2375 | ||
2382 | int block_prepare_write(struct page *page, unsigned from, unsigned to, | ||
2383 | get_block_t *get_block) | ||
2384 | { | ||
2385 | struct inode *inode = page->mapping->host; | ||
2386 | int err = __block_prepare_write(inode, page, from, to, get_block); | ||
2387 | if (err) | ||
2388 | ClearPageUptodate(page); | ||
2389 | return err; | ||
2390 | } | ||
2391 | EXPORT_SYMBOL(block_prepare_write); | ||
2392 | |||
2393 | int block_commit_write(struct page *page, unsigned from, unsigned to) | 2376 | int block_commit_write(struct page *page, unsigned from, unsigned to) |
2394 | { | 2377 | { |
2395 | struct inode *inode = page->mapping->host; | 2378 | struct inode *inode = page->mapping->host; |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 6b946bae11cf..764109886ec0 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -450,8 +450,7 @@ ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child) | |||
450 | 450 | ||
451 | static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len) | 451 | static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len) |
452 | { | 452 | { |
453 | return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, | 453 | return __block_write_begin(page, pos, len, ext2_get_block); |
454 | &page, NULL, ext2_get_block); | ||
455 | } | 454 | } |
456 | 455 | ||
457 | /* Releases the page */ | 456 | /* Releases the page */ |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a66f3fe33672..5c6f07eefa4a 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1196,8 +1196,7 @@ retry: | |||
1196 | ret = PTR_ERR(handle); | 1196 | ret = PTR_ERR(handle); |
1197 | goto out; | 1197 | goto out; |
1198 | } | 1198 | } |
1199 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 1199 | ret = __block_write_begin(page, pos, len, ext3_get_block); |
1200 | ext3_get_block); | ||
1201 | if (ret) | 1200 | if (ret) |
1202 | goto write_begin_failed; | 1201 | goto write_begin_failed; |
1203 | 1202 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d6a7701018a6..3da3c9646e5e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1578,11 +1578,9 @@ retry: | |||
1578 | *pagep = page; | 1578 | *pagep = page; |
1579 | 1579 | ||
1580 | if (ext4_should_dioread_nolock(inode)) | 1580 | if (ext4_should_dioread_nolock(inode)) |
1581 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, | 1581 | ret = __block_write_begin(page, pos, len, ext4_get_block_write); |
1582 | fsdata, ext4_get_block_write); | ||
1583 | else | 1582 | else |
1584 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, | 1583 | ret = __block_write_begin(page, pos, len, ext4_get_block); |
1585 | fsdata, ext4_get_block); | ||
1586 | 1584 | ||
1587 | if (!ret && ext4_should_journal_data(inode)) { | 1585 | if (!ret && ext4_should_journal_data(inode)) { |
1588 | ret = walk_page_buffers(handle, page_buffers(page), | 1586 | ret = walk_page_buffers(handle, page_buffers(page), |
@@ -1593,7 +1591,7 @@ retry: | |||
1593 | unlock_page(page); | 1591 | unlock_page(page); |
1594 | page_cache_release(page); | 1592 | page_cache_release(page); |
1595 | /* | 1593 | /* |
1596 | * block_write_begin may have instantiated a few blocks | 1594 | * __block_write_begin may have instantiated a few blocks |
1597 | * outside i_size. Trim these off again. Don't need | 1595 | * outside i_size. Trim these off again. Don't need |
1598 | * i_size_read because we hold i_mutex. | 1596 | * i_size_read because we hold i_mutex. |
1599 | * | 1597 | * |
@@ -3185,8 +3183,7 @@ retry: | |||
3185 | } | 3183 | } |
3186 | *pagep = page; | 3184 | *pagep = page; |
3187 | 3185 | ||
3188 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 3186 | ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep); |
3189 | ext4_da_get_block_prep); | ||
3190 | if (ret < 0) { | 3187 | if (ret < 0) { |
3191 | unlock_page(page); | 3188 | unlock_page(page); |
3192 | ext4_journal_stop(handle); | 3189 | ext4_journal_stop(handle); |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index f4abe45229bb..6b29e73f0ca6 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -359,8 +359,7 @@ static int minix_readpage(struct file *file, struct page *page) | |||
359 | 359 | ||
360 | int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len) | 360 | int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len) |
361 | { | 361 | { |
362 | return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, | 362 | return __block_write_begin(page, pos, len, minix_get_block); |
363 | &page, NULL, minix_get_block); | ||
364 | } | 363 | } |
365 | 364 | ||
366 | static int minix_write_begin(struct file *file, struct address_space *mapping, | 365 | static int minix_write_begin(struct file *file, struct address_space *mapping, |
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index fc2bcfa599a3..d14e3b94d81f 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
@@ -83,8 +83,7 @@ static unsigned nilfs_last_byte(struct inode *inode, unsigned long page_nr) | |||
83 | static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to) | 83 | static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to) |
84 | { | 84 | { |
85 | loff_t pos = page_offset(page) + from; | 85 | loff_t pos = page_offset(page) + from; |
86 | return block_write_begin_newtrunc(NULL, page->mapping, pos, to - from, | 86 | return __block_write_begin(page, pos, to - from, nilfs_get_block); |
87 | 0, &page, NULL, nilfs_get_block); | ||
88 | } | 87 | } |
89 | 88 | ||
90 | static void nilfs_commit_chunk(struct page *page, | 89 | static void nilfs_commit_chunk(struct page *page, |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 4c1fb548ab64..045729f5674a 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -2585,8 +2585,7 @@ static int reiserfs_write_begin(struct file *file, | |||
2585 | old_ref = th->t_refcount; | 2585 | old_ref = th->t_refcount; |
2586 | th->t_refcount++; | 2586 | th->t_refcount++; |
2587 | } | 2587 | } |
2588 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 2588 | ret = __block_write_begin(page, pos, len, reiserfs_get_block); |
2589 | reiserfs_get_block); | ||
2590 | if (ret && reiserfs_transaction_running(inode->i_sb)) { | 2589 | if (ret && reiserfs_transaction_running(inode->i_sb)) { |
2591 | struct reiserfs_transaction_handle *th = current->journal_info; | 2590 | struct reiserfs_transaction_handle *th = current->journal_info; |
2592 | /* this gets a little ugly. If reiserfs_get_block returned an | 2591 | /* this gets a little ugly. If reiserfs_get_block returned an |
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index 4068f485cfd6..82a005c3d7eb 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c | |||
@@ -461,8 +461,7 @@ static int sysv_readpage(struct file *file, struct page *page) | |||
461 | 461 | ||
462 | int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len) | 462 | int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len) |
463 | { | 463 | { |
464 | return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, | 464 | return __block_write_begin(page, pos, len, get_block); |
465 | &page, NULL, get_block); | ||
466 | } | 465 | } |
467 | 466 | ||
468 | static int sysv_write_begin(struct file *file, struct address_space *mapping, | 467 | static int sysv_write_begin(struct file *file, struct address_space *mapping, |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index a9555b1ffd28..45ce32391f8f 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -560,8 +560,7 @@ static int ufs_readpage(struct file *file, struct page *page) | |||
560 | 560 | ||
561 | int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len) | 561 | int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len) |
562 | { | 562 | { |
563 | return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, | 563 | return __block_write_begin(page, pos, len, ufs_getfrag_block); |
564 | &page, NULL, ufs_getfrag_block); | ||
565 | } | 564 | } |
566 | 565 | ||
567 | static int ufs_write_begin(struct file *file, struct address_space *mapping, | 566 | static int ufs_write_begin(struct file *file, struct address_space *mapping, |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 7638647f0424..accc9f81bb63 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
@@ -209,6 +209,8 @@ int block_write_begin_newtrunc(struct file *, struct address_space *, | |||
209 | int block_write_begin(struct file *, struct address_space *, | 209 | int block_write_begin(struct file *, struct address_space *, |
210 | loff_t, unsigned, unsigned, | 210 | loff_t, unsigned, unsigned, |
211 | struct page **, void **, get_block_t*); | 211 | struct page **, void **, get_block_t*); |
212 | int __block_write_begin(struct page *page, loff_t pos, unsigned len, | ||
213 | get_block_t *get_block); | ||
212 | int block_write_end(struct file *, struct address_space *, | 214 | int block_write_end(struct file *, struct address_space *, |
213 | loff_t, unsigned, unsigned, | 215 | loff_t, unsigned, unsigned, |
214 | struct page *, void *); | 216 | struct page *, void *); |