When running 'make regress' in tools/regression/tmpfs the following panic occurs: panic: Assertion pages > 0 failed at /usr/src/sys/modules/tmpfs/../../fs/tmpfs/tmpfs_vfsops.c:246 (kgdb) bt #0 doadump () at pcpu.h:246 #1 0xc08801de in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:416 #2 0xc08804b2 in panic (fmt=Variable "fmt" is not available. ) at /usr/src/sys/kern/kern_shutdown.c:579 #3 0xc4de9385 in tmpfs_mount (mp=0xc4966000) at /usr/src/sys/modules/tmpfs/../../fs/tmpfs/tmpfs_vfsops.c:246 #4 0xc09097c2 in vfs_donmount (td=0xc497b000, fsflags=0, fsoptions=0xc4c4f100) at /usr/src/sys/kern/vfs_mount.c:984 #5 0xc090aec5 in nmount (td=0xc497b000, uap=0xe6b60cf8) at /usr/src/sys/kern/vfs_mount.c:420 #6 0xc0bb0143 in syscall (frame=0xe6b60d38) at /usr/src/sys/i386/i386/trap.c:1071 #7 0xc0b929b0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #8 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) How-To-Repeat: run 'make regress' in /usr/src/tools/regression/tmpfs
Responsible Changed From-To: freebsd-bugs->freebsd-fs Over to maintainer(s).
I wasn't able to trigger it on amd64, but there were several integer overflow bugs. Besides there was inconsistency in setting max values. Max pages was set to SIZE_MAX (if no value provided by user), but max file size depended on available swap/memory at the moment of mounting filesystem. I've set max file size to 4GB (of memory limit set by user). It can be changed to uint64_t max, but using 4GB seems to be sufficient limit to prevent resource exhaustion. Would you try this patch, I have no i386 system running to test it.
State Changed From-To: open->feedback The reported panic should not occur after r201773. Can you confirm?
Responsible Changed From-To: freebsd-fs->jh I'll try to look at the other issues raised by Gleb Kurtsou.
Sorry for the delay in replying. I only managed to cause the panic once, and was unable to reproduce the crash when I tried again later. -- Bruce Cran
Author: jh Date: Wed Jan 20 16:56:20 2010 New Revision: 202708 URL: http://svn.freebsd.org/changeset/base/202708 Log: - Change the type of nodes_max to u_int and use "%u" format string to convert its value. [1] - Set default tm_nodes_max to min(pages + 3, UINT32_MAX). It's more reasonable than the old four nodes per page (with page size 4096) because non-empty regular files always use at least one page. This fixes possible overflow in the calculation. [2] - Don't allow more than tm_nodes_max nodes allocated in tmpfs_alloc_node(). PR: kern/138367 Suggested by: bde [1], Gleb Kurtsou [2] Approved by: trasz (mentor) Modified: head/sys/fs/tmpfs/tmpfs_subr.c head/sys/fs/tmpfs/tmpfs_vfsops.c Modified: head/sys/fs/tmpfs/tmpfs_subr.c ============================================================================== --- head/sys/fs/tmpfs/tmpfs_subr.c Wed Jan 20 16:50:13 2010 (r202707) +++ head/sys/fs/tmpfs/tmpfs_subr.c Wed Jan 20 16:56:20 2010 (r202708) @@ -93,7 +93,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp MPASS(IFF(type == VLNK, target != NULL)); MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); - if (tmp->tm_nodes_inuse > tmp->tm_nodes_max) + if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max) return (ENOSPC); nnode = (struct tmpfs_node *)uma_zalloc_arg( Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c ============================================================================== --- head/sys/fs/tmpfs/tmpfs_vfsops.c Wed Jan 20 16:50:13 2010 (r202707) +++ head/sys/fs/tmpfs/tmpfs_vfsops.c Wed Jan 20 16:56:20 2010 (r202708) @@ -182,10 +182,10 @@ tmpfs_mount(struct mount *mp) struct tmpfs_mount *tmp; struct tmpfs_node *root; size_t pages, mem_size; - ino_t nodes; + uint32_t nodes; int error; /* Size counters. */ - ino_t nodes_max; + u_int nodes_max; u_quad_t size_max; /* Root node attributes. */ @@ -223,7 +223,7 @@ tmpfs_mount(struct mount *mp) if (mp->mnt_cred->cr_ruid != 0 || vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1) root_mode = va.va_mode; - if (vfs_scanopt(mp->mnt_optnew, "inodes", "%d", &nodes_max) != 1) + if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1) nodes_max = 0; if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1) size_max = 0; @@ -245,9 +245,12 @@ tmpfs_mount(struct mount *mp) pages = howmany(size_max, PAGE_SIZE); MPASS(pages > 0); - if (nodes_max <= 3) - nodes = 3 + pages * PAGE_SIZE / 1024; - else + if (nodes_max <= 3) { + if (pages > UINT32_MAX - 3) + nodes = UINT32_MAX; + else + nodes = pages + 3; + } else nodes = nodes_max; MPASS(nodes >= 3); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: feedback->patched The panic should should be fixed by r201773. I will propose a different change for maximum file size.
Author: jh Date: Tue Mar 8 17:27:36 2011 New Revision: 219401 URL: http://svn.freebsd.org/changeset/base/219401 Log: MFC r201773: - Change the type of size_max to u_quad_t because its value is converted with vfs_scanopt(9) using the "%qu" format string. - Limit the maximum value of size_max to (SIZE_MAX - PAGE_SIZE) to prevent overflow in howmany() macro. PR: kern/141194 MFC r202187: - Fix some style bugs in tmpfs_mount(). - Remove a stale comment about tmpfs_mem_info() 'total' argument. MFC r202708: - Change the type of nodes_max to u_int and use "%u" format string to convert its value. - Set default tm_nodes_max to min(pages + 3, UINT32_MAX). It's more reasonable than the old four nodes per page (with page size 4096) because non-empty regular files always use at least one page. This fixes possible overflow in the calculation. - Don't allow more than tm_nodes_max nodes allocated in tmpfs_alloc_node(). PR: kern/138367 Modified: stable/8/sys/fs/tmpfs/tmpfs.h stable/8/sys/fs/tmpfs/tmpfs_subr.c stable/8/sys/fs/tmpfs/tmpfs_vfsops.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/fs/tmpfs/tmpfs.h ============================================================================== --- stable/8/sys/fs/tmpfs/tmpfs.h Tue Mar 8 17:00:31 2011 (r219400) +++ stable/8/sys/fs/tmpfs/tmpfs.h Tue Mar 8 17:27:36 2011 (r219401) @@ -476,10 +476,6 @@ int tmpfs_truncate(struct vnode *, off_t * Returns information about the number of available memory pages, * including physical and virtual ones. * - * If 'total' is TRUE, the value returned is the total amount of memory - * pages configured for the system (either in use or free). - * If it is FALSE, the value returned is the amount of free memory pages. - * * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid * excessive memory usage. * Modified: stable/8/sys/fs/tmpfs/tmpfs_subr.c ============================================================================== --- stable/8/sys/fs/tmpfs/tmpfs_subr.c Tue Mar 8 17:00:31 2011 (r219400) +++ stable/8/sys/fs/tmpfs/tmpfs_subr.c Tue Mar 8 17:27:36 2011 (r219401) @@ -93,7 +93,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp MPASS(IFF(type == VLNK, target != NULL)); MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); - if (tmp->tm_nodes_inuse > tmp->tm_nodes_max) + if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max) return (ENOSPC); nnode = (struct tmpfs_node *)uma_zalloc_arg( Modified: stable/8/sys/fs/tmpfs/tmpfs_vfsops.c ============================================================================== --- stable/8/sys/fs/tmpfs/tmpfs_vfsops.c Tue Mar 8 17:00:31 2011 (r219400) +++ stable/8/sys/fs/tmpfs/tmpfs_vfsops.c Tue Mar 8 17:27:36 2011 (r219401) @@ -182,18 +182,18 @@ tmpfs_mount(struct mount *mp) struct tmpfs_mount *tmp; struct tmpfs_node *root; size_t pages, mem_size; - ino_t nodes; + uint32_t nodes; int error; /* Size counters. */ - ino_t nodes_max; - size_t size_max; + u_int nodes_max; + u_quad_t size_max; /* Root node attributes. */ - uid_t root_uid; - gid_t root_gid; - mode_t root_mode; + uid_t root_uid; + gid_t root_gid; + mode_t root_mode; - struct vattr va; + struct vattr va; if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts)) return (EINVAL); @@ -223,7 +223,7 @@ tmpfs_mount(struct mount *mp) if (mp->mnt_cred->cr_ruid != 0 || vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1) root_mode = va.va_mode; - if (vfs_scanopt(mp->mnt_optnew, "inodes", "%d", &nodes_max) != 1) + if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1) nodes_max = 0; if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1) size_max = 0; @@ -239,15 +239,18 @@ tmpfs_mount(struct mount *mp) * allowed to use, based on the maximum size the user passed in * the mount structure. A value of zero is treated as if the * maximum available space was requested. */ - if (size_max < PAGE_SIZE || size_max >= SIZE_MAX) + if (size_max < PAGE_SIZE || size_max > SIZE_MAX - PAGE_SIZE) pages = SIZE_MAX; else pages = howmany(size_max, PAGE_SIZE); MPASS(pages > 0); - if (nodes_max <= 3) - nodes = 3 + pages * PAGE_SIZE / 1024; - else + if (nodes_max <= 3) { + if (pages > UINT32_MAX - 3) + nodes = UINT32_MAX; + else + nodes = pages + 3; + } else nodes = nodes_max; MPASS(nodes >= 3); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: patched->closed Fixed in head, stable/9 and stable/8.