fs: inode and open-file tables that grow, with a hash for iget
The inode table was NINODE (200) entries, searched end to end on every
iget(), and a panic -- "iget: no inodes" -- when all of them were held.
Held means open, a cwd, a running binary or a directory mid-walk, so a
few busy processes reached it. iget() now finds an inode through a hash
on (dev, inum), takes a free one from a list, and makes more from a
slab cache once the NINODE in the image are all in use.
The open-file table had the same shape, NFILE (512) and then ENFILE,
and gets the same treatment: a free list, and the slab past NFILE.
/proc/fsstat's peaks now read against how many exist.
getrlimit(RLIMIT_NOFILE) said unlimited, which musl turns into
sysconf(_SC_OPEN_MAX) == -1, after which zsh believed it had no
descriptors and `exec {fd}<file` failed on the first one. It reports
NOFILE now. And a comment in sys_fs.c held a "*/" that ended it early.
Checked under QEMU: six processes holding 115 files each, 713 open
descriptions and 341 inodes at once, all back to the baseline after.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
62d2a85ac8
commit
09e07423e8
6 changed files with 161 additions and 40 deletions
|
|
@ -74,6 +74,20 @@ sys_arch_prctl(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Limits are reported, not enforced: everything is unlimited except what the
|
||||
// kernel actually has a ceiling for. RLIMIT_NOFILE was "unlimited" too, and
|
||||
// musl turns that into sysconf(_SC_OPEN_MAX) == -1 -- after which zsh decided
|
||||
// it had no descriptors at all, and `exec {fd}<file` failed on the first try.
|
||||
#define RLIMIT_NOFILE_ 7
|
||||
|
||||
static void
|
||||
rlimit_of(int resource, struct rlimit *r)
|
||||
{
|
||||
r->rlim_cur = r->rlim_max = (uint64)-1;
|
||||
if (resource == RLIMIT_NOFILE_)
|
||||
r->rlim_cur = r->rlim_max = NOFILE;
|
||||
}
|
||||
|
||||
addr_t
|
||||
sys_getrlimit(void)
|
||||
{
|
||||
|
|
@ -82,19 +96,18 @@ sys_getrlimit(void)
|
|||
argint(0, &resource);
|
||||
if (argptr(1, (char**)&rlp, sizeof(*rlp)) < 0)
|
||||
return -1;
|
||||
rlp->rlim_cur = (uint64)-1;
|
||||
rlp->rlim_max = (uint64)-1;
|
||||
rlimit_of(resource, rlp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_t
|
||||
sys_prlimit(void)
|
||||
{
|
||||
int resource;
|
||||
struct rlimit *oldrlp;
|
||||
if (argptr(3, (char**)&oldrlp, sizeof(*oldrlp)) == 0 && oldrlp) {
|
||||
oldrlp->rlim_cur = (uint64)-1;
|
||||
oldrlp->rlim_max = (uint64)-1;
|
||||
}
|
||||
argint(1, &resource);
|
||||
if (argptr(3, (char**)&oldrlp, sizeof(*oldrlp)) == 0 && oldrlp)
|
||||
rlimit_of(resource, oldrlp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "errno.h"
|
||||
#include "schfs.h" /* SCHFS_BLKSIZE, SCHFS_NAME_MAX — statfs reports them */
|
||||
#include "gfx.h" /* gfx_cols/gfx_rows — TIOCGWINSZ reports them */
|
||||
#include "vt.h" /* the terminals TIOC*/VT_* act on */
|
||||
#include "vt.h" /* the terminals the TIOC and VT_ ioctls act on */
|
||||
#include "pciuser.h"
|
||||
#include "keymap.h" /* KB_*LAYOUT — the keyboard layout catalogue */
|
||||
#include "netuser.h"
|
||||
|
|
|
|||
Loading…
Reference in a new issue