[parted-devel] [PATCH 2/4] dasd: allow the use of a *regular* backing file

Jim Meyering jim at meyering.net
Thu Nov 26 14:57:56 UTC 2009


From: Jim Meyering <meyering at redhat.com>

Before this change, dasd partition tables had to be associated with
very specialized block devices available only on IBM s390 systems.
This made testing especially hard.  Not only did you need access
to one of those relatively uncommon systems, but you also needed
access to a spare block device.  In addition, many of Parted's
tests may be run as a non-privileged user, using regular files,
and those tests would fail when run on an s390.

This change makes it so you may now write a DASD partition table
to a regular backing file, just as you may with any other supported
partition table type.  However, note that even now, DASD support
is conditionally compiled and hence enabled only when compiling
for an s390 target.

* libparted/arch/linux.c (_device_set_sector_size) [__s390__]:
Allow operation on a device of type PED_DEVICE_FILE, as well as
those of type PED_DEVICE_DASD.
* libparted/labels/fdasd.c: Include <parted/device.h>.
(fdasd_get_geometry): Add a new "dev" parameter, required for
dev-phys-sector_size, which is needed in order to initialize
the "anc" structure without using the device-specific ioctls.
When file descriptor "f" refers to a regular file, initialize
"anc", "dasd_info", etc. from other sources (fstat and dev->).
Update all callers to reflect added parameter.
(fdasd_check_api_version): Skip ioctl-calling tests when "f" is
a regular file.
* include/parted/fdasd.h: Update fdasd_get_geometry prototype.
* libparted/labels/dasd.c (dasd_probe): Also allow PED_DEVICE_FILE.
(dasd_alloc_metadata): Initialize arch_specific->real_sector_size,
which is used in calculating vtoc_end.
---
 include/parted/fdasd.h   |    2 +-
 libparted/arch/linux.c   |    3 +-
 libparted/labels/dasd.c  |   17 ++++++++----
 libparted/labels/fdasd.c |   61 ++++++++++++++++++++++++++++++++-------------
 4 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/include/parted/fdasd.h b/include/parted/fdasd.h
index a893ba8..ac30134 100644
--- a/include/parted/fdasd.h
+++ b/include/parted/fdasd.h
@@ -217,7 +217,7 @@ enum fdasd_failure {

 void fdasd_cleanup (fdasd_anchor_t *anchor);
 void fdasd_initialize_anchor (fdasd_anchor_t * anc);
-void fdasd_get_geometry (fdasd_anchor_t *anc, int fd);
+void fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int fd);
 void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
 int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
 int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 4fe48ec..94cbae9 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -672,7 +672,8 @@ _device_set_sector_size (PedDevice* dev)

 #if defined __s390__ || defined __s390x__
         /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
-        if (dev->type == PED_DEVICE_DASD) {
+        if (dev->type == PED_DEVICE_DASD
+            || dev->type == PED_DEVICE_FILE) {
                 arch_specific->real_sector_size = dev->sector_size;
                 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
         }
diff --git a/libparted/labels/dasd.c b/libparted/labels/dasd.c
index fc0695c..dd492f2 100644
--- a/libparted/labels/dasd.c
+++ b/libparted/labels/dasd.c
@@ -230,7 +230,9 @@ dasd_probe (const PedDevice *dev)

 	PED_ASSERT(dev != NULL, return 0);

-	if (!(dev->type == PED_DEVICE_DASD || dev->type == PED_DEVICE_VIODASD))
+	if (!(dev->type == PED_DEVICE_DASD
+              || dev->type == PED_DEVICE_VIODASD
+              || dev->type == PED_DEVICE_FILE))
 		return 0;

 	arch_specific = LINUX_SPECIFIC(dev);
@@ -238,7 +240,7 @@ dasd_probe (const PedDevice *dev)
 	/* add partition test here */
 	fdasd_initialize_anchor(&anchor);

-	fdasd_get_geometry(&anchor, arch_specific->fd);
+	fdasd_get_geometry(dev, &anchor, arch_specific->fd);

 	fdasd_check_api_version(&anchor, arch_specific->fd);

@@ -268,7 +270,7 @@ dasd_clobber (PedDevice* dev)
 	arch_specific = LINUX_SPECIFIC(dev);

 	fdasd_initialize_anchor(&anchor);
-	fdasd_get_geometry(&anchor, arch_specific->fd);
+	fdasd_get_geometry(dev, &anchor, arch_specific->fd);

 	fdasd_recreate_vtoc(&anchor);
 	fdasd_write_labels(&anchor, arch_specific->fd);
@@ -309,7 +311,7 @@ dasd_read (PedDisk* disk)

 	fdasd_initialize_anchor(&anchor);

-	fdasd_get_geometry(&anchor, arch_specific->fd);
+	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);

 	/* check dasd for labels and vtoc */
 	if (fdasd_check_volume(&anchor, arch_specific->fd))
