From owner-freebsd-bugs@FreeBSD.ORG Tue Aug 30 23:50:27 2005 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 093EE16A41F for ; Tue, 30 Aug 2005 23:50:27 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 56C1743D53 for ; Tue, 30 Aug 2005 23:50:26 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id j7UNoPqK020887 for ; Tue, 30 Aug 2005 23:50:25 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id j7UNoPRT020885; Tue, 30 Aug 2005 23:50:25 GMT (envelope-from gnats) Resent-Date: Tue, 30 Aug 2005 23:50:25 GMT Resent-Message-Id: <200508302350.j7UNoPRT020885@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, Dmitry Pryanishnikov Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F0CEC16A41F for ; Tue, 30 Aug 2005 23:50:08 +0000 (GMT) (envelope-from dmitry@atlantis.dp.ua) Received: from postman.atlantis.dp.ua (postman.atlantis.dp.ua [193.108.47.1]) by mx1.FreeBSD.org (Postfix) with ESMTP id 167EB43D49 for ; Tue, 30 Aug 2005 23:50:07 +0000 (GMT) (envelope-from dmitry@atlantis.dp.ua) Received: from smtp.atlantis.dp.ua (smtp.atlantis.dp.ua [193.108.46.231]) by postman.atlantis.dp.ua (8.13.1/8.13.1) with ESMTP id j7UNnvv8024039 for ; Wed, 31 Aug 2005 02:49:57 +0300 (EEST) (envelope-from dmitry@atlantis.dp.ua) Message-Id: <20050831024905.M23916@atlantis.atlantis.dp.ua> Date: Wed, 31 Aug 2005 02:49:57 +0300 (EEST) From: Dmitry Pryanishnikov To: FreeBSD-gnats-submit@FreeBSD.org Cc: Subject: kern/85503: panic: wrong dirclust using msdosfs in RELENG_6 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: Tue, 30 Aug 2005 23:50:27 -0000 >Number: 85503 >Category: kern >Synopsis: panic: wrong dirclust using msdosfs in RELENG_6 >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Aug 30 23:50:25 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Dmitry Pryanishnikov >Release: FreeBSD 6.0-BETA3 i386 >Organization: Atlantis ISP >Environment: System: FreeBSD 6.0-BETA3 #0: Mon Aug 22 22:59:46 UTC 2005 root@harlow.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 Large enough (24Gb) FAT32 slice. >Description: RELENG_6 panics during 'du' run against large FAT32 slice with many directories. This is the specific regression in RELENG_6 against earlier code (e.g. RELENG_5). Here is the crash dump analysis: Unread portion of the kernel message buffer: panic: wrong dirclust (kgdb) where ... #12 0xc06321f7 in panic (fmt=0x282
) at /usr/src/sys/kern/kern_shutdown.c:537 #13 0xc05eebaf in deget (pmp=0xc14d9000, dirclust=673396, diroffset=0, depp=0xc6ffda00) at /usr/src/sys/fs/msdosfs/msdosfs_denode.c:142 #14 0xc05f143d in msdosfs_lookup (ap=0x0) at /usr/src/sys/fs/msdosfs/msdosfs_lookup.c:534 #15 0xc07fe1da in VOP_CACHEDLOOKUP_APV (vop=0x0, a=0xc6ffda7c) at vnode_if.c:150 #16 0xc067b66e in vfs_cache_lookup (ap=0x0) at vnode_if.h:82 #17 0xc07fe123 in VOP_LOOKUP_APV (vop=0xc08b55e0, a=0xc6ffdb14) at vnode_if.c:99 #18 0xc067f53e in lookup (ndp=0xc6ffdba0) at vnode_if.h:56 #19 0xc067ef06 in namei (ndp=0xc6ffdba0) at /usr/src/sys/kern/vfs_lookup.c:201 #20 0xc068aea7 in kern_lstat (td=0xc1376c00, path=0x0, pathseg=UIO_USERSPACE, sbp=0xc6ffdc74) at /usr/src/sys/kern/vfs_syscalls.c:2102 #21 0xc068ae43 in lstat (td=0xc1376c00, uap=0xc6ffdd04) at /usr/src/sys/kern/vfs_syscalls.c:2086 ... (kgdb) fr 13 #13 0xc05eebaf in deget (pmp=0xc14d9000, dirclust=673396, diroffset=0, depp=0xc6ffda00) at /usr/src/sys/fs/msdosfs/msdosfs_denode.c:142 142 KASSERT((*depp)->de_dirclust == dirclust, ("wrong dirclust")); (kgdb) list ... 140 if (nvp != NULL) { 141 *depp = VTODE(nvp); 142 KASSERT((*depp)->de_dirclust == dirclust, ("wrong dirclust")); Looking into the source (sys/fs/msdosfs/msdosfs_denode.c, function deget) gives the following: uint64_t inode; // Our "inode" number must have 64 bits ... inode = pmp->pm_bpcluster * dirclust + diroffset; This is the apparent place of the error: all members of right-hand expression are u_long (32 bits on i386), so inode will always be evaluated as 32-bit integer. Check this: (kgdb) print dirclust $2 = 673396 (kgdb) print pmp->pm_bpcluster $3 = 16384 (kgdb) print diroffset $4 = 0 (kgdb) print inode $5 = 2442985472 Actually 16384 * 673396 + 0 should give us 11032920064. So vfs_hash_get() gave us another vnode with the same low-order 32 bits of inode: (kgdb) print **depp $7 = {de_vnode = 0xc1805aa0, de_flag = 0, de_dev = 0x0, de_dirclust = 149108, de_diroffset = 0, de_fndoffset = 0, de_fndcnt = 0, de_refcnt = 1, de_pmp = 0xc14d9000, de_Name = ". ", de_Attributes = 16 '\020', de_LowerCase = 0 '\0', de_CHun = 47 '/', de_CTime = 39991, de_CDate = 12972, de_ADate = 12972, de_MTime = 39991, de_MDate = 12972, de_StartCluster = 149108, de_FileSize = 16384, de_fc = {{fc_frcn = 0, fc_fsrcn = 149108}, {fc_frcn = 0, fc_fsrcn = 149108}}, de_modrev = 140731985215, de_lockf = 0x0, de_inode = 2442985472} Original directory cluster gives (in 32-bit expression): (kgdb) print /x 673396*16384 $8 = 0x919d0000 This (incorrect) one gives the same: (kgdb) print /x 149108*16384 $9 = 0x919d0000 >How-To-Repeat: Just install 6.0-BETA3 on i386 machine, mount large FAT32 partition with many directories and run 'du' against this partition. >Fix: The primary bug (evaluation of the inode) can easily be fixed using cast: inode = (uint64_t) pmp->pm_bpcluster * dirclust + diroffset; But the real problem is that the second argument of vfs_hash_get() also has the same 32-bit limitation on i386 (type u_int, 32 bits), so I think it's the author of vfs_hash_get() approach (phk) who should decide whether to promote uint64_t to vfs_hash_get() or decouple msdosfs from this function at all. >Release-Note: >Audit-Trail: >Unformatted: