--- a/sys/vfs/tmpfs/tmpfs_vfsops.c +++ b/sys/vfs/tmpfs/tmpfs_vfsops.c @@ -203,8 +203,19 @@ sizeof(struct tmpfs_dirent)); kmalloc_create(&tmp->tm_name_zone, "tmpfs name zone"); + /* + * Scale all tmpfs zone limits with the node budget so ordinary + * operation cannot collide with the malloc default limit (kmem/10), + * which PANICs for allocations made without M_NULLOK (e.g. + * tmpfs_alloc_dirent). Dirents are bounded by nodes_max*LINK_MAX + * (hardlinks) and names by nodes_max*NAME_MAX in the worst case. + */ kmalloc_obj_raise_limit(tmp->tm_node_zone, sizeof(struct tmpfs_node) * tmp->tm_nodes_max); + kmalloc_obj_raise_limit(tmp->tm_dirent_zone, + sizeof(struct tmpfs_dirent) * tmp->tm_nodes_max); + kmalloc_raise_limit(tmp->tm_name_zone, + (size_t)tmp->tm_nodes_max * (PATH_MAX / 2)); tmp->tm_ino = TMPFS_ROOTINO; --- a/sys/vfs/tmpfs/tmpfs_subr.c +++ b/sys/vfs/tmpfs/tmpfs_subr.c @@ -304,7 +304,9 @@ struct tmpfs_dirent *nde; nde = kmalloc_obj(sizeof(struct tmpfs_dirent), - tmp->tm_dirent_zone, M_WAITOK); + tmp->tm_dirent_zone, M_WAITOK | M_NULLOK); + if (nde == NULL) + return (ENOSPC); nde->td_name = kmalloc(len + 1, tmp->tm_name_zone, M_WAITOK | M_NULLOK); if (nde->td_name == NULL) { kfree_obj(nde, tmp->tm_dirent_zone);