fastfsck patch for 2.2.12

J. E. Rodd (jerodd@rodds.net)
Sun, 17 Oct 1999 23:33:28 -0400


Hello,

I took a look at http://www.suse.cz/development/fastfsck, and wanted
to try their patch. Since my development platform is a sun4m, I couldn't
their patches against 2.3.5 and 2.3.9, so I took the patch for 2.3.9
and worked it into 2.2.12.

So far, it seems stable, and it certainly improved performance of
things like ls -l /usr/doc, rm -rf /var/spool/squid/??, and e2fsck.
Of course, usual warnings about experimental filesystem code apply--
this could trash all your ext2 filesystems without warning.

See the aforementioned URL for more information. Patch against 2.2.12
follows.

Cheers,
J. Rodd

diff -rc linux.vanilla/fs/ext2/inode.c linux/fs/ext2/inode.c
*** linux.vanilla/fs/ext2/inode.c Mon Aug 9 15:04:57 1999
--- linux/fs/ext2/inode.c Sun Oct 17 23:12:58 1999
***************
*** 18,23 ****
--- 18,25 ----
* David S. Miller (davem@caip.rutgers.edu), 1995
* 64-bit file support on 64-bit platforms by Jakub Jelinek
* (jj@sunsite.ms.mff.cuni.cz)
+ * altalloc for speeding up rm/fsck by Pavel Machek
+ * (pavel@suse.cz) sponsored by SuSE
*/

#include <asm/uaccess.h>
***************
*** 103,108 ****
--- 105,130 ----
wait_on_super (inode->i_sb);

#ifdef EXT2_PREALLOCATE
+ if (inode->u.ext2_i.i_alloc_elsewhere) {
+ if (!inode->u.ext2_i.i_elsewhere_goal) {
+ goal = (inode->u.ext2_i.i_block_group *
+ EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block);
+ if (goal > 512)
+ goal -= 512;
+ } else goal = inode->u.ext2_i.i_elsewhere_goal;
+ // printk( "Allocating goal = %d, ", goal );
+ result = ext2_new_block (inode, goal, 0, 0, err);
+ inode->u.ext2_i.i_elsewhere_goal = result;
+ // printk( "got = %d\n", result );
+ if ((result > inode->u.ext2_i.i_next_alloc_goal) &&
+ (result-32 < inode->u.ext2_i.i_next_alloc_goal)) {
+ // printk( "Making room for indirect blocks\n" );
+ inode->u.ext2_i.i_next_alloc_goal += 32;
+ }
+ return result;
+ }
+
if (inode->u.ext2_i.i_prealloc_count &&
(goal == inode->u.ext2_i.i_prealloc_block ||
goal + 1 == inode->u.ext2_i.i_prealloc_block))
***************
*** 146,152 ****

int ext2_bmap (struct inode * inode, int block)
{
! int i;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);

--- 168,174 ----

int ext2_bmap (struct inode * inode, int block)
{
! int i, ret;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);

***************
*** 162,170 ****
--- 184,195 ----
}
if (block < EXT2_NDIR_BLOCKS)
return inode_bmap (inode, block);
+ if (test_opt(inode->i_sb, ALTALLOC))
+ inode->u.ext2_i.i_alloc_elsewhere = 1;
block -= EXT2_NDIR_BLOCKS;
if (block < addr_per_block) {
i = inode_bmap (inode, EXT2_IND_BLOCK);
+ inode->u.ext2_i.i_alloc_elsewhere = 0;
if (!i)
return 0;
return block_bmap (bread (inode->i_dev, i,
***************
*** 178,183 ****
--- 203,209 ----
i = block_bmap (bread (inode->i_dev, i,
inode->i_sb->s_blocksize),
block >> addr_per_block_bits);
+ inode->u.ext2_i.i_alloc_elsewhere = 0;
if (!i)
return 0;
return block_bmap (bread (inode->i_dev, i,
***************
*** 186,203 ****
}
block -= (1 << (addr_per_block_bits * 2));
i = inode_bmap (inode, EXT2_TIND_BLOCK);
! if (!i)
return 0;
i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
block >> (addr_per_block_bits * 2));
! if (!i)
return 0;
i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
(block >> addr_per_block_bits) & (addr_per_block - 1));
! if (!i)
return 0;
! return block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
block & (addr_per_block - 1));
}

