diff options
Diffstat (limited to 'fs/buffer.c')
| -rw-r--r-- | fs/buffer.c | 91 | 
1 files changed, 59 insertions, 32 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 5287be18633b..3dc712f29d2d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c  | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/percpu.h> | 26 | #include <linux/percpu.h> | 
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> | 
| 28 | #include <linux/smp_lock.h> | 28 | #include <linux/smp_lock.h> | 
| 29 | #include <linux/capability.h> | ||
| 29 | #include <linux/blkdev.h> | 30 | #include <linux/blkdev.h> | 
| 30 | #include <linux/file.h> | 31 | #include <linux/file.h> | 
| 31 | #include <linux/quotaops.h> | 32 | #include <linux/quotaops.h> | 
| @@ -153,14 +154,8 @@ int sync_blockdev(struct block_device *bdev) | |||
| 153 | { | 154 | { | 
| 154 | int ret = 0; | 155 | int ret = 0; | 
| 155 | 156 | ||
| 156 | if (bdev) { | 157 | if (bdev) | 
| 157 | int err; | 158 | 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; | 159 | return ret; | 
| 165 | } | 160 | } | 
| 166 | EXPORT_SYMBOL(sync_blockdev); | 161 | EXPORT_SYMBOL(sync_blockdev); | 
| @@ -358,11 +353,11 @@ static long do_fsync(unsigned int fd, int datasync) | |||
| 358 | * We need to protect against concurrent writers, | 353 | * We need to protect against concurrent writers, | 
| 359 | * which could cause livelocks in fsync_buffers_list | 354 | * which could cause livelocks in fsync_buffers_list | 
| 360 | */ | 355 | */ | 
| 361 | down(&mapping->host->i_sem); | 356 | mutex_lock(&mapping->host->i_mutex); | 
| 362 | err = file->f_op->fsync(file, file->f_dentry, datasync); | 357 | err = file->f_op->fsync(file, file->f_dentry, datasync); | 
| 363 | if (!ret) | 358 | if (!ret) | 
| 364 | ret = err; | 359 | ret = err; | 
| 365 | up(&mapping->host->i_sem); | 360 | mutex_unlock(&mapping->host->i_mutex); | 
| 366 | err = filemap_fdatawait(mapping); | 361 | err = filemap_fdatawait(mapping); | 
| 367 | if (!ret) | 362 | if (!ret) | 
| 368 | ret = err; | 363 | ret = err; | 
| @@ -1032,7 +1027,7 @@ try_again: | |||
| 1032 | /* Link the buffer to its page */ | 1027 | /* Link the buffer to its page */ | 
| 1033 | set_bh_page(bh, page, offset); | 1028 | set_bh_page(bh, page, offset); | 
| 1034 | 1029 | ||
| 1035 | bh->b_end_io = NULL; | 1030 | init_buffer(bh, NULL, NULL); | 
| 1036 | } | 1031 | } | 
| 1037 | return head; | 1032 | return head; | 
| 1038 | /* | 1033 | /* | 
| @@ -1170,7 +1165,7 @@ failed: | |||
| 1170 | * some of those buffers may be aliases of filesystem data. | 1165 | * some of those buffers may be aliases of filesystem data. | 
| 1171 | * grow_dev_page() will go BUG() if this happens. | 1166 | * grow_dev_page() will go BUG() if this happens. | 
| 1172 | */ | 1167 | */ | 
| 1173 | static inline int | 1168 | static int | 
| 1174 | grow_buffers(struct block_device *bdev, sector_t block, int size) | 1169 | grow_buffers(struct block_device *bdev, sector_t block, int size) | 
| 1175 | { | 1170 | { | 
| 1176 | struct page *page; | 1171 | struct page *page; | 
| @@ -1396,7 +1391,7 @@ static void bh_lru_install(struct buffer_head *bh) | |||
| 1396 | /* | 1391 | /* | 
| 1397 | * Look up the bh in this cpu's LRU. If it's there, move it to the head. | 1392 | * Look up the bh in this cpu's LRU. If it's there, move it to the head. | 
| 1398 | */ | 1393 | */ | 
| 1399 | static inline struct buffer_head * | 1394 | static struct buffer_head * | 
| 1400 | lookup_bh_lru(struct block_device *bdev, sector_t block, int size) | 1395 | lookup_bh_lru(struct block_device *bdev, sector_t block, int size) | 
| 1401 | { | 1396 | { | 
| 1402 | struct buffer_head *ret = NULL; | 1397 | struct buffer_head *ret = NULL; | 
| @@ -1546,7 +1541,7 @@ EXPORT_SYMBOL(set_bh_page); | |||
| 1546 | /* | 1541 | /* | 
| 1547 | * Called when truncating a buffer on a page completely. | 1542 | * Called when truncating a buffer on a page completely. | 
| 1548 | */ | 1543 | */ | 
| 1549 | static inline void discard_buffer(struct buffer_head * bh) | 1544 | static void discard_buffer(struct buffer_head * bh) | 
| 1550 | { | 1545 | { | 
| 1551 | lock_buffer(bh); | 1546 | lock_buffer(bh); | 
| 1552 | clear_buffer_dirty(bh); | 1547 | clear_buffer_dirty(bh); | 
| @@ -1768,7 +1763,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, | |||
| 1768 | * handle that here by just cleaning them. | 1763 | * handle that here by just cleaning them. | 
| 1769 | */ | 1764 | */ | 
| 1770 | 1765 | ||
| 1771 | block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 1766 | block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 
| 1772 | head = page_buffers(page); | 1767 | head = page_buffers(page); | 
| 1773 | bh = head; | 1768 | bh = head; | 
| 1774 | 1769 | ||
| @@ -2160,11 +2155,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 | 2155 | * truncates. Uses prepare/commit_write to allow the filesystem to | 
| 2161 | * deal with the hole. | 2156 | * deal with the hole. | 
| 2162 | */ | 2157 | */ | 
| 2163 | int generic_cont_expand(struct inode *inode, loff_t size) | 2158 | static int __generic_cont_expand(struct inode *inode, loff_t size, | 
| 2159 | pgoff_t index, unsigned int offset) | ||
| 2164 | { | 2160 | { | 
| 2165 | struct address_space *mapping = inode->i_mapping; | 2161 | struct address_space *mapping = inode->i_mapping; | 
| 2166 | struct page *page; | 2162 | struct page *page; | 
| 2167 | unsigned long index, offset, limit; | 2163 | unsigned long limit; | 
| 2168 | int err; | 2164 | int err; | 
| 2169 | 2165 | ||
| 2170 | err = -EFBIG; | 2166 | err = -EFBIG; | 
| @@ -2176,24 +2172,24 @@ int generic_cont_expand(struct inode *inode, loff_t size) | |||
| 2176 | if (size > inode->i_sb->s_maxbytes) | 2172 | if (size > inode->i_sb->s_maxbytes) | 
| 2177 | goto out; | 2173 | goto out; | 
| 2178 | 2174 | ||
| 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; | 2175 | err = -ENOMEM; | 
| 2190 | page = grab_cache_page(mapping, index); | 2176 | page = grab_cache_page(mapping, index); | 
| 2191 | if (!page) | 2177 | if (!page) | 
| 2192 | goto out; | 2178 | goto out; | 
| 2193 | err = mapping->a_ops->prepare_write(NULL, page, offset, offset); | 2179 | err = mapping->a_ops->prepare_write(NULL, page, offset, offset); | 
| 2194 | if (!err) { | 2180 | if (err) { | 
| 2195 | err = mapping->a_ops->commit_write(NULL, page, offset, offset); | 2181 | /* | 
| 2182 | * ->prepare_write() may have instantiated a few blocks | ||
| 2183 | * outside i_size. Trim these off again. | ||
| 2184 | */ | ||
| 2185 | unlock_page(page); | ||
| 2186 | page_cache_release(page); | ||
| 2187 | vmtruncate(inode, inode->i_size); | ||
| 2188 | goto out; | ||
| 2196 | } | 2189 | } | 
| 2190 | |||
| 2191 | err = mapping->a_ops->commit_write(NULL, page, offset, offset); | ||
| 2192 | |||
| 2197 | unlock_page(page); | 2193 | unlock_page(page); | 
| 2198 | page_cache_release(page); | 2194 | page_cache_release(page); | 
| 2199 | if (err > 0) | 2195 | if (err > 0) | 
| @@ -2202,6 +2198,36 @@ out: | |||
| 2202 | return err; | 2198 | return err; | 
| 2203 | } | 2199 | } | 
| 2204 | 2200 | ||
| 2201 | int generic_cont_expand(struct inode *inode, loff_t size) | ||
| 2202 | { | ||
| 2203 | pgoff_t index; | ||
| 2204 | unsigned int offset; | ||
| 2205 | |||
| 2206 | offset = (size & (PAGE_CACHE_SIZE - 1)); /* Within page */ | ||
| 2207 | |||
| 2208 | /* ugh. in prepare/commit_write, if from==to==start of block, we | ||
| 2209 | ** skip the prepare. make sure we never send an offset for the start | ||
| 2210 | ** of a block | ||
| 2211 | */ | ||
| 2212 | if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) { | ||
| 2213 | /* caller must handle this extra byte. */ | ||
| 2214 | offset++; | ||
| 2215 | } | ||
| 2216 | index = size >> PAGE_CACHE_SHIFT; | ||
| 2217 | |||
| 2218 | return __generic_cont_expand(inode, size, index, offset); | ||
| 2219 | } | ||
| 2220 | |||
| 2221 | int generic_cont_expand_simple(struct inode *inode, loff_t size) | ||
| 2222 | { | ||
| 2223 | loff_t pos = size - 1; | ||
| 2224 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | ||
| 2225 | unsigned int offset = (pos & (PAGE_CACHE_SIZE - 1)) + 1; | ||
| 2226 | |||
| 2227 | /* prepare/commit_write can handle even if from==to==start of block. */ | ||
| 2228 | return __generic_cont_expand(inode, size, index, offset); | ||
| 2229 | } | ||
| 2230 | |||
| 2205 | /* | 2231 | /* | 
| 2206 | * For moronic filesystems that do not allow holes in file. | 2232 | * For moronic filesystems that do not allow holes in file. | 
| 2207 | * We may have to extend the file. | 2233 | * We may have to extend the file. | 
| @@ -2313,7 +2339,7 @@ int generic_commit_write(struct file *file, struct page *page, | |||
| 2313 | __block_commit_write(inode,page,from,to); | 2339 | __block_commit_write(inode,page,from,to); | 
| 2314 | /* | 2340 | /* | 
| 2315 | * No need to use i_size_read() here, the i_size | 2341 | * No need to use i_size_read() here, the i_size | 
| 2316 | * cannot change under us because we hold i_sem. | 2342 | * cannot change under us because we hold i_mutex. | 
| 2317 | */ | 2343 | */ | 
| 2318 | if (pos > inode->i_size) { | 2344 | if (pos > inode->i_size) { | 
| 2319 | i_size_write(inode, pos); | 2345 | i_size_write(inode, pos); | 
| @@ -2610,7 +2636,7 @@ int block_truncate_page(struct address_space *mapping, | |||
| 2610 | pgoff_t index = from >> PAGE_CACHE_SHIFT; | 2636 | pgoff_t index = from >> PAGE_CACHE_SHIFT; | 
| 2611 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 2637 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 
| 2612 | unsigned blocksize; | 2638 | unsigned blocksize; | 
| 2613 | pgoff_t iblock; | 2639 | sector_t iblock; | 
| 2614 | unsigned length, pos; | 2640 | unsigned length, pos; | 
| 2615 | struct inode *inode = mapping->host; | 2641 | struct inode *inode = mapping->host; | 
| 2616 | struct page *page; | 2642 | struct page *page; | 
| @@ -2626,7 +2652,7 @@ int block_truncate_page(struct address_space *mapping, | |||
| 2626 | return 0; | 2652 | return 0; | 
| 2627 | 2653 | ||
| 2628 | length = blocksize - length; | 2654 | length = blocksize - length; | 
| 2629 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 2655 | iblock = (sector_t)index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 
| 2630 | 2656 | ||
| 2631 | page = grab_cache_page(mapping, index); | 2657 | page = grab_cache_page(mapping, index); | 
| 2632 | err = -ENOMEM; | 2658 | err = -ENOMEM; | 
| @@ -3145,6 +3171,7 @@ EXPORT_SYMBOL(fsync_bdev); | |||
| 3145 | EXPORT_SYMBOL(generic_block_bmap); | 3171 | EXPORT_SYMBOL(generic_block_bmap); | 
| 3146 | EXPORT_SYMBOL(generic_commit_write); | 3172 | EXPORT_SYMBOL(generic_commit_write); | 
| 3147 | EXPORT_SYMBOL(generic_cont_expand); | 3173 | EXPORT_SYMBOL(generic_cont_expand); | 
| 3174 | EXPORT_SYMBOL(generic_cont_expand_simple); | ||
| 3148 | EXPORT_SYMBOL(init_buffer); | 3175 | EXPORT_SYMBOL(init_buffer); | 
| 3149 | EXPORT_SYMBOL(invalidate_bdev); | 3176 | EXPORT_SYMBOL(invalidate_bdev); | 
| 3150 | EXPORT_SYMBOL(ll_rw_block); | 3177 | EXPORT_SYMBOL(ll_rw_block); | 
