diff options
-rw-r--r-- | shlibs/blkid/src/blkidP.h | 6 | ||||
-rw-r--r-- | shlibs/blkid/src/partitions/partitions.c | 67 | ||||
-rw-r--r-- | shlibs/blkid/src/probe.c | 93 |
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 |