Chris Johns commented: 
https://gitlab.rtems.org/rtems/rtos/rtems/-/issues/5201#note_123181


# Reason

This behavior is also present on `6-freebsd-14` and `7-freebsd-14` and I 
suspect `main` (FreeBSD 15). The reason is an `fd` IOP is held when referenced 
by `kqueue` event sets. The `kqueue` `fd` is also held at the same time 
resulting in a deadlock because RTEMS's `libio` extended the errors `close` 
returns. If you attempt to close an `fd` while being held `EBUSY` is returned. 
The approach is a little naive performing the check at the `libio` layer rather 
than letting the file system decide. You cannot call close on either the event 
`fd` or `kqueue` to unblock the call.

The close `EBUSY` check was added then the reference counting change was made. 
My guess is the implementation simplifies the free logic for an `iop`. We 
cannot change the current implementation without checking all users and 
possibly breaking them.

# LibIO

The proper fix is to clean up `libio`. There are other issues around the 
referencing counting in `libio`. The base design is good and sound with 
lock-less atomic access to the IOP flags giving good performance however it 
does not deal with more complex `fd` relationships such as FreeBSD's `kqueue` 
and the event `fd`'s with close.

The IOP flags use the open bit in the IOP as a reference to say a user has the 
`fd`. The reference counts indicate if the IOP is held in `libio` or a file 
system call however the real count is plus one for the open state.

# Solution

The solution is to let `close` call the close handler if references to the 
`iop` are held. The default behavior is to return `EBADF` if a reference is 
held. It is what we have now. There is too much work to audit and check all the 
existing file systems and users of these handler interfaces to know handling 
close with reference held is OK.

A file system that can support close with held references can set an `iop` flag 
called `LIBIO_FLAGS_CLOSE_BUSY` in open and `close` checks for the flag and 
does raise error if set.

This approach complicates when the `iop` can be freed as the free is currently 
done in `close` as there are no held references. Adding checks to free the 
`iop` to all handler paths is not great because it complicates that code and a 
case might be missed.

FreeBSD's descriptor code has a reference for the `fd` allocation and 
implements standard reference counting logic for a shared resource. If the hold 
count drops to zero the resource is freed. Adding the free to the `iop` drop 
can work.

-- 
View it on GitLab: 
https://gitlab.rtems.org/rtems/rtos/rtems/-/issues/5201#note_123181
You're receiving this email because of your account on gitlab.rtems.org.


_______________________________________________
bugs mailing list
bugs@rtems.org
http://lists.rtems.org/mailman/listinfo/bugs

Reply via email to