bug-parted
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#15356: [PATCH 06/19] libparted: add support for implicit FBA DASD pa


From: Brian C. Lane
Subject: bug#15356: [PATCH 06/19] libparted: add support for implicit FBA DASD partitions
Date: Wed, 11 Sep 2013 12:24:56 -0700

From: Nageswara R Sastry <address@hidden>

Fixed Block Access (FBA) DASDs are mainframe-specific disk devices
which are layed out as a sequence of 512-byte sectors. In contrast
to ECKD DASDs, these disks do not require formatting and resemble
the LBA layout of non-mainframe disks. Despite this resemblance,
the Linux kernel applies special handling during partition detection
for FBA DASDs, resulting in a single, immutable partition being
reported.

While actual FBA DASD hardware is no longer available, the z/VM
hypervisor can simulate FBA DASD disks, backed by either ECKD or
SCSI devices.

This patch adds support for recognizing FBA DASD partitions
to parted.

Signed-off-by: Nageswara R Sastry <address@hidden>
Signed-off-by: Peter Oberparleiter <address@hidden>
---
 include/parted/fdasd.in.h |  2 ++
 libparted/labels/dasd.c   | 63 ++++++++++++++++++++++++++++++++++++++++-------
 libparted/labels/fdasd.c  |  5 ++++
 3 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/include/parted/fdasd.in.h b/include/parted/fdasd.in.h
index ac30134..a755246 100644
--- a/include/parted/fdasd.in.h
+++ b/include/parted/fdasd.in.h
@@ -194,6 +194,8 @@ typedef struct fdasd_anchor {
        volume_label_t   *vlabel;
        config_data_t confdata[USABLE_PARTITIONS];
        struct fdasd_hd_geometry geo;
+       unsigned int label_block;
+       unsigned int FBA_layout;
 } fdasd_anchor_t;
 
 enum offset {lower, upper};
diff --git a/libparted/labels/dasd.c b/libparted/labels/dasd.c
index a769866..b4e80b1 100644
--- a/libparted/labels/dasd.c
+++ b/libparted/labels/dasd.c
@@ -71,6 +71,7 @@ typedef struct {
 
 typedef struct {
        unsigned int format_type;
+       unsigned int label_block;
        volume_label_t vlabel;
 } DasdDiskSpecific;
 
@@ -151,6 +152,7 @@ dasd_alloc (const PedDevice* dev)
 
        /* CDL format, newer */
        disk_specific->format_type = 2;
+       disk_specific->label_block = 2;
 
        /* Setup volume label (for fresh disks) */
        snprintf(volser, sizeof(volser), "0X%04X", arch_specific->devno);
@@ -226,7 +228,9 @@ dasd_probe (const PedDevice *dev)
 
        fdasd_check_api_version(&anchor, arch_specific->fd);
 
-       if (fdasd_check_volume(&anchor, arch_specific->fd))
+       /* Labels are required on CDL formatted DASDs. */
+       if (fdasd_check_volume(&anchor, arch_specific->fd) &&
+           anchor.FBA_layout == 0)
                goto error_cleanup;
 
        fdasd_cleanup(&anchor);
@@ -273,17 +277,53 @@ dasd_read (PedDisk* disk)
        fdasd_initialize_anchor(&anchor);
 
        fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd);
+       disk_specific->label_block = anchor.label_block;
+
+       if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
+               anchor.big_disk++;
 
        /* check dasd for labels and vtoc */
