|
@@ -1042,8 +1042,21 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
|
|
|
} while ((size << sizebits) < PAGE_SIZE);
|
|
|
|
|
|
index = block >> sizebits;
|
|
|
- block = index << sizebits;
|
|
|
|
|
|
+ /*
|
|
|
+ * Check for a block which wants to lie outside our maximum possible
|
|
|
+ * pagecache index. (this comparison is done using sector_t types).
|
|
|
+ */
|
|
|
+ if (unlikely(index != block >> sizebits)) {
|
|
|
+ char b[BDEVNAME_SIZE];
|
|
|
+
|
|
|
+ printk(KERN_ERR "%s: requested out-of-range block %llu for "
|
|
|
+ "device %s\n",
|
|
|
+ __FUNCTION__, (unsigned long long)block,
|
|
|
+ bdevname(bdev, b));
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ block = index << sizebits;
|
|
|
/* Create a page with the proper size buffers.. */
|
|
|
page = grow_dev_page(bdev, block, index, size);
|
|
|
if (!page)
|
|
@@ -1070,12 +1083,16 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
|
|
|
|
|
|
for (;;) {
|
|
|
struct buffer_head * bh;
|
|
|
+ int ret;
|
|
|
|
|
|
bh = __find_get_block(bdev, block, size);
|
|
|
if (bh)
|
|
|
return bh;
|
|
|
|
|
|
- if (!grow_buffers(bdev, block, size))
|
|
|
+ ret = grow_buffers(bdev, block, size);
|
|
|
+ if (ret < 0)
|
|
|
+ return NULL;
|
|
|
+ if (ret == 0)
|
|
|
free_more_memory();
|
|
|
}
|
|
|
}
|