Commit 6e1db88d536adcbbfe562b2d4b7d6425784fff12
Committed by
Al Viro
1 parent
f4e420dc42
Exists in
master
and in
7 other branches
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>
Showing 10 changed files with 39 additions and 64 deletions Side-by-side Diff
fs/buffer.c
... | ... | @@ -1833,9 +1833,10 @@ |
1833 | 1833 | } |
1834 | 1834 | EXPORT_SYMBOL(page_zero_new_buffers); |
1835 | 1835 | |
1836 | -static int __block_prepare_write(struct inode *inode, struct page *page, | |
1837 | - unsigned from, unsigned to, get_block_t *get_block) | |
1836 | +int block_prepare_write(struct page *page, unsigned from, unsigned to, | |
1837 | + get_block_t *get_block) | |
1838 | 1838 | { |
1839 | + struct inode *inode = page->mapping->host; | |
1839 | 1840 | unsigned block_start, block_end; |
1840 | 1841 | sector_t block; |
1841 | 1842 | int err = 0; |
1842 | 1843 | |
1843 | 1844 | |
... | ... | @@ -1908,10 +1909,13 @@ |
1908 | 1909 | if (!buffer_uptodate(*wait_bh)) |
1909 | 1910 | err = -EIO; |
1910 | 1911 | } |
1911 | - if (unlikely(err)) | |
1912 | + if (unlikely(err)) { | |
1912 | 1913 | page_zero_new_buffers(page, from, to); |
1914 | + ClearPageUptodate(page); | |
1915 | + } | |
1913 | 1916 | return err; |
1914 | 1917 | } |
1918 | +EXPORT_SYMBOL(block_prepare_write); | |
1915 | 1919 | |
1916 | 1920 | static int __block_commit_write(struct inode *inode, struct page *page, |
1917 | 1921 | unsigned from, unsigned to) |
... | ... | @@ -1948,6 +1952,15 @@ |
1948 | 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 | 1965 | * Filesystems implementing the new truncate sequence should use the |
1953 | 1966 | * _newtrunc postfix variant which won't incorrectly call vmtruncate. |
1954 | 1967 | |
1955 | 1968 | |
1956 | 1969 | |
1957 | 1970 | |
1958 | 1971 | |
... | ... | @@ -1958,41 +1971,22 @@ |
1958 | 1971 | struct page **pagep, void **fsdata, |
1959 | 1972 | get_block_t *get_block) |
1960 | 1973 | { |
1961 | - struct inode *inode = mapping->host; | |
1962 | - int status = 0; | |
1974 | + pgoff_t index = pos >> PAGE_CACHE_SHIFT; | |
1963 | 1975 | struct page *page; |
1964 | - pgoff_t index; | |
1965 | - unsigned start, end; | |
1966 | - int ownpage = 0; | |
1976 | + int status; | |
1967 | 1977 | |
1968 | - index = pos >> PAGE_CACHE_SHIFT; | |
1969 | - start = pos & (PAGE_CACHE_SIZE - 1); | |
1970 | - end = start + len; | |
1978 | + page = grab_cache_page_write_begin(mapping, index, flags); | |
1979 | + if (!page) | |
1980 | + return -ENOMEM; | |
1971 | 1981 | |
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 | - | |
1984 | - status = __block_prepare_write(inode, page, start, end, get_block); | |
1982 | + status = __block_write_begin(page, pos, len, get_block); | |
1985 | 1983 | if (unlikely(status)) { |
1986 | - ClearPageUptodate(page); | |
1987 | - | |
1988 | - if (ownpage) { | |
1989 | - unlock_page(page); | |
1990 | - page_cache_release(page); | |
1991 | - *pagep = NULL; | |
1992 | - } | |
1984 | + unlock_page(page); | |
1985 | + page_cache_release(page); | |
1986 | + page = NULL; | |
1993 | 1987 | } |
1994 | 1988 | |
1995 | -out: | |
1989 | + *pagep = page; | |
1996 | 1990 | return status; |
1997 | 1991 | } |
1998 | 1992 | EXPORT_SYMBOL(block_write_begin_newtrunc); |
... | ... | @@ -2378,17 +2372,6 @@ |
2378 | 2372 | return err; |
2379 | 2373 | } |
2380 | 2374 | EXPORT_SYMBOL(cont_write_begin); |
2381 | - | |
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 | 2375 | |
2393 | 2376 | int block_commit_write(struct page *page, unsigned from, unsigned to) |
2394 | 2377 | { |
fs/ext2/dir.c
... | ... | @@ -450,8 +450,7 @@ |
450 | 450 | |
451 | 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, | |
454 | - &page, NULL, ext2_get_block); | |
453 | + return __block_write_begin(page, pos, len, ext2_get_block); | |
455 | 454 | } |
456 | 455 | |
457 | 456 | /* Releases the page */ |
fs/ext3/inode.c
... | ... | @@ -1196,8 +1196,7 @@ |
1196 | 1196 | ret = PTR_ERR(handle); |
1197 | 1197 | goto out; |
1198 | 1198 | } |
1199 | - ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | |
1200 | - ext3_get_block); | |
1199 | + ret = __block_write_begin(page, pos, len, ext3_get_block); | |
1201 | 1200 | if (ret) |
1202 | 1201 | goto write_begin_failed; |
1203 | 1202 |
fs/ext4/inode.c
... | ... | @@ -1578,11 +1578,9 @@ |
1578 | 1578 | *pagep = page; |
1579 | 1579 | |
1580 | 1580 | if (ext4_should_dioread_nolock(inode)) |
1581 | - ret = block_write_begin(file, mapping, pos, len, flags, pagep, | |
1582 | - fsdata, ext4_get_block_write); | |
1581 | + ret = __block_write_begin(page, pos, len, ext4_get_block_write); | |
1583 | 1582 | else |
1584 | - ret = block_write_begin(file, mapping, pos, len, flags, pagep, | |
1585 | - fsdata, ext4_get_block); | |
1583 | + ret = __block_write_begin(page, pos, len, ext4_get_block); | |
1586 | 1584 | |
1587 | 1585 | if (!ret && ext4_should_journal_data(inode)) { |
1588 | 1586 | ret = walk_page_buffers(handle, page_buffers(page), |
... | ... | @@ -1593,7 +1591,7 @@ |
1593 | 1591 | unlock_page(page); |
1594 | 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 | 1595 | * outside i_size. Trim these off again. Don't need |
1598 | 1596 | * i_size_read because we hold i_mutex. |
1599 | 1597 | * |
... | ... | @@ -3185,8 +3183,7 @@ |
3185 | 3183 | } |
3186 | 3184 | *pagep = page; |
3187 | 3185 | |
3188 | - ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | |
3189 | - ext4_da_get_block_prep); | |
3186 | + ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep); | |
3190 | 3187 | if (ret < 0) { |
3191 | 3188 | unlock_page(page); |
3192 | 3189 | ext4_journal_stop(handle); |
fs/minix/inode.c
... | ... | @@ -359,8 +359,7 @@ |
359 | 359 | |
360 | 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, | |
363 | - &page, NULL, minix_get_block); | |
362 | + return __block_write_begin(page, pos, len, minix_get_block); | |
364 | 363 | } |
365 | 364 | |
366 | 365 | static int minix_write_begin(struct file *file, struct address_space *mapping, |
fs/nilfs2/dir.c
... | ... | @@ -83,8 +83,7 @@ |
83 | 83 | static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to) |
84 | 84 | { |
85 | 85 | loff_t pos = page_offset(page) + from; |
86 | - return block_write_begin_newtrunc(NULL, page->mapping, pos, to - from, | |
87 | - 0, &page, NULL, nilfs_get_block); | |
86 | + return __block_write_begin(page, pos, to - from, nilfs_get_block); | |
88 | 87 | } |
89 | 88 | |
90 | 89 | static void nilfs_commit_chunk(struct page *page, |
fs/reiserfs/inode.c
... | ... | @@ -2585,8 +2585,7 @@ |
2585 | 2585 | old_ref = th->t_refcount; |
2586 | 2586 | th->t_refcount++; |
2587 | 2587 | } |
2588 | - ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | |
2589 | - reiserfs_get_block); | |
2588 | + ret = __block_write_begin(page, pos, len, reiserfs_get_block); | |
2590 | 2589 | if (ret && reiserfs_transaction_running(inode->i_sb)) { |
2591 | 2590 | struct reiserfs_transaction_handle *th = current->journal_info; |
2592 | 2591 | /* this gets a little ugly. If reiserfs_get_block returned an |
fs/sysv/itree.c
... | ... | @@ -461,8 +461,7 @@ |
461 | 461 | |
462 | 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, | |
465 | - &page, NULL, get_block); | |
464 | + return __block_write_begin(page, pos, len, get_block); | |
466 | 465 | } |
467 | 466 | |
468 | 467 | static int sysv_write_begin(struct file *file, struct address_space *mapping, |
fs/ufs/inode.c
... | ... | @@ -560,8 +560,7 @@ |
560 | 560 | |
561 | 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, | |
564 | - &page, NULL, ufs_getfrag_block); | |
563 | + return __block_write_begin(page, pos, len, ufs_getfrag_block); | |
565 | 564 | } |
566 | 565 | |
567 | 566 | static int ufs_write_begin(struct file *file, struct address_space *mapping, |
include/linux/buffer_head.h
... | ... | @@ -209,6 +209,8 @@ |
209 | 209 | int block_write_begin(struct file *, struct address_space *, |
210 | 210 | loff_t, unsigned, unsigned, |
211 | 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 | 214 | int block_write_end(struct file *, struct address_space *, |
213 | 215 | loff_t, unsigned, unsigned, |
214 | 216 | struct page *, void *); |