summaryrefslogtreecommitdiffstats
path: root/shlibs/blkid/src/probe.c
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/probe.c
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/probe.c')
-rw-r--r--shlibs/blkid/src/probe.c93
1 files changed, 88 insertions, 5 deletions
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