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