Allocating pagecache pages within the disk request_fn is deadlocky and prone
to page allocation failures, causing write I/O errors.

Attempt to bandaid things up.


---

 25-akpm/drivers/block/rd.c |   31 ++++++++++++++++++++++++++-----
 1 files changed, 26 insertions(+), 5 deletions(-)

diff -puN drivers/block/rd.c~ramdisk-memory-allocation-fixes drivers/block/rd.c
--- 25/drivers/block/rd.c~ramdisk-memory-allocation-fixes	2004-05-17 22:11:30.352130848 -0700
+++ 25-akpm/drivers/block/rd.c	2004-05-17 22:11:30.356130240 -0700
@@ -320,18 +320,39 @@ static int rd_open(struct inode *inode, 
 {
 	unsigned unit = iminor(inode);
 
-	/*
-	 * Immunize device against invalidate_buffers() and prune_icache().
-	 */
 	if (rd_bdev[unit] == NULL) {
 		struct block_device *bdev = inode->i_bdev;
+		struct address_space *mapping;
+		int gfp_mask;
+
 		inode = igrab(bdev->bd_inode);
 		rd_bdev[unit] = bdev;
 		bdev->bd_openers++;
 		bdev->bd_block_size = rd_blocksize;
 		inode->i_size = get_capacity(rd_disks[unit])<<9;
-		inode->i_mapping->a_ops = &ramdisk_aops;
-		inode->i_mapping->backing_dev_info = &rd_backing_dev_info;
+		mapping = inode->i_mapping;
+		mapping->a_ops = &ramdisk_aops;
+		mapping->backing_dev_info = &rd_backing_dev_info;
+
+		/*
+		 * Deep badness.  rd_blkdev_pagecache_IO() needs to allocate
+		 * pagecache pages within a request_fn.  We cannot recur back
+		 * into the filesytem which is mounted atop the ramdisk, because
+		 * that would deadlock on fs locks.  And we really don't want
+		 * to reenter rd_blkdev_pagecache_IO when we're already within
+		 * that function.
+		 *
+		 * So we turn off __GFP_FS and __GFP_IO.
+		 *
+		 * And to give this thing a hope of working, turn on __GFP_HIGH.
+		 * Hopefully, there's enough regular memory allocation going on
+		 * for the page allocator emergency pools to keep the ramdisk
+		 * driver happy.
+		 */
+		gfp_mask = mapping_gfp_mask(mapping);
+		gfp_mask &= ~(__GFP_FS|__GFP_IO);
+		gfp_mask |= __GFP_HIGH;
+		mapping_set_gfp_mask(mapping, gfp_mask);
 	}
 
 	return 0;

_