Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32-rc2 261 lines 6.4 kB view raw
1/* 2 * File...........: linux/fs/partitions/ibm.c 3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> 4 * Volker Sameske <sameske@de.ibm.com> 5 * Bugreports.to..: <Linux390@de.ibm.com> 6 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 */ 8 9#include <linux/buffer_head.h> 10#include <linux/hdreg.h> 11#include <linux/slab.h> 12#include <asm/dasd.h> 13#include <asm/ebcdic.h> 14#include <asm/uaccess.h> 15#include <asm/vtoc.h> 16 17#include "check.h" 18#include "ibm.h" 19 20/* 21 * compute the block number from a 22 * cyl-cyl-head-head structure 23 */ 24static sector_t 25cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { 26 27 sector_t cyl; 28 __u16 head; 29 30 /*decode cylinder and heads for large volumes */ 31 cyl = ptr->hh & 0xFFF0; 32 cyl <<= 12; 33 cyl |= ptr->cc; 34 head = ptr->hh & 0x000F; 35 return cyl * geo->heads * geo->sectors + 36 head * geo->sectors; 37} 38 39/* 40 * compute the block number from a 41 * cyl-cyl-head-head-block structure 42 */ 43static sector_t 44cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { 45 46 sector_t cyl; 47 __u16 head; 48 49 /*decode cylinder and heads for large volumes */ 50 cyl = ptr->hh & 0xFFF0; 51 cyl <<= 12; 52 cyl |= ptr->cc; 53 head = ptr->hh & 0x000F; 54 return cyl * geo->heads * geo->sectors + 55 head * geo->sectors + 56 ptr->b; 57} 58 59/* 60 */ 61int 62ibm_partition(struct parsed_partitions *state, struct block_device *bdev) 63{ 64 int blocksize, res; 65 loff_t i_size, offset, size, fmt_size; 66 dasd_information2_t *info; 67 struct hd_geometry *geo; 68 char type[5] = {0,}; 69 char name[7] = {0,}; 70 union label_t { 71 struct vtoc_volume_label_cdl vol; 72 struct vtoc_volume_label_ldl lnx; 73 struct vtoc_cms_label cms; 74 } *label; 75 unsigned char *data; 76 Sector sect; 77 78 res = 0; 79 blocksize = bdev_logical_block_size(bdev); 80 if (blocksize <= 0) 81 goto out_exit; 82 i_size = i_size_read(bdev->bd_inode); 83 if (i_size == 0) 84 goto out_exit; 85 86 info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); 87 if (info == NULL) 88 goto out_exit; 89 geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL); 90 if (geo == NULL) 91 goto out_nogeo; 92 label = kmalloc(sizeof(union label_t), GFP_KERNEL); 93 if (label == NULL) 94 goto out_nolab; 95 96 if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || 97 ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) 98 goto out_freeall; 99 100 /* 101 * Get volume label, extract name and type. 102 */ 103 data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect); 104 if (data == NULL) 105 goto out_readerr; 106 107 memcpy(label, data, sizeof(union label_t)); 108 put_dev_sector(sect); 109 110 if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { 111 strncpy(type, label->vol.vollbl, 4); 112 strncpy(name, label->vol.volid, 6); 113 } else { 114 strncpy(type, label->lnx.vollbl, 4); 115 strncpy(name, label->lnx.volid, 6); 116 } 117 EBCASC(type, 4); 118 EBCASC(name, 6); 119 120 res = 1; 121 122 /* 123 * Three different formats: LDL, CDL and unformated disk 124 * 125 * identified by info->format 126 * 127 * unformated disks we do not have to care about 128 */ 129 if (info->format == DASD_FORMAT_LDL) { 130 if (strncmp(type, "CMS1", 4) == 0) { 131 /* 132 * VM style CMS1 labeled disk 133 */ 134 blocksize = label->cms.block_size; 135 if (label->cms.disk_offset != 0) { 136 printk("CMS1/%8s(MDSK):", name); 137 /* disk is reserved minidisk */ 138 offset = label->cms.disk_offset; 139 size = (label->cms.block_count - 1) 140 * (blocksize >> 9); 141 } else { 142 printk("CMS1/%8s:", name); 143 offset = (info->label_block + 1); 144 size = label->cms.block_count 145 * (blocksize >> 9); 146 } 147 put_partition(state, 1, offset*(blocksize >> 9), 148 size-offset*(blocksize >> 9)); 149 } else { 150 if (strncmp(type, "LNX1", 4) == 0) { 151 printk("LNX1/%8s:", name); 152 if (label->lnx.ldl_version == 0xf2) { 153 fmt_size = label->lnx.formatted_blocks 154 * (blocksize >> 9); 155 } else if (!strcmp(info->type, "ECKD")) { 156 /* formated w/o large volume support */ 157 fmt_size = geo->cylinders * geo->heads 158 * geo->sectors * (blocksize >> 9); 159 } else { 160 /* old label and no usable disk geometry 161 * (e.g. DIAG) */ 162 fmt_size = i_size >> 9; 163 } 164 size = i_size >> 9; 165 if (fmt_size < size) 166 size = fmt_size; 167 offset = (info->label_block + 1); 168 } else { 169 /* unlabeled disk */ 170 printk("(nonl)"); 171 size = i_size >> 9; 172 offset = (info->label_block + 1); 173 } 174 put_partition(state, 1, offset*(blocksize >> 9), 175 size-offset*(blocksize >> 9)); 176 } 177 } else if (info->format == DASD_FORMAT_CDL) { 178 /* 179 * New style CDL formatted disk 180 */ 181 sector_t blk; 182 int counter; 183 184 /* 185 * check if VOL1 label is available 186 * if not, something is wrong, skipping partition detection 187 */ 188 if (strncmp(type, "VOL1", 4) == 0) { 189 printk("VOL1/%8s:", name); 190 /* 191 * get block number and read then go through format1 192 * labels 193 */ 194 blk = cchhb2blk(&label->vol.vtoc, geo) + 1; 195 counter = 0; 196 data = read_dev_sector(bdev, blk * (blocksize/512), 197 &sect); 198 while (data != NULL) { 199 struct vtoc_format1_label f1; 200 201 memcpy(&f1, data, 202 sizeof(struct vtoc_format1_label)); 203 put_dev_sector(sect); 204 205 /* skip FMT4 / FMT5 / FMT7 labels */ 206 if (f1.DS1FMTID == _ascebc['4'] 207 || f1.DS1FMTID == _ascebc['5'] 208 || f1.DS1FMTID == _ascebc['7'] 209 || f1.DS1FMTID == _ascebc['9']) { 210 blk++; 211 data = read_dev_sector(bdev, blk * 212 (blocksize/512), 213 &sect); 214 continue; 215 } 216 217 /* only FMT1 and 8 labels valid at this point */ 218 if (f1.DS1FMTID != _ascebc['1'] && 219 f1.DS1FMTID != _ascebc['8']) 220 break; 221 222 /* OK, we got valid partition data */ 223 offset = cchh2blk(&f1.DS1EXT1.llimit, geo); 224 size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - 225 offset + geo->sectors; 226 if (counter >= state->limit) 227 break; 228 put_partition(state, counter + 1, 229 offset * (blocksize >> 9), 230 size * (blocksize >> 9)); 231 counter++; 232 blk++; 233 data = read_dev_sector(bdev, 234 blk * (blocksize/512), 235 &sect); 236 } 237 238 if (!data) 239 /* Are we not supposed to report this ? */ 240 goto out_readerr; 241 } else 242 printk(KERN_WARNING "Warning, expected Label VOL1 not " 243 "found, treating as CDL formated Disk"); 244 245 } 246 247 printk("\n"); 248 goto out_freeall; 249 250 251out_readerr: 252 res = -1; 253out_freeall: 254 kfree(label); 255out_nolab: 256 kfree(geo); 257out_nogeo: 258 kfree(info); 259out_exit: 260 return res; 261}