description:      _
product_versions: Linux linux-260-test8-efs
changelog:        _
URL:              _
requires: _
conflicts:        _
maintainer:       _
patch_name:       efs_blocksize3d.patch
author:           Randy.Dunlap <rddunlap@osdl.org>
patch_version:    2003-10-26.21:56:06

diffstat:=

diff -Naurp ./fs/efs/dir.c~blocksize ./fs/efs/dir.c
--- ./fs/efs/dir.c~blocksize	2003-10-17 14:43:20.000000000 -0700
+++ ./fs/efs/dir.c	2003-10-26 21:47:35.000000000 -0800
@@ -19,10 +19,12 @@ struct inode_operations efs_dir_inode_op
 	.lookup		= efs_lookup,
 };
 
-static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
+static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct buffer_head *bh;
-
+	char			*blockbuf;
+	unsigned long		blockbuf_offset;
 	struct efs_dir		*dirblock;
 	struct efs_dentry	*dirslot;
 	efs_ino_t		inodenum;
@@ -44,14 +46,15 @@ static int efs_readdir(struct file *filp
 	/* look at all blocks */
 	while (block < inode->i_blocks) {
 		/* read the dir block */
-		bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
+		bh = efs_bread(inode->i_sb, efs_bmap(inode, block), &blockbuf_offset);
 
 		if (!bh) {
 			printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
 			break;
 		}
 
-		dirblock = (struct efs_dir *) bh->b_data; 
+		blockbuf = bh->b_data + blockbuf_offset;
+		dirblock = (struct efs_dir *) blockbuf; 
 
 		if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
 			printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
@@ -65,8 +68,11 @@ static int efs_readdir(struct file *filp
 				continue;
 			}
 
-			dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
+			dirslot  = (struct efs_dentry *) (blockbuf
+					+ EFS_SLOTAT(dirblock, slot));
 
+			printk(KERN_DEBUG "efs_readdir: dirslot ptr=%p for slot %d\n",
+					dirslot, slot);
 			inodenum = be32_to_cpu(dirslot->inode);
 			namelen  = dirslot->namelen;
 			nameptr  = dirslot->name;
@@ -110,4 +116,3 @@ out:
 	unlock_kernel();
 	return 0;
 }
-
diff -Naurp ./fs/efs/file.c~blocksize ./fs/efs/file.c
--- ./fs/efs/file.c~blocksize	2003-10-17 14:43:15.000000000 -0700
+++ ./fs/efs/file.c	2003-10-22 19:31:04.000000000 -0700
@@ -22,8 +22,8 @@ int efs_get_block(struct inode *inode, s
 		/*
 		 * i have no idea why this happens as often as it does
 		 */
-		printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
-			block,
+		printk(KERN_WARNING "EFS: bmap(): block %llu >= %ld (filesize %llu)\n",
+			(unsigned long long)iblock,
 			inode->i_blocks,
 			inode->i_size);
 #endif
@@ -35,8 +35,8 @@ int efs_get_block(struct inode *inode, s
 	return 0;
 }
 
-int efs_bmap(struct inode *inode, efs_block_t block) {
-
+int efs_bmap(struct inode *inode, efs_block_t block)
+{
 	if (block < 0) {
 		printk(KERN_WARNING "EFS: bmap(): block < 0\n");
 		return 0;
@@ -48,8 +48,8 @@ int efs_bmap(struct inode *inode, efs_bl
 		/*
 		 * i have no idea why this happens as often as it does
 		 */
-		printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
-			block,
+		printk(KERN_WARNING "EFS: bmap(): block %ld >= %ld (filesize %llu)\n",
+			(long)block,
 			inode->i_blocks,
 			inode->i_size);
 #endif
diff -Naurp ./fs/efs/inode.c~blocksize ./fs/efs/inode.c
--- ./fs/efs/inode.c~blocksize	2003-10-17 14:43:03.000000000 -0700
+++ ./fs/efs/inode.c	2003-10-26 20:12:14.000000000 -0800
@@ -9,6 +9,7 @@
 
 #include <linux/efs_fs.h>
 #include <linux/efs_fs_sb.h>
+#include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -53,6 +54,8 @@ void efs_read_inode(struct inode *inode)
 	dev_t device;
 	u32 rdev;
 	struct buffer_head *bh;
+	char *blockbuf;
+	unsigned long blockbuf_offset;
 	struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
 	struct efs_inode_info *in = INODE_INFO(inode);
 	efs_block_t block, offset;
@@ -81,13 +84,14 @@ void efs_read_inode(struct inode *inode)
 			(EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
 		sizeof(struct efs_dinode);
 
-	bh = sb_bread(inode->i_sb, block);
+	bh = efs_bread(inode->i_sb, block, &blockbuf_offset);
 	if (!bh) {
 		printk(KERN_WARNING "EFS: bread() failed at block %d\n", block);
 		goto read_inode_error;
 	}
 
-	efs_inode = (struct efs_dinode *) (bh->b_data + offset);
+	blockbuf = bh->b_data + blockbuf_offset;
+	efs_inode = (struct efs_dinode *) (blockbuf + offset);
     
 	inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
 	inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
@@ -191,11 +195,13 @@ efs_extent_check(efs_extent *ptr, efs_bl
 	}
 }
 
-efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
+efs_block_t efs_map_block(struct inode *inode, efs_block_t block)
+{
 	struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
 	struct efs_inode_info *in = INODE_INFO(inode);
 	struct buffer_head    *bh = NULL;
-
+	char *blockbuf = NULL;
+	unsigned long blockbuf_offset;
 	int cur, last, first = 1;
 	int ibase, ioffset, dirext, direxts, indext, indexts;
 	efs_block_t iblock, result = 0, lastblock = 0;
@@ -271,11 +277,12 @@ efs_block_t efs_map_block(struct inode *
 		if (first || lastblock != iblock) {
 			if (bh) brelse(bh);
 
-			bh = sb_bread(inode->i_sb, iblock);
+			bh = efs_bread(inode->i_sb, iblock, &blockbuf_offset);
 			if (!bh) {
 				printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock);
 				return 0;
 			}
+			blockbuf = bh->b_data + blockbuf_offset;
 #ifdef DEBUG
 			printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock);
 #endif
@@ -283,7 +290,7 @@ efs_block_t efs_map_block(struct inode *
 			lastblock = iblock;
 		}
 
-		exts = (efs_extent *) bh->b_data;
+		exts = (efs_extent *) blockbuf;
 
 		extent_copy(&(exts[ioffset]), &ext);
 
@@ -304,4 +311,21 @@ efs_block_t efs_map_block(struct inode *
 	return 0;
 }  
 
+struct buffer_head *efs_bread(struct super_block *sb,
+				sector_t block, unsigned long *blockbuf_offset)
+{
+	struct efs_sb_info *sinfo = SUPER_INFO(sb);
+	unsigned blocking = sinfo->blocking;
+	sector_t phys_sector;
+
+	if (blocking <= 1) {
+		*blockbuf_offset = 0;
+		return sb_bread(sb, block);
+	}
+
+	phys_sector = block;
+	*blockbuf_offset = sector_div(phys_sector, blocking) * EFS_BLOCKSIZE;
+	return sb_bread(sb, phys_sector);
+}
+
 MODULE_LICENSE("GPL");
diff -Naurp ./fs/efs/namei.c~blocksize ./fs/efs/namei.c
--- ./fs/efs/namei.c~blocksize	2003-10-17 14:43:20.000000000 -0700
+++ ./fs/efs/namei.c	2003-10-22 20:53:03.000000000 -0700
@@ -12,8 +12,9 @@
 #include <linux/smp_lock.h>
 
 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
-	struct buffer_head *bh;
-
+	struct buffer_head	*bh;
+	char			*blockbuf;
+	unsigned long		blockbuf_offset;
 	int			slot, namelen;
 	char			*nameptr;
 	struct efs_dir		*dirblock;
@@ -26,13 +27,14 @@ static efs_ino_t efs_find_entry(struct i
 
 	for(block = 0; block < inode->i_blocks; block++) {
 
-		bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
+		bh = efs_bread(inode->i_sb, efs_bmap(inode, block), &blockbuf_offset);
 		if (!bh) {
 			printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block);
 			return 0;
 		}
     
-		dirblock = (struct efs_dir *) bh->b_data;
+		blockbuf = bh->b_data + blockbuf_offset;
+		dirblock = (struct efs_dir *) blockbuf;
 
 		if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
 			printk(KERN_ERR "EFS: find_entry(): invalid directory block\n");
@@ -41,7 +43,7 @@ static efs_ino_t efs_find_entry(struct i
 		}
 
 		for(slot = 0; slot < dirblock->slots; slot++) {
-			dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
+			dirslot  = (struct efs_dentry *) (blockbuf + EFS_SLOTAT(dirblock, slot));
 
 			namelen  = dirslot->namelen;
 			nameptr  = dirslot->name;
@@ -74,4 +76,3 @@ struct dentry *efs_lookup(struct inode *
 	d_add(dentry, inode);
 	return NULL;
 }
-
diff -Naurp ./fs/efs/super.c~blocksize ./fs/efs/super.c
--- ./fs/efs/super.c~blocksize	2003-10-17 14:43:25.000000000 -0700
+++ ./fs/efs/super.c	2003-10-22 21:00:26.000000000 -0700
@@ -210,6 +210,9 @@ int efs_fill_super(struct super_block *s
 {
 	struct efs_sb_info *sb;
 	struct buffer_head *bh;
+	char *blockbuf;
+	unsigned long blockbuf_offset;
+	unsigned long blocksize;
 
  	sb = kmalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
 	if (!sb)
@@ -217,40 +220,49 @@ int efs_fill_super(struct super_block *s
 	s->s_fs_info = sb;
 	memset(sb, 0, sizeof(struct efs_sb_info));
  
-	s->s_magic		= EFS_SUPER_MAGIC;
-	if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
-		printk(KERN_ERR "EFS: device does not support %d byte blocks\n",
-			EFS_BLOCKSIZE);
-		goto out_no_fs_ul;
-	}
-  
+	s->s_magic   = EFS_SUPER_MAGIC;
+	sb->blocking = 1;
+	for (blocksize = EFS_BLOCKSIZE; blocksize <= 4 * EFS_BLOCKSIZE;
+			blocksize += blocksize, sb->blocking += sb->blocking) {
+		if (!sb_set_blocksize(s, blocksize))
+			printk(KERN_ERR "EFS: device does not support %ld byte blocks\n",
+				blocksize);
+		else
+			goto efs_have_blocksize;
+	}
+	goto out_no_fs_ul;
+
+efs_have_blocksize:
+	printk(KERN_DEBUG "EFS: using blocksize = %ld, blocking factor = %d\n",
+			blocksize, sb->blocking);
 	/* read the vh (volume header) block */
-	bh = sb_bread(s, 0);
-
+	bh = efs_bread(s, 0, &blockbuf_offset);
 	if (!bh) {
 		printk(KERN_ERR "EFS: cannot read volume header\n");
 		goto out_no_fs_ul;
 	}
+	blockbuf = bh->b_data + blockbuf_offset;
 
 	/*
 	 * if this returns zero then we didn't find any partition table.
 	 * this isn't (yet) an error - just assume for the moment that
 	 * the device is valid and go on to search for a superblock.
 	 */
-	sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
+	sb->fs_start = efs_validate_vh((struct volume_header *) blockbuf);
 	brelse(bh);
 
 	if (sb->fs_start == -1) {
 		goto out_no_fs_ul;
 	}
 
-	bh = sb_bread(s, sb->fs_start + EFS_SUPER);
+	bh = efs_bread(s, sb->fs_start + EFS_SUPER, &blockbuf_offset);
 	if (!bh) {
 		printk(KERN_ERR "EFS: cannot read superblock\n");
 		goto out_no_fs_ul;
 	}
-		
-	if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
+	blockbuf = bh->b_data + blockbuf_offset;
+
+	if (efs_validate_super(sb, (struct efs_super *) blockbuf)) {
 #ifdef DEBUG
 		printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
 #endif
@@ -301,4 +313,3 @@ int efs_statfs(struct super_block *s, st
 
 	return 0;
 }
-
diff -Naurp ./fs/efs/symlink.c~blocksize ./fs/efs/symlink.c
--- ./fs/efs/symlink.c~blocksize	2003-10-17 14:43:16.000000000 -0700
+++ ./fs/efs/symlink.c	2003-10-22 20:55:20.000000000 -0700
@@ -16,6 +16,8 @@ static int efs_symlink_readpage(struct f
 {
 	char *link = kmap(page);
 	struct buffer_head * bh;
+	char *blockbuf;
+	unsigned long blockbuf_offset;
 	struct inode * inode = page->mapping->host;
 	efs_block_t size = inode->i_size;
 	int err;
@@ -27,16 +29,18 @@ static int efs_symlink_readpage(struct f
 	lock_kernel();
 	/* read first 512 bytes of link target */
 	err = -EIO;
-	bh = sb_bread(inode->i_sb, efs_bmap(inode, 0));
+	bh = efs_bread(inode->i_sb, efs_bmap(inode, 0), &blockbuf_offset);
 	if (!bh)
 		goto fail;
-	memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
+	blockbuf = bh->b_data + blockbuf_offset;
+	memcpy(link, blockbuf, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
 	brelse(bh);
 	if (size > EFS_BLOCKSIZE) {
-		bh = sb_bread(inode->i_sb, efs_bmap(inode, 1));
+		bh = efs_bread(inode->i_sb, efs_bmap(inode, 1), &blockbuf_offset);
 		if (!bh)
 			goto fail;
-		memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
+		blockbuf = bh->b_data + blockbuf_offset;
+		memcpy(link + EFS_BLOCKSIZE, blockbuf, size - EFS_BLOCKSIZE);
 		brelse(bh);
 	}
 	link[size] = '\0';
diff -Naurp ./include/linux/efs_fs.h~blocksize ./include/linux/efs_fs.h
--- ./include/linux/efs_fs.h~blocksize	2003-10-17 14:43:04.000000000 -0700
+++ ./include/linux/efs_fs.h	2003-10-22 19:30:27.000000000 -0700
@@ -10,6 +10,7 @@
 #define __EFS_FS_H__
 
 #define EFS_VERSION "1.0a"
+#define DEBUG	1	/* rddunlap */
 
 static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aeschi.ch.eu.org>";
 
@@ -48,5 +49,7 @@ extern efs_block_t efs_map_block(struct 
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int efs_bmap(struct inode *, int);
+extern struct buffer_head *efs_bread(struct super_block *sb,
+				sector_t block, unsigned long *bh_offset);
 
 #endif /* __EFS_FS_H__ */
diff -Naurp ./include/linux/efs_fs_sb.h~blocksize ./include/linux/efs_fs_sb.h
--- ./include/linux/efs_fs_sb.h~blocksize	2003-10-17 14:43:20.000000000 -0700
+++ ./include/linux/efs_fs_sb.h	2003-10-21 20:48:22.000000000 -0700
@@ -56,6 +56,7 @@ struct efs_sb_info {
 	int32_t	inode_free;	/* # of free inodes */
 	short	inode_blocks;	/* # of blocks used for inodes in every grp */
 	short	total_groups;	/* # of groups */
+	int32_t	blocking;	/* number of logical blocks per physical block */
 };
 
 #endif /* __EFS_FS_SB_H__ */
