From owner-freebsd-bugs@FreeBSD.ORG Fri Dec 31 16:00:25 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7A8B5106566C for ; Fri, 31 Dec 2010 16:00:25 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3803C8FC15 for ; Fri, 31 Dec 2010 16:00:25 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oBVG0Pag022594 for ; Fri, 31 Dec 2010 16:00:25 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oBVG0PFe022583; Fri, 31 Dec 2010 16:00:25 GMT (envelope-from gnats) Resent-Date: Fri, 31 Dec 2010 16:00:25 GMT Resent-Message-Id: <201012311600.oBVG0PFe022583@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Pedro F. Giffuni" Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 64471106564A for ; Fri, 31 Dec 2010 15:53:07 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (unknown [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id 4748A8FC0A for ; Fri, 31 Dec 2010 15:53:07 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.4/8.14.4) with ESMTP id oBVFr6de009271 for ; Fri, 31 Dec 2010 15:53:06 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.4/8.14.4/Submit) id oBVFr6jE009270; Fri, 31 Dec 2010 15:53:06 GMT (envelope-from nobody) Message-Id: <201012311553.oBVFr6jE009270@red.freebsd.org> Date: Fri, 31 Dec 2010 15:53:06 GMT From: "Pedro F. Giffuni" To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/153584: Performance fix and cleanups for BSD licensed ext2fs X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Dec 2010 16:00:25 -0000 >Number: 153584 >Category: kern >Synopsis: Performance fix and cleanups for BSD licensed ext2fs >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Dec 31 16:00:24 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Pedro F. Giffuni >Release: 8.2-BETA1 >Organization: >Environment: Non-relevant: I added the BSD-licensed ext2fs to my 8.2 kernel (i386) >Description: Since the adoption of the BSD licensed ext2fs implementation, a performance decrease was observed. Bruce Evans found the source for some of the problems: http://lists.freebsd.org/pipermail/freebsd-fs/2010-September/009589.html In addition to these, some merges from UFS1 have been backported and some style issues have been fixed. See PR 142924 and 143345 for the details. This patch include bde's fixes and applies the basic cleanups from the previous PRs. It also adds back the async mount option as it is operational after the initial BSD licensed backporting: this has been tested as part of the recent GSoC project. >How-To-Repeat: >Fix: Patch follows. Patch attached with submission follows: diff -ru ext2fs.orig/ext2_alloc.c ext2fs/ext2_alloc.c --- ext2fs.orig/ext2_alloc.c 2010-12-29 15:14:06.000000000 +0000 +++ ext2fs/ext2_alloc.c 2010-12-31 10:04:27.000000000 +0000 @@ -59,6 +59,10 @@ int)); static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); +#ifdef FANCY_REALLOC +static int ext2_reallocblks(struct vop_reallocblks_args *); +#endif + /* * Allocate a block in the file system. * @@ -76,7 +80,6 @@ * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ - int ext2_alloc(ip, lbn, bpref, size, cred, bnp) struct inode *ip; @@ -116,6 +119,10 @@ bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2_alloccg); if (bno > 0) { + /* set next_alloc fields as done in block_getblk */ + ip->i_next_alloc_block = lbn; + ip->i_next_alloc_goal = bno; + ip->i_blocks += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; @@ -144,9 +151,13 @@ */ #ifdef FANCY_REALLOC -#include +SYSCTL_NODE(_vfs, OID_AUTO, ext2, CTLFLAG_RW, 0, "EXT2FS filesystem"); + static int doasyncfree = 1; +SYSCTL_INT(_vfs_ext2, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); + static int doreallocblks = 1; +SYSCTL_INT(_vfs_ext2s, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); #ifdef OPT_DEBUG SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); @@ -173,7 +184,7 @@ struct ext2mount *ump; struct cluster_save *buflist; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int32_t start_lbn, end_lbn, soff, newblk, blkno =0; + int32_t start_lbn, end_lbn, soff, newblk, blkno; int i, len, start_lvl, end_lvl, pref, ssize; vp = ap->a_vp; @@ -223,7 +234,7 @@ * Find the preferred location for the cluster. */ EXT2_LOCK(ump); - pref = ext2_blkpref(ip, start_lbn, soff, sbap, blkno); + pref = ext2_blkpref(ip, start_lbn, soff, sbap, blkno=0); /* * If the block range spans two block maps, get the second map. */ @@ -625,7 +636,7 @@ struct m_ext2fs *fs; struct buf *bp; struct ext2mount *ump; - int error, bno, start, end, loc; + int error, bno; char *bbp; /* XXX ondisk32 */ fs = ip->i_e2fs; @@ -658,26 +669,7 @@ /* * no blocks in the requested cylinder, so take next * available one in this cylinder group. - * first try to get 8 contigous blocks, then fall back to a single - * block. */ - if (bpref) - start = dtogd(fs, bpref) / NBBY; - else - start = 0; - end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; - for (loc = start; loc < end; loc++) { - if (bbp[loc] == 0) { - bno = loc * NBBY; - goto gotit; - } - } - for (loc = 0; loc < start; loc++) { - if (bbp[loc] == 0) { - bno = loc * NBBY; - goto gotit; - } - } bno = ext2_mapsearch(fs, bbp, bpref); if (bno < 0){ diff -ru ext2fs.orig/ext2_dinode.h ext2fs/ext2_dinode.h --- ext2fs.orig/ext2_dinode.h 2010-12-29 15:14:23.000000000 +0000 +++ ext2fs/ext2_dinode.h 2010-12-30 23:18:21.000000000 +0000 @@ -32,6 +32,18 @@ #define e2di_size_high e2di_dacl /* + * Special inode numbers + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes and bad blocks are normally linked to inode 1, thus + * the root inode is 2. + * Inode 3 to 10 are reserved in ext2fs. + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ + +/* * Inode flags * The current implementation uses only EXT2_IMMUTABLE and EXT2_APPEND flags */ @@ -74,5 +86,5 @@ u_int32_t e2di_linux_reserved3; /* 124 */ }; -#endif /* _FS_EXT2FS_EXT2_DINODE_H_ */ +#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */ diff -ru ext2fs.orig/ext2_lookup.c ext2fs/ext2_lookup.c --- ext2fs.orig/ext2_lookup.c 2010-12-29 15:14:51.000000000 +0000 +++ ext2fs/ext2_lookup.c 2010-12-30 23:16:06.000000000 +0000 @@ -347,6 +347,7 @@ slotneeded = (sizeof(struct direct) - MAXNAMLEN + cnp->cn_namelen + 3) &~ 3; */ } + bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; /* * If there is cached information on a previous search of @@ -359,7 +360,6 @@ * profiling time and hence has been removed in the interest * of simplicity. */ - bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; if (nameiop != LOOKUP || i_diroff == 0 || i_diroff > dp->i_size) { entryoffsetinblock = 0; diff -ru ext2fs.orig/ext2_vfsops.c ext2fs/ext2_vfsops.c --- ext2fs.orig/ext2_vfsops.c 2010-12-29 15:15:11.000000000 +0000 +++ ext2fs/ext2_vfsops.c 2010-12-31 10:01:28.000000000 +0000 @@ -95,9 +95,9 @@ static int compute_sb_data(struct vnode * devvp, struct ext2fs * es, struct m_ext2fs * fs); -static const char *ext2_opts[] = { "from", "export", "acls", "noexec", - "noatime", "union", "suiddir", "multilabel", "nosymfollow", - "noclusterr", "noclusterw", "force", NULL }; +static const char *ext2_opts[] = { "acls", "async", "noatime", "noclusterr", + "noclusterw", "noexec", "export", "force", "from", "multilabel", + "suiddir", "nosymfollow", "sync", "union", NULL }; /* * VFS Operations. @@ -945,9 +945,8 @@ } /* - * Finish inode initialization now that aliasing has been resolved. + * Finish inode initialization. */ - ip->i_devvp = ump->um_devvp; /* * Set up a generation number for this inode if it does not diff -ru ext2fs.orig/ext2fs.h ext2fs/ext2fs.h --- ext2fs.orig/ext2fs.h 2010-12-29 15:15:21.000000000 +0000 +++ ext2fs/ext2fs.h 2010-12-30 23:18:21.000000000 +0000 @@ -39,22 +39,6 @@ #include -/* - * Special inode numbers - */ -#define EXT2_BAD_INO 1 /* Bad blocks inode */ -#define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ -#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -/* First non-reserved inode for old ext2 filesystems */ -#define E2FS_REV0_FIRST_INO 11 - -/* - * The second extended file system magic number - */ -#define E2FS_MAGIC 0xEF53 - #if defined(_KERNEL) /* * FreeBSD passes the pointer to the in-core struct with relevant @@ -129,7 +113,9 @@ u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */ char e2fs_vname[16]; /* volume name */ char e2fs_fsmnt[64]; /* name mounted on */ - u_int32_t e2fs_algo; /* For comcate for dir */ + u_int32_t e2fs_algo; /* for compression */ + uint8_t e2fs_prealloc; /* # of blocks to preallocate */ + uint8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */ u_int16_t e2fs_reserved_ngdb; /* # of reserved gd blocks for resize */ u_int32_t reserved2[204]; }; @@ -153,8 +139,8 @@ uint32_t e2fs_bshift; /* calc of logical block no */ int32_t e2fs_bmask; /* calc of block offset */ int32_t e2fs_bpg; /* Number of blocks per group */ - int64_t e2fs_qbmask; /* = s_blocksize -1 */ - uint32_t e2fs_fsbtodb; /* Shift to get disk block */ + int64_t e2fs_qbmask; /* = s_blocksize -1 */ + uint32_t e2fs_fsbtodb; /* Shift to get disk block */ uint32_t e2fs_ipg; /* Number of inodes per group */ uint32_t e2fs_ipb; /* Number of inodes per block */ uint32_t e2fs_itpg; /* Number of inode table per group */ @@ -169,8 +155,8 @@ int32_t e2fs_isize; /* Size of inode */ uint32_t e2fs_mount_opt; uint32_t e2fs_blocksize_bits; + uint8_t *e2fs_contigdirs; /* (u) # of contig. allocated dirs */ uint32_t e2fs_total_dir; /* Total number of directories */ - uint8_t *e2fs_contigdirs; char e2fs_wasvalid; /* valid at mount time */ off_t e2fs_maxfilesize; struct ext2_gd *e2fs_gd; /* Group Descriptors */ @@ -182,6 +168,14 @@ #define E2FS_DATE "95/08/09" #define E2FS_VERSION "0.5b" +/* First non-reserved inode for old ext2 filesystems */ +#define E2FS_REV0_FIRST_INO 11 + +/* + * The second extended file system magic number + */ +#define E2FS_MAGIC 0xEF53 + /* * Revision levels */ @@ -197,6 +191,7 @@ * compatible/incompatible features */ #define EXT2F_COMPAT_PREALLOC 0x0001 +#define EXT2F_COMPAT_HASJOURNAL 0x0004 #define EXT2F_COMPAT_RESIZE 0x0010 #define EXT2F_ROCOMPAT_SPARSESUPER 0x0001 @@ -326,4 +321,4 @@ #endif -#endif /* _LINUX_EXT2_FS_H */ +#endif /* !_FS_EXT2FS_EXT2FS_H */ diff -ru ext2fs.orig/inode.h ext2fs/inode.h --- ext2fs.orig/inode.h 2010-12-29 15:15:30.000000000 +0000 +++ ext2fs/inode.h 2010-12-30 23:16:06.000000000 +0000 @@ -62,7 +62,6 @@ */ struct inode { struct vnode *i_vnode;/* Vnode associated with this inode. */ - struct vnode *i_devvp;/* Vnode for block I/O. */ struct ext2mount *i_ump; u_int32_t i_flag; /* flags, see below */ ino_t i_number; /* The identity of the inode. */ @@ -143,6 +142,9 @@ #define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */ #define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the suspension finished */ + +#define i_devvp i_ump->um_devvp + #ifdef _KERNEL /* * Structure used to pass around logical block paths generated by >Release-Note: >Audit-Trail: >Unformatted: