Subject: Repeatable mkdir ffs panic (affects both Free- and NetBSD)
To: None <current-users@netbsd.org, freebsd-hackers@freebsd.org>
From: BOUWSMA Beery <freebsd-misuser@dcf77-zeit.netscum.dyndns.dk>
List: current-users
Date: 05/26/2002 15:26:53
[This is sent both to the NetBSD current list, plus the FreeBSD
 hackers list, since I've had this panic on both.  The debug info
 is from FreeBSD, but the /NetBSD/usr/src/sys/ufs/ffs/ffs_alloc.c
 source looks virtually identical.  Please adjust followups as
 appropriate if not relevant to both lists, thankz]


Some background info:  I've `newfs'ed a partition with huge block and
fragment size defaults, which has sometimes given me panics when trying
to create a directory on the fs (I've had no problems filling the fs
with big files).  Now both FreeBSD and NetBSD panic when creating a
directory.  The fs details are
  h: 90194769 28573776    4.2BSD    16384 65536  2968   # (Cyl. 28347 - 117825*)
bash-2.05a# tunefs  -p /dev/ad0s3h
tunefs: soft updates:  (-n)                                enabled
tunefs: maximum contiguous block count: (-a)               1
tunefs: rotational delay between contiguous blocks: (-d)   0 ms
tunefs: maximum blocks per file in a cylinder group: (-e)  16384
tunefs: average file size: (-f)                            67108864
tunefs: average number of files in a directory: (-s)       64
tunefs: minimum percentage of free space: (-m)             8%
tunefs: optimization preference: (-o)                      time

All OS source is from March-ish, since I've been too bus^H^H^Hlazy
to update lately.


Here's the panic I get when trying to `mkdir' a subdirectory on
such a filesystem (top-level `mkdir's work fine) as seen under
FreeBSD:

Fatal trap 18: integer divide fault while in kernel mode
instruction pointer     = 0x8:0xc0201a7d
stack pointer           = 0x10:0xc7213c84
frame pointer           = 0x10:0xc7213cb0
code segment            = base 0x0, limit 0xfffff, type 0x1b
                        = DPL 0, pres 1, def32 1, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 331 (mkdir)
interrupt mask          = none
trap number             = 18
panic: integer divide fault


a trace looks somewhat like this:
[...]
#4  0xc028e626 in trap (frame={tf_fs = 16, tf_es = 16, tf_ds = 16,
      tf_edi = -954122456, tf_esi = 0, tf_ebp = -954123088,
      tf_isp = -954123152, tf_ebx = -1053343744, tf_edx = -1,
      tf_ecx = -692060160, tf_eax = -692060160, tf_trapno = 18, tf_err = 0,
      tf_eip = -1071637891, tf_cs = 8, tf_eflags = 66118,
      tf_esp = -1051781888, tf_ss = -1053343744})
    at /usr/src/sys/i386/i386/trap.c:628
#5  0xc0201a7d in ffs_dirpref (pip=0xc14f1500)
    at /usr/src/sys/ufs/ffs/ffs_alloc.c:710
#6  0xc0201781 in ffs_valloc (pvp=0xc725e800, mode=16877, cred=0xc1509c80,
    vpp=0xc7213d04) at /usr/src/sys/ufs/ffs/ffs_alloc.c:590
#7  0xc0213a22 in ufs_mkdir (ap=0xc7213e6c)
    at /usr/src/sys/ufs/ufs/ufs_vnops.c:1321
#8  0xc0214b75 in ufs_vnoperate (ap=0xc7213e6c)
    at /usr/src/sys/ufs/ufs/ufs_vnops.c:2422
#9  0xc01a0f26 in mkdir (p=0xc6708be0, uap=0xc7213f80) at vnode_if.h:674
[...]

The line of interest appears to be
(kgdb) up 5
#5  0xc0201a7d in ffs_dirpref (pip=0xc14f1500)
    at /usr/src/sys/ufs/ffs/ffs_alloc.c:710
710             maxcontigdirs = min(cgsize / dirsize, 255);


The surrounding k0de looks like
        int cg, prefcg, dirsize, cgsize;
 [...]
        cgsize = fs->fs_fsize * fs->fs_fpg;
        dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir;
        curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0;
        if (dirsize < curdirsize)
                dirsize = curdirsize;
        maxcontigdirs = min(cgsize / dirsize, 255);


If I'm reading this right, my choice of average file size (tunefs -f)
and average files per directory (tunefs -s) bring about this panic:
64*67108864
4294967296
2^32
4294967296

You see, what I have today (where I've reproduced this panic on a
freshly initialized filesystem on a new drive) is a 120GB drive,
where I'm wanting to store a handful of WAV files of several hours
length each, or a bunch of mp3 files of half a day length, so that
the average file size will be well above 64MB.

Given that as today's disks get larger, making storage of big files
the norm, would it be appropriate for me to waddle around in this
section of code, to use 64-bit numbers where appropriate, or is
there a better way that this should be handled?  Like not using
such large values for average file size and the like?


Now, I also get problems (under FreeBSD) when trying to newfs with
a -f fragment size larger than 65536, plus when I try to create as
few inodes as possible, I don't seem to be able to go as small as
I would like (512 inodes/group or something, less than which is 0,
which results in an inode value out of range).  This means that now
I have 17914 free inodes on the 120GB filesystem, when I'll be lucky
to use a couple hundred.  But at least my fsck time, after inducing
the above panic, on this horribly slow machine is but a handful of
seconds, so I can't complain too much...


thanks
barry bouwsma