]> 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>
Thu, 24 May 2012 10:17:51 +0000 (12:17 +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>
Conflicts:

libmount/src/cache.c

libmount/src/cache.c

index 1b3e94d00ee5b0dd03a18820b90fabbd2f4f7c22..f3156a550c916b56e6180de7751c4d9c163de4a6 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" };
 
        assert(cache);
@@ -319,17 +278,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);
 
-       if (blkid_do_safeprobe(cache->pr))
+       blkid_probe_enable_partitions(pr, 1);
+       blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
+
+       if (blkid_do_safeprobe(pr))
                goto error;
 
        DBG(CACHE, mnt_debug_h(cache, "reading tags for: %s", devname));
@@ -343,7 +304,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, tags[i], &data, NULL))
+               if (blkid_probe_lookup_value(pr, tags[i], &data, NULL))
                        continue;
                dev = strdup(devname);
                if (!dev)
@@ -357,8 +318,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;
 }
 
@@ -424,7 +387,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);