static struct buffer_head * inode_getblk (struct inode * inode, int nr,
--- 212,237 ----
}
block -= (1 << (addr_per_block_bits * 2));
i = inode_bmap (inode, EXT2_TIND_BLOCK);
! if (!i) {
! inode->u.ext2_i.i_alloc_elsewhere = 0;
return 0;
+ }
i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
block >> (addr_per_block_bits * 2));
! if (!i) {
! inode->u.ext2_i.i_alloc_elsewhere = 0;
return 0;
+ }
i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
(block >> addr_per_block_bits) & (addr_per_block - 1));
! if (!i) {
! inode->u.ext2_i.i_alloc_elsewhere = 0;
return 0;
! }
! ret = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
block & (addr_per_block - 1));
+ inode->u.ext2_i.i_alloc_elsewhere = 0;
+ return ret;
}

static struct buffer_head * inode_getblk (struct inode * inode, int nr,
***************
*** 252,259 ****
goto repeat;
}
*p = tmp;
! inode->u.ext2_i.i_next_alloc_block = new_block;
! inode->u.ext2_i.i_next_alloc_goal = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocks;
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)
--- 286,295 ----
goto repeat;
}
*p = tmp;
! if (!inode->u.ext2_i.i_alloc_elsewhere) {
! inode->u.ext2_i.i_next_alloc_block = new_block;
! inode->u.ext2_i.i_next_alloc_goal = tmp;
! }
inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocks;
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)
***************
*** 333,340 ****
inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocks;
mark_inode_dirty(inode);
! inode->u.ext2_i.i_next_alloc_block = new_block;
! inode->u.ext2_i.i_next_alloc_goal = tmp;
brelse (bh);
return result;
}
--- 369,378 ----
inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocks;
mark_inode_dirty(inode);
! if (!inode->u.ext2_i.i_alloc_elsewhere) {
! inode->u.ext2_i.i_next_alloc_block = new_block;
! inode->u.ext2_i.i_next_alloc_goal = tmp;
! }
brelse (bh);
return result;
}
***************
*** 517,522 ****
--- 555,562 ----
inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
inode->i_version = ++event;
inode->u.ext2_i.i_new_inode = 0;
+ inode->u.ext2_i.i_alloc_elsewhere = 0;
+ inode->u.ext2_i.i_elsewhere_goal = 0;
inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);
inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
diff -rc linux.vanilla/fs/ext2/super.c linux/fs/ext2/super.c
*** linux.vanilla/fs/ext2/super.c Mon Aug 9 15:04:41 1999
--- linux/fs/ext2/super.c Sun Oct 17 23:13:26 1999
***************
*** 181,186 ****
--- 181,188 ----
}
else if (!strcmp (this_char, "debug"))
set_opt (*mount_options, DEBUG);
+ else if (!strcmp (this_char, "altalloc"))
+ set_opt (*mount_options, ALTALLOC);
else if (!strcmp (this_char, "errors")) {
if (!value || !*value) {
printk ("EXT2-fs: the errors option requires "
diff -rc linux.vanilla/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
*** linux.vanilla/include/linux/ext2_fs.h Mon Aug 9 15:04:41 1999
--- linux/include/linux.vanilla/ext2_fs.h Sun Oct 17 22:41:06 1999
***************
*** 310,315 ****
--- 310,316 ----
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
+ #define EXT2_MOUNT_ALTALLOC 0x0100 /* Alloc indirect blocks close to each other */

#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
diff -rc linux.vanilla/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h
*** linux.vanilla/include/linux/ext2_fs_i.h Thu Apr 2 16:39:51 1998
--- linux/include/linux.vanilla/ext2_fs_i.h Sun Oct 17 22:41:36 1999
***************
*** 37,42 ****
--- 37,44 ----
__u32 i_prealloc_count;
__u32 i_high_size;
int i_new_inode:1; /* Is a freshly allocated inode */
+ int i_alloc_elsewhere:1;
+ __u32 i_elsewhere_goal;
};

#endif /* _LINUX_EXT2_FS_I */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/