diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 5287be18633b..55f0975a9b15 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -153,14 +153,8 @@ int sync_blockdev(struct block_device *bdev) | |||
153 | { | 153 | { |
154 | int ret = 0; | 154 | int ret = 0; |
155 | 155 | ||
156 | if (bdev) { | 156 | if (bdev) |
157 | int err; | 157 | ret = filemap_write_and_wait(bdev->bd_inode->i_mapping); |
158 | |||
159 | ret = filemap_fdatawrite(bdev->bd_inode->i_mapping); | ||
160 | err = filemap_fdatawait(bdev->bd_inode->i_mapping); | ||
161 | if (!ret) | ||
162 | ret = err; | ||
163 | } | ||
164 | return ret; | 158 | return ret; |
165 | } | 159 | } |
166 | EXPORT_SYMBOL(sync_blockdev); | 160 | EXPORT_SYMBOL(sync_blockdev); |
@@ -1768,7 +1762,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, | |||
1768 | * handle that here by just cleaning them. | 1762 | * handle that here by just cleaning them. |
1769 | */ | 1763 | */ |
1770 | 1764 | ||
1771 | block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 1765 | block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
1772 | head = page_buffers(page); | 1766 | head = page_buffers(page); |
1773 | bh = head; | 1767 | bh = head; |
1774 | 1768 | ||
@@ -2160,11 +2154,12 @@ int block_read_full_page(struct page *page, get_block_t *get_block) | |||
2160 | * truncates. Uses prepare/commit_write to allow the filesystem to | 2154 | * truncates. Uses prepare/commit_write to allow the filesystem to |
2161 | * deal with the hole. | 2155 | * deal with the hole. |
2162 | */ | 2156 | */ |
2163 | int generic_cont_expand(struct inode *inode, loff_t size) | 2157 | static int __generic_cont_expand(struct inode *inode, loff_t size, |
2158 | pgoff_t index, unsigned int offset) | ||
2164 | { | 2159 | { |
2165 | struct address_space *mapping = inode->i_mapping; | 2160 | struct address_space *mapping = inode->i_mapping; |
2166 | struct page *page; | 2161 | struct page *page; |
2167 | unsigned long index, offset, limit; | 2162 | unsigned long limit; |
2168 | int err; | 2163 | int err; |
2169 | 2164 | ||
2170 | err = -EFBIG; | 2165 | err = -EFBIG; |
@@ -2176,24 +2171,24 @@ int generic_cont_expand(struct inode *inode, loff_t size) | |||
2176 | if (size > inode->i_sb->s_maxbytes) | 2171 | if (size > inode->i_sb->s_maxbytes) |
2177 | goto out; | 2172 | goto out; |
2178 | 2173 | ||
2179 | offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */ | ||
2180 | |||
2181 | /* ugh. in prepare/commit_write, if from==to==start of block, we | ||
2182 | ** skip the prepare. make sure we never send an offset for the start | ||
2183 | ** of a block | ||
2184 | */ | ||
2185 | if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) { | ||
2186 | offset++; | ||
2187 | } | ||
2188 | index = size >> PAGE_CACHE_SHIFT; | ||
2189 | err = -ENOMEM; | 2174 | err = -ENOMEM; |
2190 | page = grab_cache_page(mapping, index); | 2175 | page = grab_cache_page(mapping, index); |
2191 | if (!page) | 2176 | if (!page) |
2192 | goto out; | 2177 | goto out; |
2193 | err = mapping->a_ops->prepare_write(NULL, page, offset, offset); | 2178 | err = mapping->a_ops->prepare_write(NULL, page, offset, offset); |
2194 | if (!err) { | 2179 | if (err) { |
2195 | err = mapping->a_ops->commit_write(NULL, page, offset, offset); | 2180 | /* |
2181 | * ->prepare_write() may have instantiated a few blocks | ||
2182 | * outside i_size. Trim these off again. | ||
2183 | */ | ||
2184 | unlock_page(page); | ||
2185 | page_cache_release(page); | ||
2186 | vmtruncate(inode, inode->i_size); | ||
2187 | goto out; | ||
2196 | } | 2188 | } |
2189 | |||
2190 | err = mapping->a_ops->commit_write(NULL, page, offset, offset); | ||
2191 | |||
2197 | unlock_page(page); | 2192 | unlock_page(page); |
2198 | page_cache_release(page); | 2193 | page_cache_release(page); |
2199 | if (err > 0) | 2194 | if (err > 0) |
@@ -2202,6 +2197,36 @@ out: | |||
2202 | return err; | 2197 | return err; |
2203 | } | 2198 | } |
2204 | 2199 | ||
2200 | int generic_cont_expand(struct inode *inode, loff_t size) | ||
2201 | { | ||
2202 | pgoff_t index; | ||
2203 | unsigned int offset; | ||
2204 | |||
2205 | offset = (size & (PAGE_CACHE_SIZE - 1)); /* Within page */ | ||
2206 | |||
2207 | /* ugh. in prepare/commit_write, if from==to==start of block, we | ||
2208 | ** skip the prepare. make sure we never send an offset for the start | ||
2209 | ** of a block | ||
2210 | */ | ||
2211 | if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) { | ||
2212 | /* caller must handle this extra byte. */ | ||
2213 | offset++; | ||
2214 | } | ||
2215 | index = size >> PAGE_CACHE_SHIFT; | ||
2216 | |||
2217 | return __generic_cont_expand(inode, size, index, offset); | ||
2218 | } | ||
2219 | |||
2220 | int generic_cont_expand_simple(struct inode *inode, loff_t size) | ||
2221 | { | ||
2222 | loff_t pos = size - 1; | ||
2223 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | ||
2224 | unsigned int offset = (pos & (PAGE_CACHE_SIZE - 1)) + 1; | ||
2225 | |||
2226 | /* prepare/commit_write can handle even if from==to==start of block. */ | ||
2227 | return __generic_cont_expand(inode, size, index, offset); | ||
2228 | } | ||
2229 | |||
2205 | /* | 2230 | /* |
2206 | * For moronic filesystems that do not allow holes in file. | 2231 | * For moronic filesystems that do not allow holes in file. |
2207 | * We may have to extend the file. | 2232 | * We may have to extend the file. |
@@ -2610,7 +2635,7 @@ int block_truncate_page(struct address_space *mapping, | |||
2610 | pgoff_t index = from >> PAGE_CACHE_SHIFT; | 2635 | pgoff_t index = from >> PAGE_CACHE_SHIFT; |
2611 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 2636 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
2612 | unsigned blocksize; | 2637 | unsigned blocksize; |
2613 | pgoff_t iblock; | 2638 | sector_t iblock; |
2614 | unsigned length, pos; | 2639 | unsigned length, pos; |
2615 | struct inode *inode = mapping->host; | 2640 | struct inode *inode = mapping->host; |
2616 | struct page *page; | 2641 | struct page *page; |
@@ -2626,7 +2651,7 @@ int block_truncate_page(struct address_space *mapping, | |||
2626 | return 0; | 2651 | return 0; |
2627 | 2652 | ||
2628 | length = blocksize - length; | 2653 | length = blocksize - length; |
2629 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 2654 | iblock = (sector_t)index << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
2630 | 2655 | ||
2631 | page = grab_cache_page(mapping, index); | 2656 | page = grab_cache_page(mapping, index); |
2632 | err = -ENOMEM; | 2657 | err = -ENOMEM; |
@@ -3145,6 +3170,7 @@ EXPORT_SYMBOL(fsync_bdev); | |||
3145 | EXPORT_SYMBOL(generic_block_bmap); | 3170 | EXPORT_SYMBOL(generic_block_bmap); |
3146 | EXPORT_SYMBOL(generic_commit_write); | 3171 | EXPORT_SYMBOL(generic_commit_write); |
3147 | EXPORT_SYMBOL(generic_cont_expand); | 3172 | EXPORT_SYMBOL(generic_cont_expand); |
3173 | EXPORT_SYMBOL(generic_cont_expand_simple); | ||
3148 | EXPORT_SYMBOL(init_buffer); | 3174 | EXPORT_SYMBOL(init_buffer); |
3149 | EXPORT_SYMBOL(invalidate_bdev); | 3175 | EXPORT_SYMBOL(invalidate_bdev); |
3150 | EXPORT_SYMBOL(ll_rw_block); | 3176 | EXPORT_SYMBOL(ll_rw_block); |