]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: remove empty loop devices from cache when garbage collecting
authorChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Sat, 21 Feb 2026 03:42:02 +0000 (22:42 -0500)
committerChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Mon, 23 Feb 2026 11:53:22 +0000 (06:53 -0500)
The cache garbage collection (blkid --garbage-collect) does not work for
entries of loop devices even when these have been detached. The previous
logic performed a simple stat() on the dev node path, however this is not
enough for loop devices as their nodes can remain present even if they
aren't backed by any file or other block device.

Therefore, it is more sane to verify if the loop device has a backing file
and if not, we remove it from the cache.

Closes: #4061
Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
libblkid/src/cache.c

index 5f598735b1d5223d2dc8aab00be978103e056cbe..6a2cc342083253ec904ccfb8b3aab8d8fa9da057 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 #include "blkidP.h"
 #include "env.h"
+#include "loopdev.h"
 
 /**
  * SECTION:cache
@@ -174,16 +175,25 @@ void blkid_gc_cache(blkid_cache cache)
 {
        struct list_head *p, *pnext;
        struct stat st;
+       int ret;
 
        if (!cache)
                return;
 
        list_for_each_safe(p, pnext, &cache->bic_devs) {
                blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
-               if (stat(dev->bid_name, &st) < 0) {
+
+               ret = stat(dev->bid_name, &st);
+               if (ret < 0) {
                        DBG(CACHE, ul_debugobj(cache, "freeing non-existing %s", dev->bid_name));
                        blkid_free_dev(dev);
                        cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+               } else if (is_loopdev(dev->bid_name)
+                                       && !loopdev_has_backing_file(dev->bid_name)) {
+                       /* remove empty loop device from cache */
+                       DBG(CACHE, ul_debugobj(cache, "freeing empty loop device %s", dev->bid_name));
+                       blkid_free_dev(dev);
+                       cache->bic_flags |= BLKID_BIC_FL_CHANGED;
                } else {
                        DBG(CACHE, ul_debug("Device %s exists", dev->bid_name));
                }