-       if (fdasd_check_volume(&anchor, arch_specific->fd))
-               goto error_close_dev;
+       if (fdasd_check_volume(&anchor, arch_specific->fd)) {
+               DasdPartitionData* dasd_data;
+
+               /* Kernel partitioning code will report 'implicit' partitions
+                * for non-CDL format DASDs even when there is no
+                * label/VTOC.  */
+               if (anchor.FBA_layout == 0)
+                       goto error_close_dev;
+
+               disk_specific->format_type = 1;
+
+               /* Register implicit partition */
+               ped_disk_delete_all (disk);
+
+               start = (PedSector) arch_specific->real_sector_size /
+                       (PedSector) disk->dev->sector_size *
+                       (PedSector) (anchor.label_block + 1);
+               end = disk->dev->length - 1;
+               part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
+                                         start, end);
+               if (!part)
+                       goto error_close_dev;
+
+               part->num = 1;
+               part->fs_type = ped_file_system_probe (&part->geom);
+               dasd_data = part->disk_specific;
+               dasd_data->raid = 0;
+               dasd_data->lvm = 0;
+               dasd_data->type = 0;
+
+               if (!ped_disk_add_partition (disk, part, NULL))
+                       goto error_close_dev;
+
+               fdasd_cleanup(&anchor);
+
+               return 1;
+       }
 
        /* Save volume label (read by fdasd_check_volume) for writing */
        memcpy(&disk_specific->vlabel, anchor.vlabel, sizeof(volume_label_t));
 
-       if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
-               anchor.big_disk++;
-
        ped_disk_delete_all (disk);
 
        bool is_ldl = strncmp(anchor.vlabel->volkey,
@@ -348,7 +388,7 @@ dasd_read (PedDisk* disk)
                            / (long long) disk->dev->sector_size
                            * (long long) (cms_ptr->block_count - 1) - 1;
 
-               part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, 
start, end);
+               part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, 
start, end);
                if (!part)
                        goto error_close_dev;
 
@@ -923,7 +963,12 @@ dasd_alloc_metadata (PedDisk* disk)
           the start of the first partition */
        if (disk_specific->format_type == 1) {
                part = ped_disk_get_partition(disk, 1);
-               vtoc_end = part->geom.start - 1;
+               if (part)
+                       vtoc_end = part->geom.start - 1;
+               else
+                       vtoc_end = (PedSector) arch_specific->real_sector_size /
+                                  (PedSector) disk->dev->sector_size *
+                                  (PedSector) disk_specific->label_block;
        }
        else {
                 if (disk->dev->type == PED_DEVICE_FILE)
@@ -943,7 +988,7 @@ dasd_alloc_metadata (PedDisk* disk)
                goto error;
        }
 
-       if (disk_specific->format_type == 1) {
+       if (disk_specific->format_type == 1 && part) {
           /*
              For LDL or CMS there may be trailing metadata as well.
              For example: the last block of a CMS reserved file,
diff --git a/libparted/labels/fdasd.c b/libparted/labels/fdasd.c
index e235dd3..f92065f 100644
--- a/libparted/labels/fdasd.c
+++ b/libparted/labels/fdasd.c
@@ -721,6 +721,7 @@ fdasd_check_volume (fdasd_anchor_t *anc, int fd)
        unsigned long b = -1;
        char str[LINE_LENGTH];
 
+       memset(v, 0, sizeof(volume_label_t));
        vtoc_read_volume_label (fd, anc->label_pos, v);
 
        if (strncmp(v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0) {
@@ -800,6 +801,8 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t 
*anc, int f)
            dasd_info.dev_type = 13200;
            dasd_info.label_block = 2;
            dasd_info.devno = 513;
+           dasd_info.label_block = 2;
+           dasd_info.FBA_layout = 0;
        } else {
                if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0)
                        fdasd_error(anc, unable_to_ioctl,
@@ -820,6 +823,8 @@ fdasd_get_geometry (const PedDevice *dev, fdasd_anchor_t 
*anc, int f)
        anc->label_pos  = dasd_info.label_block * blksize;
        anc->devno      = dasd_info.devno;
        anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - 
FIRST_USABLE_TRK;
+       anc->label_block = dasd_info.label_block;
+       anc->FBA_layout = dasd_info.FBA_layout;
 }
 
 /*
-- 
1.8.3.1






reply via email to

[Prev in Thread] Current Thread [Next in Thread]