<div dir="ltr">If I remember correctly, udev (recent versions) takes a BSD lock using flock(2) while processing the device, and tools are supposed to do the same. The flock() call can be set to wait until the lock can be taken.<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Nov 26, 2023 at 1:40 AM Richard Weinberger <<a href="mailto:richard.weinberger@gmail.com">richard.weinberger@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello!<br>
<br>
After upgrading my main test worker to a recent distribution, the UBI<br>
test suite [0] fails at various places with -EBUSY.<br>
The reason is that these tests create and remove UBI volumes rapidly.<br>
A typical test sequence is as follows:<br>
1. creation of /dev/ubi0_0<br>
2. some exclusive operation, such as atomic update or volume resize on<br>
/dev/ubi0_0<br>
3. removal of /dev/ubi0_0<br>
<br>
Both steps 2 and 3 can fail with -EBUSY because the udev worker still<br>
holds a file descriptor to /dev/ubi0_0.<br>
<br>
FWIW, the problem can also get triggered using UBI's shell utilities<br>
if the system is fast enough, e.g.<br>
# ubimkvol -N testv -S 50 -n 0 /dev/ubi0 && ubirmvol -n 0 /dev/ubi0<br>
Volume ID 0, size 50 LEBs (793600 bytes, 775.0 KiB), LEB size 15872<br>
bytes (15.5 KiB), dynamic, name "testv", alignment 1<br>
ubirmvol: error!: cannot UBI remove volume<br>
error 16 (Device or resource busy)<br>
<br>
Instead of adding a retry loop around -EBUSY, I believe the best<br>
solution is to add code to wait for udev.<br>
For example, having a udev barrier in ubi_mkvol() and ubi_rmvol() [1]<br>
seems like a good idea to me.<br>
<br>
What function from libsystemd do you suggest for waiting until udev is<br>
done with rule processing?<br>
My naive approach, using udev_queue_is_empty() and<br>
sd_device_get_is_initialized(), does not resolve all failures so far.<br>
Firstly, udev_queue_is_empty() doesn't seem to be exported by<br>
libsystemd. I have open-coded it as:<br>
static int udev_queue_is_empty(void) {<br>
return access("/run/udev/queue", F_OK) < 0 ?<br>
(errno == ENOENT ? true : -errno) : false;<br>
}<br>
<br>
Additionally, sd_device_get_is_initialized() seems to return sometimes<br>
true even if the udev worker still has the volume open.<br>
In short, which API do you recommend to ensure that the device my<br>
thread has created is actually usable?<br>
<br>
[0]: <a href="http://git.infradead.org/mtd-utils.git/tree/HEAD:/tests/ubi-tests" rel="noreferrer" target="_blank">http://git.infradead.org/mtd-utils.git/tree/HEAD:/tests/ubi-tests</a><br>
[1]: <a href="http://git.infradead.org/mtd-utils.git/blob/HEAD:/lib/libubi.c#l994" rel="noreferrer" target="_blank">http://git.infradead.org/mtd-utils.git/blob/HEAD:/lib/libubi.c#l994</a><br>
<br>
-- <br>
Thanks,<br>
//richard<br>
</blockquote></div><br clear="all"><br><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr">Mantas Mikulėnas</div></div>