diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index eeb8ac1aa856..f65ef8821c73 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1042,8 +1042,21 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) | |||
1042 | } while ((size << sizebits) < PAGE_SIZE); | 1042 | } while ((size << sizebits) < PAGE_SIZE); |
1043 | 1043 | ||
1044 | index = block >> sizebits; | 1044 | index = block >> sizebits; |
1045 | block = index << sizebits; | ||
1046 | 1045 | ||
1046 | /* | ||
1047 | * Check for a block which wants to lie outside our maximum possible | ||
1048 | * pagecache index. (this comparison is done using sector_t types). | ||
1049 | */ | ||
1050 | if (unlikely(index != block >> sizebits)) { | ||
1051 | char b[BDEVNAME_SIZE]; | ||
1052 | |||
1053 | printk(KERN_ERR "%s: requested out-of-range block %llu for " | ||
1054 | "device %s\n", | ||
1055 | __FUNCTION__, (unsigned long long)block, | ||
1056 | bdevname(bdev, b)); | ||
1057 | return -EIO; | ||
1058 | } | ||
1059 | block = index << sizebits; | ||
1047 | /* Create a page with the proper size buffers.. */ | 1060 | /* Create a page with the proper size buffers.. */ |
1048 | page = grow_dev_page(bdev, block, index, size); | 1061 | page = grow_dev_page(bdev, block, index, size); |
1049 | if (!page) | 1062 | if (!page) |
@@ -1070,12 +1083,16 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) | |||
1070 | 1083 | ||
1071 | for (;;) { | 1084 | for (;;) { |
1072 | struct buffer_head * bh; | 1085 | struct buffer_head * bh; |
1086 | int ret; | ||
1073 | 1087 | ||
1074 | bh = __find_get_block(bdev, block, size); | 1088 | bh = __find_get_block(bdev, block, size); |
1075 | if (bh) | 1089 | if (bh) |
1076 | return bh; | 1090 | return bh; |
1077 | 1091 | ||
1078 | if (!grow_buffers(bdev, block, size)) | 1092 | ret = grow_buffers(bdev, block, size); |
1093 | if (ret < 0) | ||
1094 | return NULL; | ||
1095 | if (ret == 0) | ||
1079 | free_more_memory(); | 1096 | free_more_memory(); |
1080 | } | 1097 | } |
1081 | } | 1098 | } |
@@ -1837,6 +1854,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page, | |||
1837 | clear_buffer_new(bh); | 1854 | clear_buffer_new(bh); |
1838 | kaddr = kmap_atomic(page, KM_USER0); | 1855 | kaddr = kmap_atomic(page, KM_USER0); |
1839 | memset(kaddr+block_start, 0, bh->b_size); | 1856 | memset(kaddr+block_start, 0, bh->b_size); |
1857 | flush_dcache_page(page); | ||
1840 | kunmap_atomic(kaddr, KM_USER0); | 1858 | kunmap_atomic(kaddr, KM_USER0); |
1841 | set_buffer_uptodate(bh); | 1859 | set_buffer_uptodate(bh); |
1842 | mark_buffer_dirty(bh); | 1860 | mark_buffer_dirty(bh); |
@@ -2343,6 +2361,7 @@ failed: | |||
2343 | */ | 2361 | */ |
2344 | kaddr = kmap_atomic(page, KM_USER0); | 2362 | kaddr = kmap_atomic(page, KM_USER0); |
2345 | memset(kaddr, 0, PAGE_CACHE_SIZE); | 2363 | memset(kaddr, 0, PAGE_CACHE_SIZE); |
2364 | flush_dcache_page(page); | ||
2346 | kunmap_atomic(kaddr, KM_USER0); | 2365 | kunmap_atomic(kaddr, KM_USER0); |
2347 | SetPageUptodate(page); | 2366 | SetPageUptodate(page); |
2348 | set_page_dirty(page); | 2367 | set_page_dirty(page); |