summaryrefslogtreecommitdiffstats
path: root/shlibs/blkid/src
diff options
context:
space:
mode:
authorKarel Zak2011-05-13 15:07:56 +0200
committerKarel Zak2011-05-16 20:22:52 +0200
commitfd9f45e1585e920cc3bd201219df8ce6975ff9ea (patch)
tree43230d68bd4b16f8a4c7cac69f1c587f0ce9e254 /shlibs/blkid/src
parenttests: update for recent fdisk changes (diff)
downloadkernel-qcow2-util-linux-fd9f45e1585e920cc3bd201219df8ce6975ff9ea.tar.gz
kernel-qcow2-util-linux-fd9f45e1585e920cc3bd201219df8ce6975ff9ea.tar.xz
kernel-qcow2-util-linux-fd9f45e1585e920cc3bd201219df8ce6975ff9ea.zip
libblkid: make whole disk probing more robust
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/blkid/src')
-rw-r--r--shlibs/blkid/src/blkidP.h6
-rw-r--r--shlibs/blkid/src/partitions/partitions.c67
-rw-r--r--shlibs/blkid/src/probe.c93
3 files changed, 103 insertions, 63 deletions
diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h
index 53e4c5954..ddd1bb890 100644
--- a/shlibs/blkid/src/blkidP.h
+++ b/shlibs/blkid/src/blkidP.h
@@ -209,6 +209,9 @@ struct blkid_struct_probe
struct blkid_prval vals[BLKID_NVALS]; /* results */
int nvals; /* number of assigned vals */
+
+ struct blkid_struct_probe *parent; /* for clones */
+ struct blkid_struct_probe *disk_probe; /* whole-disk probing */
};
/* private flags library flags */
@@ -219,6 +222,9 @@ struct blkid_struct_probe
/* private per-probing flags */
#define BLKID_PROBE_FL_IGNORE_PT (1 << 1) /* ignore partition table */
+extern blkid_probe blkid_clone_probe(blkid_probe parent);
+extern blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr);
+
/*
* Evaluation methods (for blkid_eval_* API)
*/
diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c
index b89dad5bd..42c6c2c79 100644
--- a/shlibs/blkid/src/partitions/partitions.c
+++ b/shlibs/blkid/src/partitions/partitions.c
@@ -677,30 +677,13 @@ static int blkid_partitions_probe_partition(blkid_probe pr)
blkid_probe disk_pr = NULL;
blkid_partlist ls;
blkid_partition par;
- dev_t devno, disk_devno;
- char *disk_path = NULL;
+ dev_t devno;
devno = blkid_probe_get_devno(pr);
if (!devno)
goto nothing;
- disk_devno = blkid_probe_get_wholedisk_devno(pr);
- if (!disk_devno)
- goto nothing;
-
- if (devno == disk_devno)
- goto nothing; /* this is not a partition */
-
- disk_path = blkid_devno_to_devname(disk_devno);
- if (!disk_path)
- goto nothing;
-
- DBG(DEBUG_LOWPROBE, printf(
- "parts: %d:%d: starting whole-disk probing: %s\n",
- major(devno), minor(devno), disk_path));
-
- /* create a new prober for the disk */
- disk_pr = blkid_new_probe_from_filename(disk_path);
+ disk_pr = blkid_probe_get_wholedisk_probe(pr);
if (!disk_pr)
goto nothing;
@@ -749,53 +732,17 @@ static int blkid_partitions_probe_partition(blkid_probe pr)
}
rc = 0;
nothing:
- blkid_free_probe(disk_pr);
- free(disk_path);
return rc;
}
/*
- * This function is compatible with blkid_probe_get_partitions(), but the
- * result is not stored in @pr and all probing is independent on the
- * status of @pr. It's possible to call this function from arbitrary
- * place without a care about @pr.
- */
-static blkid_partlist blkid_probe_get_independent_partlist(blkid_probe pr)
-{
-
- blkid_partlist ls = NULL, org_ls = NULL;
- struct blkid_chain *chn = &pr->chains[BLKID_CHAIN_PARTS];
- struct blkid_prval vals[BLKID_NVALS_PARTS];
- int nvals = BLKID_NVALS_PARTS;
- int idx;
-
- /* save old results */
- nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
- idx = chn->idx;
- if (chn->data) {
- org_ls = chn->data;
- chn->data = NULL;
- }
-
- ls = blkid_probe_get_partitions(pr);
-
- /* restore original results */
- chn->data = org_ls;
- chn->idx = idx;
-
- blkid_probe_chain_reset_vals(pr, chn);
- blkid_probe_append_vals(pr, vals, nvals);
-
- return ls;
-}
-
-/*
* Returns 1 if the device is whole-disk and the area specified by @offset and
* @size is covered by any partition.
*/
int blkid_probe_is_covered_by_pt(blkid_probe pr,
blkid_loff_t offset, blkid_loff_t size)
{
+ blkid_probe prc;
blkid_partlist ls = NULL;
blkid_loff_t start, end;
int nparts, i, rc = 0;
@@ -804,7 +751,11 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr,
"=> checking if off=%jd size=%jd covered by PT\n",
offset, size));
- ls = blkid_probe_get_independent_partlist(pr);
+ prc = blkid_clone_probe(pr);
+ if (!prc)
+ goto done;
+
+ ls = blkid_probe_get_partitions(prc);
if (!ls)
goto done;
@@ -837,7 +788,7 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr,
}
}
done:
- partitions_free_data(pr, (void *)ls);
+ blkid_free_probe(prc);
DBG(DEBUG_LOWPROBE, printf("<= %s covered by PT\n", rc ? "IS" : "NOT"));
return rc;
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index 7cece7ef2..5f75d713e 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -142,6 +142,8 @@ blkid_probe blkid_new_probe(void)
if (!pr)
return NULL;
+ DBG(DEBUG_LOWPROBE, printf("allocate a new probe %p\n", pr));
+
/* initialize chains */
for (i = 0; i < BLKID_NCHAINS; i++) {
pr->chains[i].driver = chains_drvs[i];
@@ -152,6 +154,39 @@ blkid_probe blkid_new_probe(void)
return pr;
}
+/*
+ * Clone @parent, the new clone shares all, but except:
+ *
+ * - probing result
+ * - bufferes if another device (or offset) is set to the prober
+ */
+blkid_probe blkid_clone_probe(blkid_probe parent)
+{
+ blkid_probe pr;
+
+ if (!parent)
+ return NULL;
+
+ DBG(DEBUG_LOWPROBE, printf("allocate a probe clone\n"));
+
+ pr = blkid_new_probe();
+ if (!pr)
+ return NULL;
+
+ pr->fd = parent->fd;
+ pr->off = parent->off;
+ pr->size = parent->size;
+ pr->devno = parent->devno;
+ pr->disk_devno = parent->disk_devno;
+ pr->blkssz = parent->blkssz;
+ pr->flags = parent->flags;
+ pr->parent = parent;
+
+ return pr;
+}
+
+
+
/**
* blkid_new_probe_from_filename:
* @filename: device or regular file
@@ -218,6 +253,9 @@ void blkid_free_probe(blkid_probe pr)
if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
close(pr->fd);
blkid_probe_reset_buffer(pr);
+ blkid_free_probe(pr->disk_probe);
+
+ DBG(DEBUG_LOWPROBE, printf("free probe %p\n", pr));
free(pr);
}
@@ -487,14 +525,23 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
if (pr->size <= 0)
return NULL;
+ if (pr->parent &&
+ pr->parent->devno == pr->devno &&
+ pr->parent->off == pr->off)
+ /*
+ * This is a cloned prober and points to the same area as
+ * parent. Let's use parent's bufferes.
+ */
+ return blkid_probe_get_buffer(pr->parent, off, len);
+
list_for_each(p, &pr->buffers) {
struct blkid_bufinfo *x =
list_entry(p, struct blkid_bufinfo, bufs);
if (x->off <= off && off + len <= x->off + x->len) {
DBG(DEBUG_LOWPROBE,
- printf("\treuse buffer: off=%jd len=%jd\n",
- x->off, x->len));
+ printf("\treuse buffer: off=%jd len=%jd pr=%p\n",
+ x->off, x->len, pr));
bf = x;
break;
}
@@ -516,7 +563,8 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
INIT_LIST_HEAD(&bf->bufs);
DBG(DEBUG_LOWPROBE,
- printf("\tbuffer read: off=%jd len=%jd\n", off, len));
+ printf("\tbuffer read: off=%jd len=%jd pr=%p\n",
+ off, len, pr));
ret = read(pr->fd, bf->data, len);
if (ret != (ssize_t) len) {
@@ -537,12 +585,11 @@ static void blkid_probe_reset_buffer(blkid_probe pr)
if (!pr || list_empty(&pr->buffers))
return;
- DBG(DEBUG_LOWPROBE, printf("reseting probing buffers\n"));
+ DBG(DEBUG_LOWPROBE, printf("reseting probing buffers pr=%p\n", pr));
while (!list_empty(&pr->buffers)) {
struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
struct blkid_bufinfo, bufs);
-
read_ct++;
len_ct += bf->len;
list_del(&bf->bufs);
@@ -1123,6 +1170,42 @@ int blkid_probe_is_wholedisk(blkid_probe pr)
return devno == disk_devno;
}
+blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
+{
+ dev_t disk;
+
+ if (blkid_probe_is_wholedisk(pr))
+ return NULL; /* this is not partition */
+
+ if (pr->parent)
+ /* this is cloned blkid_probe, use parent's stuff */
+ return blkid_probe_get_wholedisk_probe(pr->parent);
+
+ disk = blkid_probe_get_wholedisk_devno(pr);
+
+ if (pr->disk_probe && pr->disk_probe->devno != disk) {
+ /* we have disk prober, but for another disk... close it */
+ blkid_free_probe(pr->disk_probe);
+ pr->disk_probe = NULL;
+ }
+
+ if (!pr->disk_probe) {
+ /* Open a new disk prober */
+ char *disk_path = blkid_devno_to_devname(disk);
+
+ if (!disk_path)
+ return NULL;
+
+ DBG(DEBUG_LOWPROBE, printf("allocate a wholedisk probe\n"));
+
+ pr->disk_probe = blkid_new_probe_from_filename(disk_path);
+ if (!pr->disk_probe)
+ return NULL; /* ENOMEM? */
+ }
+
+ return pr->disk_probe;
+}
+
/**
* blkid_probe_get_size:
* @pr: probe