From: viro@parcelfarce.linux.theplanet.co.uk

	Patch switches cramfs_read() to direct use of pagecache and
eliminates all messing with buffer_heads.  Fixes the interaction with
ramdisk (there set_blocksize() simply killed the ramdisk contents) and
gets code less brittle overall.



 fs/cramfs/inode.c |   50 ++++++++++++++++++++++++++------------------------
 1 files changed, 26 insertions(+), 24 deletions(-)

diff -puN fs/cramfs/inode.c~cramfs-use-pagecache fs/cramfs/inode.c
--- 25/fs/cramfs/inode.c~cramfs-use-pagecache	2003-11-10 19:36:04.000000000 -0800
+++ 25-akpm/fs/cramfs/inode.c	2003-11-10 19:36:04.000000000 -0800
@@ -112,8 +112,8 @@ static int next_buffer;
  */
 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
 {
-	struct buffer_head * bh_array[BLKS_PER_BUF];
-	struct buffer_head * read_array[BLKS_PER_BUF];
+	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+	struct page *pages[BLKS_PER_BUF];
 	unsigned i, blocknr, buffer, unread;
 	unsigned long devsize;
 	char *data;
@@ -138,33 +138,36 @@ static void *cramfs_read(struct super_bl
 		return read_buffers[i] + blk_offset;
 	}
 
-	devsize = sb->s_bdev->bd_inode->i_size >> 12;
-	if (!devsize)
-		devsize = ~0UL;
+	devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
 
 	/* Ok, read in BLKS_PER_BUF pages completely first. */
 	unread = 0;
 	for (i = 0; i < BLKS_PER_BUF; i++) {
-		struct buffer_head *bh;
+		struct page *page = NULL;
 
-		bh = NULL;
 		if (blocknr + i < devsize) {
-			bh = sb_getblk(sb, blocknr + i);
-			if (!buffer_uptodate(bh))
-				read_array[unread++] = bh;
+			page = read_cache_page(mapping, blocknr + i,
+				(filler_t *)mapping->a_ops->readpage,
+				NULL);
+			/* synchronous error? */
+			if (IS_ERR(page))
+				page = NULL;
 		}
-		bh_array[i] = bh;
+		pages[i] = page;
 	}
 
-	if (unread) {
-		ll_rw_block(READ, unread, read_array);
-		do {
-			unread--;
-			wait_on_buffer(read_array[unread]);
-		} while (unread);
+	for (i = 0; i < BLKS_PER_BUF; i++) {
+		struct page *page = pages[i];
+		if (page) {
+			wait_on_page_locked(page);
+			if (!PageUptodate(page)) {
+				/* asynchronous error */
+				page_cache_release(page);
+				pages[i] = NULL;
+			}
+		}
 	}
 
-	/* Ok, copy them to the staging area without sleeping. */
 	buffer = next_buffer;
 	next_buffer = NEXT_BUFFER(buffer);
 	buffer_blocknr[buffer] = blocknr;
@@ -172,10 +175,11 @@ static void *cramfs_read(struct super_bl
 
 	data = read_buffers[buffer];
 	for (i = 0; i < BLKS_PER_BUF; i++) {
-		struct buffer_head * bh = bh_array[i];
-		if (bh) {
-			memcpy(data, bh->b_data, PAGE_CACHE_SIZE);
-			brelse(bh);
+		struct page *page = pages[i];
+		if (page) {
+			memcpy(data, kmap(page), PAGE_CACHE_SIZE);
+			kunmap(page);
+			page_cache_release(page);
 		} else
 			memset(data, 0, PAGE_CACHE_SIZE);
 		data += PAGE_CACHE_SIZE;
@@ -202,8 +206,6 @@ static int cramfs_fill_super(struct supe
 	sb->s_fs_info = sbi;
 	memset(sbi, 0, sizeof(struct cramfs_sb_info));
 
-	sb_set_blocksize(sb, PAGE_CACHE_SIZE);
-
 	/* Invalidate the read buffers on mount: think disk change.. */
 	down(&read_mutex);
 	for (i = 0; i < READ_BUFFERS; i++)

_