[parted-devel] [PATCH 3/4] ped_disk_clobber: change semantics
Jim Meyering
jim at meyering.net
Thu Nov 26 14:57:57 UTC 2009
From: Jim Meyering <meyering at redhat.com>
Why? Because if we're going to clobber a partition table,
it is wasteful and error prone to try to interpret as a partition
table whatever existing data there may be. It may be corrupt, or
a mix of two or more types. It is far cleaner just to zero out
the key sectors.
The previous mechanism was like this:
for each partition table type, T,
# See if the device has a partition of type T.
# If so, run the partition-table-specific code to clear it.
if t->ops->probe (dev)
t->ops->clobber (dev)
Instead, simply zero out the first few and last few sectors.
Except for GPT, for which we exempt the first sector (the pMBR).
In order to zero out even the bits DASD uses for its identifying
strings, we have to clobber at least the 8.5KiB at the beginning
of the disk, so round up to 9KiB.
* libparted/disk.c: Include "labels/pt-tools.h".
(find_disk_type): New helper function.
(ped_disk_clobber_exclude):
---
libparted/disk.c | 67 +++++++++++++++++++++++++++++++++++++----------------
1 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/libparted/disk.c b/libparted/disk.c
index 8c4b229..3127e03 100644
--- a/libparted/disk.c
+++ b/libparted/disk.c
@@ -39,6 +39,7 @@
#include "architecture.h"
#include "intprops.h"
+#include "labels/pt-tools.h"
#if ENABLE_NLS
# include <libintl.h>
@@ -276,6 +277,20 @@ error:
return NULL;
}
+/* Given a partition table type NAME, e.g., "gpt", return its PedDiskType
+ handle. If no known type has a name matching NAME, return NULL. */
+static PedDiskType const *
+find_disk_type (char const *name)
+{
+ PedDiskType const *t;
+ for (t = ped_disk_type_get_next (NULL); t; t = ped_disk_type_get_next (t))
+ {
+ if (strcmp (t->name, name) == 0)
+ return t;
+ }
+ return NULL;
+}
+
/**
* Remove all identifying signatures of a partition table,
* except for partition tables of a given type.
@@ -287,31 +302,43 @@ error:
int
ped_disk_clobber_exclude (PedDevice* dev, const PedDiskType* exclude)
{
- PedDiskType* walk;
-
PED_ASSERT (dev != NULL, goto error);
if (!ped_device_open (dev))
goto error;
- for (walk = ped_disk_type_get_next (NULL); walk;
- walk = ped_disk_type_get_next (walk)) {
- int probed;
+ PedDiskType const *gpt = find_disk_type ("gpt");
+ PED_ASSERT (gpt != NULL, goto error);
+
+ /* If there is a GPT table, don't clobber the protective MBR. */
+ bool is_gpt = gpt->ops->probe (dev);
+ PedSector first_sector = (is_gpt ? 1 : 0);
+
+ /* How many sectors to zero out at each end.
+ This must be large enough to zero out the magic bytes
+ starting at offset 8KiB on a DASD partition table.
+ Doing the same from the end of the disk is probably
+ overkill, but at least on GPT, we do need to zero out
+ the final sector. */
+ const PedSector n_sectors = 9 * 1024 / dev->sector_size + 1;
+
+ /* Clear the first few. */
+ PedSector n = n_sectors;
+ if (dev->length < first_sector + n_sectors)
+ n = dev->length - first_sector;
+ if (!ptt_clear_sectors (dev, first_sector, n))
+ goto error_close_dev;
+
+ /* Clear the last few. */
+ PedSector t = (dev->length -
+ (n_sectors < dev->length ? n_sectors : 1));
+
+ /* Don't clobber the pMBR if we have a pathologically small disk. */
+ if (t < first_sector)
+ t = first_sector;
+ if (!ptt_clear_sectors (dev, t, dev->length - t))
+ goto error_close_dev;
- if (walk == exclude)
- continue;
-
- ped_exception_fetch_all ();
- probed = walk->ops->probe (dev);
- if (!probed)
- ped_exception_catch ();
- ped_exception_leave_all ();
-
- if (probed && walk->ops->clobber) {
- if (!walk->ops->clobber (dev))
- goto error_close_dev;
- }
- }
ped_device_close (dev);
return 1;
@@ -469,7 +496,7 @@ ped_disk_commit_to_dev (PedDisk* disk)
goto error;
if (disk->needs_clobber) {
- if (!ped_disk_clobber_exclude (disk->dev, disk->type))
+ if (!ped_disk_clobber_exclude (disk->dev, NULL))
goto error_close_dev;
disk->needs_clobber = 0;
}
--
1.6.6.rc0.54.gb073b
More information about the parted-devel
mailing list