summaryrefslogtreecommitdiffstats
path: root/shlibs/blkid/src/probe.c
diff options
context:
space:
mode:
authorKarel Zak2011-02-24 14:03:44 +0100
committerKarel Zak2011-02-24 14:21:11 +0100
commit8b7eae458ccb04befb579dc87bdbfc1b6cbd5553 (patch)
tree695dbee4e53285980b460fac2852bb085bd5c0fa /shlibs/blkid/src/probe.c
parentdocs: update TODO (diff)
downloadkernel-qcow2-util-linux-8b7eae458ccb04befb579dc87bdbfc1b6cbd5553.tar.gz
kernel-qcow2-util-linux-8b7eae458ccb04befb579dc87bdbfc1b6cbd5553.tar.xz
kernel-qcow2-util-linux-8b7eae458ccb04befb579dc87bdbfc1b6cbd5553.zip
libblkid: try to detect if PT is newer than LVM
LVM (pvcreate) wipes the begin of the device. If there is a PT in the wiped area then LVM signature is obsolete. # pvcreate /dev/sdb # fdisk /dev/sdb old version: # blkid -p -o udev /dev/sdb ID_FS_TYPE=LVM2_member new version: # blkid -p -o udev /dev/sdb ID_PART_TABLE_TYPE=dos Reported-by: Matej Cepl <mcepl@redhat.com> Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=679799 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/blkid/src/probe.c')
-rw-r--r--shlibs/blkid/src/probe.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index 677b32fab..342927743 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -752,6 +752,7 @@ static inline void blkid_probe_start(blkid_probe pr)
if (pr) {
pr->cur_chain = NULL;
pr->prob_flags = 0;
+ blkid_probe_set_wiper(pr, 0, 0);
}
}
@@ -760,6 +761,7 @@ static inline void blkid_probe_end(blkid_probe pr)
if (pr) {
pr->cur_chain = NULL;
pr->prob_flags = 0;
+ blkid_probe_set_wiper(pr, 0, 0);
}
}
@@ -1338,3 +1340,79 @@ size_t blkid_rtrim_whitespace(unsigned char *str)
return i;
}
+/*
+ * Some mkfs-like utils wipe some parts (usually begin) of the device.
+ * For example LVM (pvcreate) or mkswap(8). This information could be used
+ * for later resolution to conflicts between superblocks.
+ *
+ * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
+ * the device. If we found another signature (for example MBR) this wiped area
+ * then the signature has been added later and LVM superblock should be ignore.
+ *
+ * Note that this heuristic is not 100% reliable, for example "pvcreate --zero
+ * n" allows to keep the begin of the device unmodified. It's probably better
+ * to use this heuristic for conflicts between superblocks and partition tables
+ * than for conflicts between filesystem superblocks -- existence of unwanted
+ * partition table is very unusual, because PT is pretty visible (parsed and
+ * interpreted by kernel).
+ */
+void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
+{
+ struct blkid_chain *chn;
+
+ if (!pr)
+ return;
+
+ if (!size) {
+ DBG(DEBUG_LOWPROBE, printf("zeroize wiper\n"));
+ pr->wipe_size = pr->wipe_off = 0;
+ pr->wipe_chain = NULL;
+ return;
+ }
+
+ chn = pr->cur_chain;
+
+ if (!chn || !chn->driver ||
+ chn->idx < 0 || chn->idx >= chn->driver->nidinfos)
+ return;
+
+ pr->wipe_size = size;
+ pr->wipe_off = off;
+ pr->wipe_chain = chn;
+
+ DBG(DEBUG_LOWPROBE,
+ printf("wiper set to %s::%s off=%jd size=%jd\n",
+ chn->driver->name,
+ chn->driver->idinfos[chn->idx]->name,
+ pr->wipe_off, pr->wipe_size));
+ return;
+}
+
+/*
+ * Returns 1 if the <@off,@size> area was wiped
+ */
+int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
+ blkid_loff_t off, blkid_loff_t size)
+{
+ if (!pr || !size)
+ return 0;
+
+ if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
+ if (chn)
+ *chn = pr->wipe_chain;
+ return 1;
+ }
+ return 0;
+}
+
+void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
+{
+ struct blkid_chain *chn = NULL;
+
+ if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
+ DBG(DEBUG_LOWPROBE, printf("wiped area detected -- ignore previous results\n"));
+ blkid_probe_set_wiper(pr, 0, 0);
+ blkid_probe_chain_reset_vals(pr, chn);
+ }
+}
+