NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop.
The following reply was made to PR kern/57145; it has been noted by GNATS.
From: David Holland <dholland-bugs%netbsd.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: pkg/57145: gmake: *** INTERNAL: readdir: Operation not
supported. Stop.
Date: Thu, 22 Jan 2026 05:31:45 +0000
On Tue, Jan 20, 2026 at 04:15:01PM +0000, Havard Eidnes via gnats wrote:
> 14717 14717 gmake RET __getdents30 4080/0xff0
> 14717 14717 gmake CALL lseek(6,0,0,1)
> 14717 14717 gmake RET lseek 3132/0xc3c
> 14717 14717 gmake CALL __getdents30(6,0x79e73d4a0000,0x1000)
> 14717 14717 gmake RET __getdents30 -1 errno 22 Invalid argument
This is, I think, caused by:
- the buffer passed to getdents is 4096 bytes
- the previous getdents call fills the buffer (note it returns 4080
bytes, and the minimum size of a valid dirent is 20)
- this puts it at offset 3132 in the dir
- when it goes back the dir has been updated and the block it's in the
middle of rebuilt, and 3132 is no longer a valid offset
- --> EINVAL
Note that 4080 bytes of dirents puts us at offset 3132 because struct
dirent is larger than the FFS on-disk struct direct.
There is a fairly easy workaround:
Always enable __DTF_READALL and __DTF_RETRY_ON_BADCOOKIE in opendir.
This causes opendir to read the whole directory up front and also
retry if it gets EINVAL while doing so.
That is, however, not a fix... a better approach would be to rearrange
the (delicate) logic in ufs_readdir to never stop in the middle of a
block. That'll be a headache though.
Basically, if it stops in the middle of a block there's no way to
prevent the resulting offset from becoming invalid before the next
call, and then no way to recover if that happens. (Other than retry
from the beginning, which under enough load will just never finish
instead.)
The other option is to bite the bullet and change the meaning of
directory offsets in FFS so that it counts entries instead of using
the position. (So, offset 0 is the first entry, offset 1 is the
second, offset 512 or 4096 is the first entry in the second block,
etc.) This is even more invasive though.
--
David A. Holland
dholland%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index