]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: close device fd (to avoid mount(2) EBUSY)
authorKarel Zak <kzak@redhat.com>
Fri, 27 Apr 2012 08:30:08 +0000 (10:30 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 27 Apr 2012 08:30:08 +0000 (10:30 +0200)
libmount uses libblkid to detect filesystem type. Unfortunately, the
blkid probe struct is not freed before mount(2), it means that the
device is still open and mount(2) may return EBUSY.

We don't need persistent blkid stuff in libmount, so let's close
all immediately after device probing.

Reported-by: David Zeuthen <zeuthen@gmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/cache.c

index afd426089a0cc196bf7ac1a9a405b68fadf7703b..8962a903cb9f788546dcbd138946375a8134b861 100644 (file)
@@ -59,9 +59,6 @@ struct libmnt_cache {
         *    better to reuse the blkid_cache.
         */
        blkid_cache             bc;
-       blkid_probe             pr;
-
-       char                    *filename;
 };
 
 /**
@@ -100,10 +97,8 @@ void mnt_free_cache(struct libmnt_cache *cache)
                free(e->key);
        }
        free(cache->ents);
-       free(cache->filename);
        if (cache->bc)
                blkid_put_cache(cache->bc);
-       blkid_free_probe(cache->pr);
        free(cache);
 }
 
@@ -249,42 +244,6 @@ static char *cache_find_tag_value(struct libmnt_cache *cache,
        return NULL;
 }
 
-/*
- * returns (in @res) blkid prober, the @cache argument is optional
- */
-static int cache_get_probe(struct libmnt_cache *cache, const char *devname,
-                          blkid_probe *res)
-{
-       blkid_probe pr = cache ? cache->pr : NULL;
-
-       assert(devname);
-
-       if (cache && cache->pr && (!cache->filename ||
-                                  strcmp(devname, cache->filename))) {
-               blkid_free_probe(cache->pr);
-               free(cache->filename);
-               cache->filename = NULL;
-               pr = cache->pr = NULL;
-       }
-
-       if (!pr) {
-               pr = blkid_new_probe_from_filename(devname);
-               if (!pr)
-                       return -1;
-               if (cache) {
-                       cache->pr = pr;
-                       cache->filename = strdup(devname);
-                       if (!cache->filename)
-                               return -ENOMEM;
-               }
-
-       }
-
-       if (res)
-               *res = pr;
-       return 0;
-}
-
 /**
  * mnt_cache_read_tags
  * @cache: pointer to struct libmnt_cache instance
@@ -297,8 +256,8 @@ static int cache_get_probe(struct libmnt_cache *cache, const char *devname,
  */
 int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
 {
+       blkid_probe pr;
        size_t i, ntags = 0;
-       int rc;
        const char *tags[] = { "LABEL", "UUID", "TYPE", "PARTUUID", "PARTLABEL" };
        const char *blktags[] = { "LABEL", "UUID", "TYPE", "PART_ENTRY_UUID", "PART_ENTRY_NAME" };
 
@@ -320,20 +279,19 @@ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
                        return 0;
        }
 
-       rc = cache_get_probe(cache, devname, NULL);
-       if (rc)
-               return rc;
+       pr =  blkid_new_probe_from_filename(devname);
+       if (!pr)
+               return -1;
 
-       blkid_probe_enable_superblocks(cache->pr, 1);
-
-       blkid_probe_set_superblocks_flags(cache->pr,
+       blkid_probe_enable_superblocks(pr, 1);
+       blkid_probe_set_superblocks_flags(pr,
                        BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
                        BLKID_SUBLKS_TYPE);
 
-       blkid_probe_enable_partitions(cache->pr, 1);
-       blkid_probe_set_partitions_flags(cache->pr, BLKID_PARTS_ENTRY_DETAILS);
+       blkid_probe_enable_partitions(pr, 1);
+       blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
 
-       if (blkid_do_safeprobe(cache->pr))
+       if (blkid_do_safeprobe(pr))
                goto error;
 
        DBG(CACHE, mnt_debug_h(cache, "reading tags for: %s", devname));
@@ -347,7 +305,7 @@ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
                                        "\ntag %s already cached", tags[i]));
                        continue;
                }
-               if (blkid_probe_lookup_value(cache->pr, blktags[i], &data, NULL))
+               if (blkid_probe_lookup_value(pr, blktags[i], &data, NULL))
                        continue;
                dev = strdup(devname);
                if (!dev)
@@ -361,8 +319,10 @@ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
        }
 
        DBG(CACHE, mnt_debug_h(cache, "\tread %zd tags", ntags));
+       blkid_free_probe(pr);
        return ntags ? 0 : 1;
 error:
+       blkid_free_probe(pr);
        return -1;
 }
 
@@ -428,7 +388,11 @@ char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache)
        if (cache)
                return mnt_cache_find_tag_value(cache, devname, "TYPE");
 
-       if (cache_get_probe(NULL, devname, &pr))
+       /*
+        * no cache, probe directly
+        */
+       pr =  blkid_new_probe_from_filename(devname);
+       if (!pr)
                return NULL;
 
        blkid_probe_enable_superblocks(pr, 1);