Imported Upstream version 0.6.3
[platform/upstream/multipath-tools.git] / kpartx / dasd.c
index dcdf678..faf5e2e 100644 (file)
@@ -19,9 +19,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <stdio.h>
@@ -47,8 +45,25 @@ unsigned long long sectors512(unsigned long long sectors, int blocksize)
 }
 
 /*
+ * Magic records per track calculation, copied from fdasd.c
  */
-int 
+static unsigned int ceil_quot(unsigned int d1, unsigned int d2)
+{
+       return (d1 + (d2 - 1)) / d2;
+}
+
+unsigned int recs_per_track(unsigned int dl)
+{
+       int dn = ceil_quot(dl + 6, 232) + 1;
+       return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
+}
+
+
+typedef unsigned int __attribute__((__may_alias__)) label_ints_t;
+
+/*
+ */
+int
 read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
 {
        int retval = -1;
@@ -97,7 +112,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
                 * major/minor into an openable device file, so we have
                 * to create one for ourselves.
                 */
-               
+
                sprintf(pathname, "/dev/.kpartx-node-%u-%u",
                        (unsigned int)major(dev), (unsigned int)minor(dev));
                if ((fd_dasd = open(pathname, O_RDONLY)) == -1) {
@@ -122,19 +137,31 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
        }
 
        if (ioctl(fd_dasd, BIODASDINFO, (unsigned long)&info) != 0) {
-               goto out;
+               info.label_block = 2;
+               info.FBA_layout = 0;
+               memcpy(info.type, "ECKD", sizeof(info.type));
        }
 
-       if (ioctl(fd_dasd, HDIO_GETGEO, (unsigned long)&geo) != 0) {
+       if (ioctl(fd_dasd, BLKSSZGET, &blocksize) != 0)
                goto out;
-       }
 
        if (ioctl(fd_dasd, BLKGETSIZE64, &disksize) != 0)
                goto out;
-       disksize >>= 9;
 
-       if (ioctl(fd_dasd, BLKSSZGET, &blocksize) != 0)
-               goto out;
+       if (ioctl(fd_dasd, HDIO_GETGEO, (unsigned long)&geo) != 0) {
+               unsigned int cyl;
+
+               geo.heads = 15;
+               geo.sectors = recs_per_track(blocksize);
+               cyl = disksize / (blocksize * geo.heads * geo.sectors);
+               if (cyl < LV_COMPAT_CYL)
+                       geo.cylinders = cyl;
+               else
+                       geo.cylinders = LV_COMPAT_CYL;
+               geo.start = 0;
+       }
+
+       disksize >>= 9;
 
        if (blocksize < 512 || blocksize > 4096)
                goto out;
@@ -169,7 +196,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
                /*
                 * VM style CMS1 labeled disk
                 */
-               unsigned int *label = (unsigned int *) &vlabel;
+               label_ints_t *label = (label_ints_t *) &vlabel;
 
                blocksize = label[4];
                if (label[14] != 0) {
@@ -206,7 +233,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
                            || EBCtoASC[f1.DS1FMTID] == '5'
                            || EBCtoASC[f1.DS1FMTID] == '7'
                            || EBCtoASC[f1.DS1FMTID] == '9') {
-                               blk++;
+                               blk++;
                                continue;
                        }
 
@@ -216,7 +243,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
                                break;
 
                        /* OK, we got valid partition data */
-                       offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
+                       offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
                        size  = cchh2blk(&f1.DS1EXT1.ulimit, &geo) -
                                offset + geo.sectors;
                        sp[counter].start = sectors512(offset, blocksize);
@@ -253,7 +280,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
                retval = 1;
        }
 
- out:
+out:
        if (data != NULL)
                free(data);
        if (fd_dasd != -1 && fd_dasd != fd)