@@ -577,7 +579,7 @@ dasd_write (const PedDisk* disk)

 	/* initialize the anchor */
 	fdasd_initialize_anchor(&anchor);
-	fdasd_get_geometry(&anchor, arch_specific->fd);
+	fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
 	memcpy(anchor.vlabel, &disk_specific->vlabel, sizeof(volume_label_t));
 	anchor.vlabel_changed++;

@@ -905,11 +907,14 @@ dasd_alloc_metadata (PedDisk* disk)
 	/* If formated in LDL, the real partition starts at sector 24. */
 	if (disk_specific->format_type == 1)
 		vtoc_end = 23;
-	else
+	else {
+                if (disk->dev->type == PED_DEVICE_FILE)
+                        arch_specific->real_sector_size = disk->dev->sector_size;
         /* Mark the start of the disk as metadata. */
 		vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors
 				   * (long long) arch_specific->real_sector_size
 				   / (long long) disk->dev->sector_size) - 1;
+        }

 	new_part = ped_partition_new (disk,PED_PARTITION_METADATA,NULL,0,vtoc_end);
 	if (!new_part)
diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c
index b116a69..6397f27 100644
--- a/libparted/labels/fdasd.c
+++ b/libparted/labels/fdasd.c
@@ -19,6 +19,7 @@
 #include <config.h>
 #include <arch/linux.h>
 #include <parted/vtoc.h>
+#include <parted/device.h>
 #include <parted/fdasd.h>

 #include <parted/parted.h>
@@ -753,15 +754,21 @@ fdasd_check_api_version (fdasd_anchor_t *anc, int f)
 	int api;
 	char s[LINE_LENGTH];

-	if (ioctl(f, DASDAPIVER, &api) != 0)
-		fdasd_error(anc, unable_to_ioctl,
-			    _("Could not retrieve API version."));
-
-	if (api != DASD_MIN_API_VERSION) {
-		sprintf(s, _("The current API version '%d' doesn't " \
-				"match dasd driver API version " \
-				"'%d'!"), api, DASD_MIN_API_VERSION);
-		fdasd_error(anc, api_version_mismatch, s);
+        struct stat st;
+        if (fstat (f, &st) == 0 && S_ISREG (st.st_mode)) {
+		/* skip these tests when F is a regular file.  */
+	}
+	else {
+		if (ioctl(f, DASDAPIVER, &api) != 0)
+			fdasd_error(anc, unable_to_ioctl,
+				    _("Could not retrieve API version."));
+
+		if (api != DASD_MIN_API_VERSION) {
+			sprintf(s, _("The current API version '%d' doesn't " \
+					"match dasd driver API version " \
+					"'%d'!"), api, DASD_MIN_API_VERSION);
+			fdasd_error(anc, api_version_mismatch, s);
+		}
 	}
 }

@@ -769,24 +776,42 @@ fdasd_check_api_version (fdasd_anchor_t *anc, int f)
  * reads dasd geometry data
  */
 void
-fdasd_get_geometry (fdasd_anchor_t *anc, int f)
+fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t *anc, int f)
 {
 	PDEBUG
 	int blksize = 0;
 	dasd_information_t dasd_info;

-	if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
-		fdasd_error(anc, unable_to_ioctl,
+	/* We can't get geometry from a regular file,
+	   so simulate something usable, for the sake of testing.  */
+	struct stat st;
+	if (fstat (f, &st) == 0 && S_ISREG (st.st_mode)) {
+	    PedSector n_sectors = st.st_size / dev->sector_size;
+	    anc->geo.heads = 15;
+	    anc->geo.sectors = 12;
+	    anc->geo.cylinders
+	      = (n_sectors / (anc->geo.heads * anc->geo.sectors
+			      * (dev->sector_size / dev->phys_sector_size)));
+	    anc->geo.start = 0;
+	    blksize = 4096;
+	    memcpy (dasd_info.type, "ECKD", 4);
+	    dasd_info.dev_type = 13200;
+	    dasd_info.label_block = 2;
+	    dasd_info.devno = 513;
+	} else {
+		if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
+			fdasd_error(anc, unable_to_ioctl,
 			    _("Could not retrieve disk geometry information."));

-	if (ioctl(f, BLKSSZGET, &blksize) != 0)
-		fdasd_error(anc, unable_to_ioctl,
+		if (ioctl(f, BLKSSZGET, &blksize) != 0)
+			fdasd_error(anc, unable_to_ioctl,
 			    _("Could not retrieve blocksize information."));

-	/* get disk type */
-	if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
-		fdasd_error(anc, unable_to_ioctl,
-			    _("Could not retrieve disk information."));
+		/* get disk type */
+		if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
+			fdasd_error(anc, unable_to_ioctl,
+				    _("Could not retrieve disk information."));
+	}

 	if (strncmp(dasd_info.type, "ECKD", 4) != 0)
 		fdasd_error(anc, wrong_disk_type,
-- 
1.6.6.rc0.54.gb073b




More information about the parted-devel mailing list