summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/partition.c
diff options
context:
space:
mode:
authorKarel Zak2016-05-04 12:32:52 +0200
committerKarel Zak2016-05-04 12:32:52 +0200
commit131e38a28ea055548a098611eeba94078a17c19d (patch)
tree73a6f3d50e0b961740f1970d2a7f79abe93f2a3d /libfdisk/src/partition.c
parentlibblkid: make I/O errors on CDROMs non-fatal (diff)
downloadkernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.tar.gz
kernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.tar.xz
kernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.zip
libfdisk: add fdisk_wipe_partition()
Now libfdisk provides functionality wipe disk device only ([s]fdisk option --wipe). This patch allows to probe for filesystems/RAIDs on newly created partitions. It means we can remove signatures before the partition node (device) is created. This reduces udev events and it's unnecessary to call wipefs for all partitions. For example sfdisk --wipe=always --wipe-partitions=always /dev/sda <<< ... EOF is a elegant way how to create new disk layout without any obsolete filesystems/RAIDs. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/partition.c')
-rw-r--r--libfdisk/src/partition.c137
1 files changed, 132 insertions, 5 deletions
diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c
index 5e41eed0d..4fbd1e468 100644
--- a/libfdisk/src/partition.c
+++ b/libfdisk/src/partition.c
@@ -2,6 +2,10 @@
#include "c.h"
#include "strutils.h"
+#ifdef HAVE_LIBBLKID
+# include <blkid.h>
+#endif
+
#include "fdiskP.h"
/**
@@ -63,6 +67,9 @@ void fdisk_reset_partition(struct fdisk_partition *pa)
free(pa->name);
free(pa->uuid);
free(pa->attrs);
+ free(pa->fstype);
+ free(pa->fsuuid);
+ free(pa->fslabel);
memset(pa, 0, sizeof(*pa));
pa->refcount = ref;
@@ -85,6 +92,13 @@ static struct fdisk_partition *__copy_partition(struct fdisk_partition *o)
n->uuid = strdup(o->uuid);
if (o->attrs)
n->attrs = strdup(o->attrs);
+ if (o->fstype)
+ n->fstype = strdup(o->fstype);
+ if (o->fsuuid)
+ n->fsuuid = strdup(o->fsuuid);
+ if (o->fslabel)
+ n->fslabel = strdup(o->fslabel);
+
return n;
}
@@ -127,7 +141,7 @@ void fdisk_unref_partition(struct fdisk_partition *pa)
* @off: offset in sectors, maximal is UINT64_MAX-1
*
* Note that zero is valid offset too. Use fdisk_partition_unset_start() to
- * undefine the offset.
+ * undefine the offset.
*
* Returns: 0 on success, <0 on error.
*/
@@ -138,6 +152,7 @@ int fdisk_partition_set_start(struct fdisk_partition *pa, fdisk_sector_t off)
if (FDISK_IS_UNDEF(off))
return -ERANGE;
pa->start = off;
+ pa->fs_probed = 0;
return 0;
}
@@ -154,6 +169,7 @@ int fdisk_partition_unset_start(struct fdisk_partition *pa)
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->start);
+ pa->fs_probed = 0;
return 0;
}
@@ -259,6 +275,7 @@ int fdisk_partition_set_size(struct fdisk_partition *pa, fdisk_sector_t sz)
if (FDISK_IS_UNDEF(sz))
return -ERANGE;
pa->size = sz;
+ pa->fs_probed = 0;
return 0;
}
@@ -275,6 +292,7 @@ int fdisk_partition_unset_size(struct fdisk_partition *pa)
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->size);
+ pa->fs_probed = 0;
return 0;
}
@@ -724,6 +742,60 @@ int fdisk_partition_next_partno(
return 0;
}
+static int probe_partition_content(struct fdisk_context *cxt, struct fdisk_partition *pa)
+{
+ int rc = 1; /* nothing */
+
+ DBG(PART, ul_debugobj(pa, "start probe #%zu partition [cxt %p] >>>", pa->partno, cxt));
+
+ /* zeroize the current setting */
+ strdup_to_struct_member(pa, fstype, NULL);
+ strdup_to_struct_member(pa, fsuuid, NULL);
+ strdup_to_struct_member(pa, fslabel, NULL);
+
+ if (!fdisk_partition_has_start(pa) ||
+ !fdisk_partition_has_size(pa))
+ goto done;
+
+#ifdef HAVE_LIBBLKID
+ else {
+ uintmax_t start, size;
+
+ blkid_probe pr = blkid_new_probe();
+ if (!pr)
+ goto done;
+
+ DBG(PART, ul_debugobj(pa, "blkid prober: %p", pr));
+
+ start = fdisk_partition_get_start(pa) * fdisk_get_sector_size(cxt);
+ size = fdisk_partition_get_size(pa) * fdisk_get_sector_size(cxt);
+
+ if (blkid_probe_set_device(pr, cxt->dev_fd, start, size) == 0
+ && blkid_do_fullprobe(pr) == 0) {
+
+ const char *data;
+ rc = 0;
+
+ if (!blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
+ rc = strdup_to_struct_member(pa, fstype, data);
+
+ if (!rc && !blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
+ rc = strdup_to_struct_member(pa, fslabel, data);
+
+ if (!rc && !blkid_probe_lookup_value(pr, "UUID", &data, NULL))
+ rc = strdup_to_struct_member(pa, fsuuid, data);
+ }
+
+ blkid_free_probe(pr);
+ pa->fs_probed = 1;
+ }
+#endif /* HAVE_LIBBLKID */
+
+done:
+ DBG(PART, ul_debugobj(pa, "<<< end probe #%zu partition[cxt %p, rc=%d]", pa->partno, cxt, rc));
+ return rc;
+}
+
/**
* fdisk_partition_to_string:
* @pa: partition
@@ -859,6 +931,18 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
case FDISK_FIELD_EADDR:
p = pa->end_chs && *pa->end_chs? strdup(pa->end_chs) : NULL;
break;
+ case FDISK_FIELD_FSUUID:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fsuuid && *pa->fsuuid ? strdup(pa->fsuuid) : NULL;
+ break;
+ case FDISK_FIELD_FSLABEL:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fslabel && *pa->fslabel ? strdup(pa->fslabel) : NULL;
+ break;
+ case FDISK_FIELD_FSTYPE:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fstype && *pa->fstype ? strdup(pa->fstype) : NULL;
+ break;
default:
return -EINVAL;
}
@@ -876,6 +960,7 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
return rc;
}
+
/**
* fdisk_get_partition:
* @cxt: context
@@ -1140,14 +1225,16 @@ erange:
int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
struct fdisk_partition *pa)
{
- struct fdisk_partition *xpa = pa;
- int rc;
+ struct fdisk_partition *xpa = pa, *tmp = NULL;
+ int rc, wipe = 0;
if (!cxt || !cxt->label || !pa)
return -EINVAL;
if (!cxt->label->op->set_part)
return -ENOSYS;
+ pa->fs_probed = 0;
+
if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) {
xpa = __copy_partition(pa);
xpa->movestart = 0;
@@ -1166,7 +1253,19 @@ int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
(uintmax_t) fdisk_partition_get_end(xpa),
(uintmax_t) fdisk_partition_get_size(xpa)));
+ /* disable wipe for old offset/size setting */
+ if (fdisk_get_partition(cxt, partno, &tmp) == 0 && tmp) {
+ wipe = fdisk_set_wipe_area(cxt, fdisk_partition_get_start(tmp),
+ fdisk_partition_get_size(tmp), FALSE);
+ fdisk_unref_partition(tmp);
+ }
+
+ /* call label driver */
rc = cxt->label->op->set_part(cxt, partno, xpa);
+
+ /* enable wipe for new offset/size */
+ if (!rc && wipe)
+ fdisk_wipe_partition(cxt, partno, TRUE);
done:
DBG(CXT, ul_debugobj(cxt, "set_partition() rc=%d", rc));
if (xpa != pa)
@@ -1174,6 +1273,31 @@ done:
return rc;
}
+/**
+ * fdisk_wipe_partition:
+ * @cxt: fdisk context
+ * @partno: partition number
+ * @enable: 0 or 1
+ *
+ * Enable/disable filesystems/RAIDs wiping in area defined by partition start and size.
+ *
+ * Returns: <0 in case of error, 0 on success
+ */
+int fdisk_wipe_partition(struct fdisk_context *cxt, size_t partno, int enable)
+{
+ struct fdisk_partition *pa = NULL;
+ int rc;
+
+ rc = fdisk_get_partition(cxt, partno, &pa);
+ if (rc)
+ return rc;
+
+ rc = fdisk_set_wipe_area(cxt, fdisk_partition_get_start(pa),
+ fdisk_partition_get_size(pa), enable);
+ fdisk_unref_partition(pa);
+ return rc < 0 ? rc : 0;
+}
+
/**
* fdisk_add_partition:
@@ -1201,7 +1325,8 @@ int fdisk_add_partition(struct fdisk_context *cxt,
if (fdisk_missing_geometry(cxt))
return -EINVAL;
- if (pa)
+ if (pa) {
+ pa->fs_probed = 0;
DBG(CXT, ul_debugobj(cxt, "adding new partition %p (start=%ju, end=%ju, size=%ju, "
"defaults(start=%s, end=%s, partno=%s)",
pa,
@@ -1211,7 +1336,7 @@ int fdisk_add_partition(struct fdisk_context *cxt,
pa->start_follow_default ? "yes" : "no",
pa->end_follow_default ? "yes" : "no",
pa->partno_follow_default ? "yes" : "no"));
- else
+ } else
DBG(CXT, ul_debugobj(cxt, "adding partition"));
rc = cxt->label->op->add_part(cxt, pa, partno);
@@ -1236,6 +1361,8 @@ int fdisk_delete_partition(struct fdisk_context *cxt, size_t partno)
if (!cxt->label->op->del_part)
return -ENOSYS;
+ fdisk_wipe_partition(cxt, partno, 0);
+
DBG(CXT, ul_debugobj(cxt, "deleting %s partition number %zd",
cxt->label->name, partno));
return cxt->label->op->del_part(cxt, partno);