1 786 lclee /* 2 786 lclee * CDDL HEADER START 3 786 lclee * 4 786 lclee * The contents of this file are subject to the terms of the 5 3525 shidokht * Common Development and Distribution License (the "License"). 6 3525 shidokht * You may not use this file except in compliance with the License. 7 786 lclee * 8 786 lclee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 786 lclee * or http://www.opensolaris.org/os/licensing. 10 786 lclee * See the License for the specific language governing permissions 11 786 lclee * and limitations under the License. 12 786 lclee * 13 786 lclee * When distributing Covered Code, include this CDDL HEADER in each 14 786 lclee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 786 lclee * If applicable, add the following below this CDDL HEADER, with the 16 786 lclee * fields enclosed by brackets "[]" replaced with your own identifying 17 786 lclee * information: Portions Copyright [yyyy] [name of copyright owner] 18 786 lclee * 19 786 lclee * CDDL HEADER END 20 786 lclee */ 21 786 lclee 22 786 lclee /* 23 8570 Sriram * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 786 lclee * Use is subject to license terms. 25 786 lclee */ 26 786 lclee 27 786 lclee /* 28 786 lclee * This module provides support for labeling operations for target 29 786 lclee * drivers. 30 786 lclee */ 31 786 lclee 32 786 lclee #include <sys/scsi/scsi.h> 33 786 lclee #include <sys/sunddi.h> 34 786 lclee #include <sys/dklabel.h> 35 786 lclee #include <sys/dkio.h> 36 786 lclee #include <sys/vtoc.h> 37 786 lclee #include <sys/dktp/fdisk.h> 38 786 lclee #include <sys/vtrace.h> 39 786 lclee #include <sys/efi_partition.h> 40 786 lclee #include <sys/cmlb.h> 41 786 lclee #include <sys/cmlb_impl.h> 42 10021 Sheshadri #if defined(__i386) || defined(__amd64) 43 10021 Sheshadri #include <sys/fs/dv_node.h> 44 10021 Sheshadri #endif 45 7224 cth #include <sys/ddi_impldefs.h> 46 786 lclee 47 786 lclee /* 48 786 lclee * Driver minor node structure and data table 49 786 lclee */ 50 786 lclee struct driver_minor_data { 51 786 lclee char *name; 52 786 lclee minor_t minor; 53 786 lclee int type; 54 786 lclee }; 55 786 lclee 56 786 lclee static struct driver_minor_data dk_minor_data[] = { 57 786 lclee {"a", 0, S_IFBLK}, 58 786 lclee {"b", 1, S_IFBLK}, 59 786 lclee {"c", 2, S_IFBLK}, 60 786 lclee {"d", 3, S_IFBLK}, 61 786 lclee {"e", 4, S_IFBLK}, 62 786 lclee {"f", 5, S_IFBLK}, 63 786 lclee {"g", 6, S_IFBLK}, 64 786 lclee {"h", 7, S_IFBLK}, 65 786 lclee #if defined(_SUNOS_VTOC_16) 66 786 lclee {"i", 8, S_IFBLK}, 67 786 lclee {"j", 9, S_IFBLK}, 68 786 lclee {"k", 10, S_IFBLK}, 69 786 lclee {"l", 11, S_IFBLK}, 70 786 lclee {"m", 12, S_IFBLK}, 71 786 lclee {"n", 13, S_IFBLK}, 72 786 lclee {"o", 14, S_IFBLK}, 73 786 lclee {"p", 15, S_IFBLK}, 74 786 lclee #endif /* defined(_SUNOS_VTOC_16) */ 75 786 lclee #if defined(_FIRMWARE_NEEDS_FDISK) 76 786 lclee {"q", 16, S_IFBLK}, 77 786 lclee {"r", 17, S_IFBLK}, 78 786 lclee {"s", 18, S_IFBLK}, 79 786 lclee {"t", 19, S_IFBLK}, 80 786 lclee {"u", 20, S_IFBLK}, 81 786 lclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 82 786 lclee {"a,raw", 0, S_IFCHR}, 83 786 lclee {"b,raw", 1, S_IFCHR}, 84 786 lclee {"c,raw", 2, S_IFCHR}, 85 786 lclee {"d,raw", 3, S_IFCHR}, 86 786 lclee {"e,raw", 4, S_IFCHR}, 87 786 lclee {"f,raw", 5, S_IFCHR}, 88 786 lclee {"g,raw", 6, S_IFCHR}, 89 786 lclee {"h,raw", 7, S_IFCHR}, 90 786 lclee #if defined(_SUNOS_VTOC_16) 91 786 lclee {"i,raw", 8, S_IFCHR}, 92 786 lclee {"j,raw", 9, S_IFCHR}, 93 786 lclee {"k,raw", 10, S_IFCHR}, 94 786 lclee {"l,raw", 11, S_IFCHR}, 95 786 lclee {"m,raw", 12, S_IFCHR}, 96 786 lclee {"n,raw", 13, S_IFCHR}, 97 786 lclee {"o,raw", 14, S_IFCHR}, 98 786 lclee {"p,raw", 15, S_IFCHR}, 99 786 lclee #endif /* defined(_SUNOS_VTOC_16) */ 100 786 lclee #if defined(_FIRMWARE_NEEDS_FDISK) 101 786 lclee {"q,raw", 16, S_IFCHR}, 102 786 lclee {"r,raw", 17, S_IFCHR}, 103 786 lclee {"s,raw", 18, S_IFCHR}, 104 786 lclee {"t,raw", 19, S_IFCHR}, 105 786 lclee {"u,raw", 20, S_IFCHR}, 106 786 lclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 107 786 lclee {0} 108 786 lclee }; 109 786 lclee 110 10021 Sheshadri #if defined(__i386) || defined(__amd64) 111 10021 Sheshadri #if defined(_FIRMWARE_NEEDS_FDISK) 112 10021 Sheshadri static struct driver_minor_data dk_ext_minor_data[] = { 113 10021 Sheshadri {"p5", 21, S_IFBLK}, 114 10021 Sheshadri {"p6", 22, S_IFBLK}, 115 10021 Sheshadri {"p7", 23, S_IFBLK}, 116 10021 Sheshadri {"p8", 24, S_IFBLK}, 117 10021 Sheshadri {"p9", 25, S_IFBLK}, 118 10021 Sheshadri {"p10", 26, S_IFBLK}, 119 10021 Sheshadri {"p11", 27, S_IFBLK}, 120 10021 Sheshadri {"p12", 28, S_IFBLK}, 121 10021 Sheshadri {"p13", 29, S_IFBLK}, 122 10021 Sheshadri {"p14", 30, S_IFBLK}, 123 10021 Sheshadri {"p15", 31, S_IFBLK}, 124 10021 Sheshadri {"p16", 32, S_IFBLK}, 125 10021 Sheshadri {"p17", 33, S_IFBLK}, 126 10021 Sheshadri {"p18", 34, S_IFBLK}, 127 10021 Sheshadri {"p19", 35, S_IFBLK}, 128 10021 Sheshadri {"p20", 36, S_IFBLK}, 129 10021 Sheshadri {"p21", 37, S_IFBLK}, 130 10021 Sheshadri {"p22", 38, S_IFBLK}, 131 10021 Sheshadri {"p23", 39, S_IFBLK}, 132 10021 Sheshadri {"p24", 40, S_IFBLK}, 133 10021 Sheshadri {"p25", 41, S_IFBLK}, 134 10021 Sheshadri {"p26", 42, S_IFBLK}, 135 10021 Sheshadri {"p27", 43, S_IFBLK}, 136 10021 Sheshadri {"p28", 44, S_IFBLK}, 137 10021 Sheshadri {"p29", 45, S_IFBLK}, 138 10021 Sheshadri {"p30", 46, S_IFBLK}, 139 10021 Sheshadri {"p31", 47, S_IFBLK}, 140 10021 Sheshadri {"p32", 48, S_IFBLK}, 141 10021 Sheshadri {"p33", 49, S_IFBLK}, 142 10021 Sheshadri {"p34", 50, S_IFBLK}, 143 10021 Sheshadri {"p35", 51, S_IFBLK}, 144 10021 Sheshadri {"p36", 52, S_IFBLK}, 145 10021 Sheshadri {"p5,raw", 21, S_IFCHR}, 146 10021 Sheshadri {"p6,raw", 22, S_IFCHR}, 147 10021 Sheshadri {"p7,raw", 23, S_IFCHR}, 148 10021 Sheshadri {"p8,raw", 24, S_IFCHR}, 149 10021 Sheshadri {"p9,raw", 25, S_IFCHR}, 150 10021 Sheshadri {"p10,raw", 26, S_IFCHR}, 151 10021 Sheshadri {"p11,raw", 27, S_IFCHR}, 152 10021 Sheshadri {"p12,raw", 28, S_IFCHR}, 153 10021 Sheshadri {"p13,raw", 29, S_IFCHR}, 154 10021 Sheshadri {"p14,raw", 30, S_IFCHR}, 155 10021 Sheshadri {"p15,raw", 31, S_IFCHR}, 156 10021 Sheshadri {"p16,raw", 32, S_IFCHR}, 157 10021 Sheshadri {"p17,raw", 33, S_IFCHR}, 158 10021 Sheshadri {"p18,raw", 34, S_IFCHR}, 159 10021 Sheshadri {"p19,raw", 35, S_IFCHR}, 160 10021 Sheshadri {"p20,raw", 36, S_IFCHR}, 161 10021 Sheshadri {"p21,raw", 37, S_IFCHR}, 162 10021 Sheshadri {"p22,raw", 38, S_IFCHR}, 163 10021 Sheshadri {"p23,raw", 39, S_IFCHR}, 164 10021 Sheshadri {"p24,raw", 40, S_IFCHR}, 165 10021 Sheshadri {"p25,raw", 41, S_IFCHR}, 166 10021 Sheshadri {"p26,raw", 42, S_IFCHR}, 167 10021 Sheshadri {"p27,raw", 43, S_IFCHR}, 168 10021 Sheshadri {"p28,raw", 44, S_IFCHR}, 169 10021 Sheshadri {"p29,raw", 45, S_IFCHR}, 170 10021 Sheshadri {"p30,raw", 46, S_IFCHR}, 171 10021 Sheshadri {"p31,raw", 47, S_IFCHR}, 172 10021 Sheshadri {"p32,raw", 48, S_IFCHR}, 173 10021 Sheshadri {"p33,raw", 49, S_IFCHR}, 174 10021 Sheshadri {"p34,raw", 50, S_IFCHR}, 175 10021 Sheshadri {"p35,raw", 51, S_IFCHR}, 176 10021 Sheshadri {"p36,raw", 52, S_IFCHR}, 177 10021 Sheshadri {0} 178 10021 Sheshadri }; 179 10021 Sheshadri #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 180 10021 Sheshadri #endif /* if defined(__i386) || defined(__amd64) */ 181 10021 Sheshadri 182 786 lclee static struct driver_minor_data dk_minor_data_efi[] = { 183 786 lclee {"a", 0, S_IFBLK}, 184 786 lclee {"b", 1, S_IFBLK}, 185 786 lclee {"c", 2, S_IFBLK}, 186 786 lclee {"d", 3, S_IFBLK}, 187 786 lclee {"e", 4, S_IFBLK}, 188 786 lclee {"f", 5, S_IFBLK}, 189 786 lclee {"g", 6, S_IFBLK}, 190 786 lclee {"wd", 7, S_IFBLK}, 191 8749 Shidokht #if defined(_SUNOS_VTOC_16) 192 8749 Shidokht {"i", 8, S_IFBLK}, 193 8749 Shidokht {"j", 9, S_IFBLK}, 194 8749 Shidokht {"k", 10, S_IFBLK}, 195 8749 Shidokht {"l", 11, S_IFBLK}, 196 8749 Shidokht {"m", 12, S_IFBLK}, 197 8749 Shidokht {"n", 13, S_IFBLK}, 198 8749 Shidokht {"o", 14, S_IFBLK}, 199 8749 Shidokht {"p", 15, S_IFBLK}, 200 8749 Shidokht #endif /* defined(_SUNOS_VTOC_16) */ 201 786 lclee #if defined(_FIRMWARE_NEEDS_FDISK) 202 786 lclee {"q", 16, S_IFBLK}, 203 786 lclee {"r", 17, S_IFBLK}, 204 786 lclee {"s", 18, S_IFBLK}, 205 786 lclee {"t", 19, S_IFBLK}, 206 786 lclee {"u", 20, S_IFBLK}, 207 786 lclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 208 786 lclee {"a,raw", 0, S_IFCHR}, 209 786 lclee {"b,raw", 1, S_IFCHR}, 210 786 lclee {"c,raw", 2, S_IFCHR}, 211 786 lclee {"d,raw", 3, S_IFCHR}, 212 786 lclee {"e,raw", 4, S_IFCHR}, 213 786 lclee {"f,raw", 5, S_IFCHR}, 214 786 lclee {"g,raw", 6, S_IFCHR}, 215 786 lclee {"wd,raw", 7, S_IFCHR}, 216 8749 Shidokht #if defined(_SUNOS_VTOC_16) 217 8749 Shidokht {"i,raw", 8, S_IFCHR}, 218 8749 Shidokht {"j,raw", 9, S_IFCHR}, 219 8749 Shidokht {"k,raw", 10, S_IFCHR}, 220 8749 Shidokht {"l,raw", 11, S_IFCHR}, 221 8749 Shidokht {"m,raw", 12, S_IFCHR}, 222 8749 Shidokht {"n,raw", 13, S_IFCHR}, 223 8749 Shidokht {"o,raw", 14, S_IFCHR}, 224 8749 Shidokht {"p,raw", 15, S_IFCHR}, 225 8749 Shidokht #endif /* defined(_SUNOS_VTOC_16) */ 226 786 lclee #if defined(_FIRMWARE_NEEDS_FDISK) 227 786 lclee {"q,raw", 16, S_IFCHR}, 228 786 lclee {"r,raw", 17, S_IFCHR}, 229 786 lclee {"s,raw", 18, S_IFCHR}, 230 786 lclee {"t,raw", 19, S_IFCHR}, 231 786 lclee {"u,raw", 20, S_IFCHR}, 232 786 lclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 233 786 lclee {0} 234 786 lclee }; 235 786 lclee 236 7224 cth /* 237 7224 cth * Declare the dynamic properties implemented in prop_op(9E) implementation 238 7224 cth * that we want to have show up in a di_init(3DEVINFO) device tree snapshot 239 7224 cth * of drivers that call cmlb_attach(). 240 7224 cth */ 241 7224 cth static i_ddi_prop_dyn_t cmlb_prop_dyn[] = { 242 7224 cth {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, 243 7224 cth {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, 244 7224 cth {"device-nblocks", DDI_PROP_TYPE_INT64}, 245 7224 cth {"device-blksize", DDI_PROP_TYPE_INT}, 246 7224 cth {NULL} 247 7224 cth }; 248 786 lclee 249 6318 edp /* 250 6318 edp * External kernel interfaces 251 6318 edp */ 252 786 lclee extern struct mod_ops mod_miscops; 253 6318 edp 254 6318 edp extern int ddi_create_internal_pathname(dev_info_t *dip, char *name, 255 6318 edp int spec_type, minor_t minor_num); 256 786 lclee 257 786 lclee /* 258 786 lclee * Global buffer and mutex for debug logging 259 786 lclee */ 260 786 lclee static char cmlb_log_buffer[1024]; 261 786 lclee static kmutex_t cmlb_log_mutex; 262 786 lclee 263 786 lclee 264 3525 shidokht struct cmlb_lun *cmlb_debug_cl = NULL; 265 786 lclee uint_t cmlb_level_mask = 0x0; 266 786 lclee 267 786 lclee int cmlb_rot_delay = 4; /* default rotational delay */ 268 786 lclee 269 786 lclee static struct modlmisc modlmisc = { 270 786 lclee &mod_miscops, /* Type of module */ 271 7563 Prasad "Common Labeling module" 272 786 lclee }; 273 786 lclee 274 786 lclee static struct modlinkage modlinkage = { 275 786 lclee MODREV_1, (void *)&modlmisc, NULL 276 786 lclee }; 277 786 lclee 278 786 lclee /* Local function prototypes */ 279 3525 shidokht static dev_t cmlb_make_device(struct cmlb_lun *cl); 280 8863 Edward static int cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid, 281 3525 shidokht int flags, void *tg_cookie); 282 3525 shidokht static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 283 3525 shidokht void *tg_cookie); 284 3525 shidokht static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, 285 3525 shidokht void *tg_cookie); 286 786 lclee static void cmlb_swap_efi_gpt(efi_gpt_t *e); 287 786 lclee static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p); 288 786 lclee static int cmlb_validate_efi(efi_gpt_t *labp); 289 3525 shidokht static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 290 3525 shidokht void *tg_cookie); 291 3525 shidokht static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie); 292 3525 shidokht static int cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *l, int flags); 293 3525 shidokht #if defined(_SUNOS_VTOC_8) 294 3525 shidokht static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 295 3525 shidokht #endif 296 3525 shidokht static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 297 3525 shidokht static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie); 298 3525 shidokht static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, 299 3525 shidokht void *tg_cookie); 300 3525 shidokht static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie); 301 3525 shidokht static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie); 302 3525 shidokht static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie); 303 3525 shidokht static int cmlb_create_minor_nodes(struct cmlb_lun *cl); 304 3525 shidokht static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie); 305 8863 Edward static boolean_t cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr); 306 3525 shidokht 307 3525 shidokht #if defined(__i386) || defined(__amd64) 308 3525 shidokht static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie); 309 786 lclee #endif 310 786 lclee 311 786 lclee #if defined(_FIRMWARE_NEEDS_FDISK) 312 8863 Edward static boolean_t cmlb_has_max_chs_vals(struct ipart *fdp); 313 786 lclee #endif 314 786 lclee 315 786 lclee #if defined(_SUNOS_VTOC_16) 316 10320 Larry static void cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity, 317 10320 Larry struct dk_geom *cl_g, void *tg_cookie); 318 3525 shidokht #endif 319 3525 shidokht 320 3525 shidokht static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 321 3525 shidokht void *tg_cookie); 322 3525 shidokht static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag); 323 3525 shidokht static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 324 3525 shidokht void *tg_cookie); 325 3525 shidokht static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag); 326 3525 shidokht static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, 327 3525 shidokht void *tg_cookie); 328 3525 shidokht static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 329 3525 shidokht int flag, void *tg_cookie); 330 3525 shidokht static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, 331 3525 shidokht void *tg_cookie); 332 7563 Prasad static int cmlb_dkio_get_extvtoc(struct cmlb_lun *cl, caddr_t arg, int flag, 333 7563 Prasad void *tg_cookie); 334 3525 shidokht static int cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 335 7563 Prasad int flag, void *tg_cookie); 336 7563 Prasad static int cmlb_dkio_set_extvtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 337 3525 shidokht int flag, void *tg_cookie); 338 3525 shidokht static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 339 3525 shidokht void *tg_cookie); 340 3525 shidokht static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 341 3525 shidokht void *tg_cookie); 342 3525 shidokht static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 343 3525 shidokht void *tg_cookie); 344 3525 shidokht 345 3525 shidokht #if defined(__i386) || defined(__amd64) 346 10021 Sheshadri static int cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag, 347 10021 Sheshadri void *tg_cookie); 348 10021 Sheshadri static int cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart, 349 10021 Sheshadri uint32_t start, uint32_t size); 350 10021 Sheshadri static int cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start, 351 10021 Sheshadri void *tg_cookie); 352 3525 shidokht static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag); 353 10320 Larry static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag, 354 10320 Larry void *tg_cookie); 355 3525 shidokht static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 356 7563 Prasad int flag); 357 7563 Prasad static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 358 786 lclee int flag); 359 3525 shidokht #endif 360 3525 shidokht 361 3525 shidokht static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...); 362 786 lclee static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level, 363 786 lclee const char *fmt, va_list ap); 364 786 lclee static void cmlb_log(dev_info_t *dev, char *label, uint_t level, 365 786 lclee const char *fmt, ...); 366 786 lclee 367 786 lclee int 368 786 lclee _init(void) 369 786 lclee { 370 786 lclee mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL); 371 786 lclee return (mod_install(&modlinkage)); 372 786 lclee } 373 786 lclee 374 786 lclee int 375 786 lclee _info(struct modinfo *modinfop) 376 786 lclee { 377 786 lclee return (mod_info(&modlinkage, modinfop)); 378 786 lclee } 379 786 lclee 380 786 lclee int 381 786 lclee _fini(void) 382 786 lclee { 383 786 lclee int err; 384 786 lclee 385 786 lclee if ((err = mod_remove(&modlinkage)) != 0) { 386 786 lclee return (err); 387 786 lclee } 388 786 lclee 389 786 lclee mutex_destroy(&cmlb_log_mutex); 390 786 lclee return (err); 391 786 lclee } 392 786 lclee 393 786 lclee /* 394 786 lclee * cmlb_dbg is used for debugging to log additional info 395 786 lclee * Level of output is controlled via cmlb_level_mask setting. 396 786 lclee */ 397 786 lclee static void 398 3525 shidokht cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...) 399 786 lclee { 400 786 lclee va_list ap; 401 786 lclee dev_info_t *dev; 402 786 lclee uint_t level_mask = 0; 403 786 lclee 404 3525 shidokht ASSERT(cl != NULL); 405 3525 shidokht dev = CMLB_DEVINFO(cl); 406 786 lclee ASSERT(dev != NULL); 407 786 lclee /* 408 786 lclee * Filter messages based on the global component and level masks, 409 3525 shidokht * also print if cl matches the value of cmlb_debug_cl, or if 410 3525 shidokht * cmlb_debug_cl is set to NULL. 411 786 lclee */ 412 786 lclee if (comp & CMLB_TRACE) 413 786 lclee level_mask |= CMLB_LOGMASK_TRACE; 414 786 lclee 415 786 lclee if (comp & CMLB_INFO) 416 786 lclee level_mask |= CMLB_LOGMASK_INFO; 417 786 lclee 418 786 lclee if (comp & CMLB_ERROR) 419 786 lclee level_mask |= CMLB_LOGMASK_ERROR; 420 786 lclee 421 786 lclee if ((cmlb_level_mask & level_mask) && 422 3525 shidokht ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) { 423 786 lclee va_start(ap, fmt); 424 3525 shidokht cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap); 425 786 lclee va_end(ap); 426 786 lclee } 427 786 lclee } 428 786 lclee 429 786 lclee /* 430 786 lclee * cmlb_log is basically a duplicate of scsi_log. It is redefined here 431 786 lclee * so that this module does not depend on scsi module. 432 786 lclee */ 433 786 lclee static void 434 786 lclee cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 435 786 lclee { 436 786 lclee va_list ap; 437 786 lclee 438 786 lclee va_start(ap, fmt); 439 786 lclee cmlb_v_log(dev, label, level, fmt, ap); 440 786 lclee va_end(ap); 441 786 lclee } 442 786 lclee 443 786 lclee static void 444 786 lclee cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, 445 786 lclee va_list ap) 446 786 lclee { 447 786 lclee static char name[256]; 448 786 lclee int log_only = 0; 449 786 lclee int boot_only = 0; 450 786 lclee int console_only = 0; 451 786 lclee 452 786 lclee mutex_enter(&cmlb_log_mutex); 453 786 lclee 454 786 lclee if (dev) { 455 786 lclee if (level == CE_PANIC || level == CE_WARN || 456 786 lclee level == CE_NOTE) { 457 786 lclee (void) sprintf(name, "%s (%s%d):\n", 458 786 lclee ddi_pathname(dev, cmlb_log_buffer), 459 786 lclee label, ddi_get_instance(dev)); 460 786 lclee } else { 461 786 lclee name[0] = '\0'; 462 786 lclee } 463 786 lclee } else { 464 786 lclee (void) sprintf(name, "%s:", label); 465 786 lclee } 466 786 lclee 467 786 lclee (void) vsprintf(cmlb_log_buffer, fmt, ap); 468 786 lclee 469 786 lclee switch (cmlb_log_buffer[0]) { 470 786 lclee case '!': 471 786 lclee log_only = 1; 472 786 lclee break; 473 786 lclee case '?': 474 786 lclee boot_only = 1; 475 786 lclee break; 476 786 lclee case '^': 477 786 lclee console_only = 1; 478 786 lclee break; 479 786 lclee } 480 786 lclee 481 786 lclee switch (level) { 482 786 lclee case CE_NOTE: 483 786 lclee level = CE_CONT; 484 786 lclee /* FALLTHROUGH */ 485 786 lclee case CE_CONT: 486 786 lclee case CE_WARN: 487 786 lclee case CE_PANIC: 488 786 lclee if (boot_only) { 489 786 lclee cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]); 490 786 lclee } else if (console_only) { 491 786 lclee cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]); 492 786 lclee } else if (log_only) { 493 786 lclee cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]); 494 786 lclee } else { 495 786 lclee cmn_err(level, "%s\t%s", name, cmlb_log_buffer); 496 786 lclee } 497 786 lclee break; 498 786 lclee case CE_IGNORE: 499 786 lclee break; 500 786 lclee default: 501 786 lclee cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer); 502 786 lclee break; 503 786 lclee } 504 786 lclee mutex_exit(&cmlb_log_mutex); 505 786 lclee } 506 786 lclee 507 786 lclee 508 786 lclee /* 509 786 lclee * cmlb_alloc_handle: 510 786 lclee * 511 786 lclee * Allocates a handle. 512 786 lclee * 513 786 lclee * Arguments: 514 786 lclee * cmlbhandlep pointer to handle 515 786 lclee * 516 786 lclee * Notes: 517 786 lclee * Allocates a handle and stores the allocated handle in the area 518 786 lclee * pointed to by cmlbhandlep 519 786 lclee * 520 786 lclee * Context: 521 786 lclee * Kernel thread only (can sleep). 522 786 lclee */ 523 786 lclee void 524 786 lclee cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep) 525 786 lclee { 526 3525 shidokht struct cmlb_lun *cl; 527 3525 shidokht 528 3525 shidokht cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP); 529 786 lclee ASSERT(cmlbhandlep != NULL); 530 786 lclee 531 3525 shidokht cl->cl_state = CMLB_INITED; 532 3525 shidokht cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 533 3525 shidokht mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL); 534 3525 shidokht 535 3525 shidokht *cmlbhandlep = (cmlb_handle_t)(cl); 536 786 lclee } 537 786 lclee 538 786 lclee /* 539 786 lclee * cmlb_free_handle 540 786 lclee * 541 786 lclee * Frees handle. 542 786 lclee * 543 786 lclee * Arguments: 544 786 lclee * cmlbhandlep pointer to handle 545 786 lclee */ 546 786 lclee void 547 786 lclee cmlb_free_handle(cmlb_handle_t *cmlbhandlep) 548 786 lclee { 549 3525 shidokht struct cmlb_lun *cl; 550 3525 shidokht 551 3525 shidokht cl = (struct cmlb_lun *)*cmlbhandlep; 552 3525 shidokht if (cl != NULL) { 553 3525 shidokht mutex_destroy(CMLB_MUTEX(cl)); 554 3525 shidokht kmem_free(cl, sizeof (struct cmlb_lun)); 555 786 lclee } 556 786 lclee 557 786 lclee } 558 786 lclee 559 786 lclee /* 560 786 lclee * cmlb_attach: 561 786 lclee * 562 786 lclee * Attach handle to device, create minor nodes for device. 563 786 lclee * 564 786 lclee * Arguments: 565 786 lclee * devi pointer to device's dev_info structure. 566 786 lclee * tgopsp pointer to array of functions cmlb can use to callback 567 786 lclee * to target driver. 568 786 lclee * 569 786 lclee * device_type Peripheral device type as defined in 570 786 lclee * scsi/generic/inquiry.h 571 786 lclee * 572 786 lclee * is_removable whether or not device is removable. 573 3525 shidokht * 574 3525 shidokht * is_hotpluggable whether or not device is hotpluggable. 575 786 lclee * 576 786 lclee * node_type minor node type (as used by ddi_create_minor_node) 577 786 lclee * 578 786 lclee * alter_behavior 579 786 lclee * bit flags: 580 786 lclee * 581 786 lclee * CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create 582 786 lclee * an alternate slice for the default label, if 583 786 lclee * device type is DTYPE_DIRECT an architectures default 584 786 lclee * label type is VTOC16. 585 786 lclee * Otherwise alternate slice will no be created. 586 786 lclee * 587 786 lclee * 588 786 lclee * CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default 589 786 lclee * geometry and label for DKIOCGGEOM and DKIOCGVTOC 590 786 lclee * on architecture with VTOC8 label types. 591 786 lclee * 592 3525 shidokht * CMLB_OFF_BY_ONE: do the workaround for legacy off-by- 593 3525 shidokht * one bug in obtaining capacity (in sd): 594 3525 shidokht * SCSI READ_CAPACITY command returns the LBA number of the 595 3525 shidokht * last logical block, but sd once treated this number as 596 3525 shidokht * disks' capacity on x86 platform. And LBAs are addressed 597 3525 shidokht * based 0. So the last block was lost on x86 platform. 598 3525 shidokht * 599 3525 shidokht * Now, we remove this workaround. In order for present sd 600 3525 shidokht * driver to work with disks which are labeled/partitioned 601 3525 shidokht * via previous sd, we add workaround as follows: 602 3525 shidokht * 603 3525 shidokht * 1) Locate backup EFI label: cmlb searches the next to 604 3525 shidokht * last 605 3525 shidokht * block for backup EFI label. If fails, it will 606 3525 shidokht * turn to the last block for backup EFI label; 607 3525 shidokht * 608 3525 shidokht * 2) Clear backup EFI label: cmlb first search the last 609 3525 shidokht * block for backup EFI label, and will search the 610 3525 shidokht * next to last block only if failed for the last 611 3525 shidokht * block. 612 3525 shidokht * 613 3525 shidokht * 3) Calculate geometry:refer to cmlb_convert_geometry() 614 3525 shidokht * If capacity increasing by 1 causes disks' capacity 615 7563 Prasad * to cross over the limits in geometry calculation, 616 3525 shidokht * geometry info will change. This will raise an issue: 617 3525 shidokht * In case that primary VTOC label is destroyed, format 618 3525 shidokht * commandline can restore it via backup VTOC labels. 619 3525 shidokht * And format locates backup VTOC labels by use of 620 3525 shidokht * geometry. So changing geometry will 621 3525 shidokht * prevent format from finding backup VTOC labels. To 622 3525 shidokht * eliminate this side effect for compatibility, 623 3525 shidokht * sd uses (capacity -1) to calculate geometry; 624 3525 shidokht * 625 3525 shidokht * 4) 1TB disks: some important data structures use 626 3525 shidokht * 32-bit signed long/int (for example, daddr_t), 627 3525 shidokht * so that sd doesn't support a disk with capacity 628 3525 shidokht * larger than 1TB on 32-bit platform. However, 629 3525 shidokht * for exactly 1TB disk, it was treated as (1T - 512)B 630 3525 shidokht * in the past, and could have valid Solaris 631 3525 shidokht * partitions. To workaround this, if an exactly 1TB 632 3525 shidokht * disk has Solaris fdisk partition, it will be allowed 633 3525 shidokht * to work with sd. 634 3525 shidokht * 635 5084 johnlev * 636 5084 johnlev * 637 5084 johnlev * CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering 638 5084 johnlev * the entire disk, if there is no valid partition info. 639 5084 johnlev * If there is a valid Solaris partition, s0 and s2 will 640 5084 johnlev * only cover the entire Solaris partition. 641 3525 shidokht * 642 786 lclee * 643 786 lclee * cmlbhandle cmlb handle associated with device 644 3525 shidokht * 645 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 646 3525 shidokht * driver when we call back to it through tg_ops. 647 786 lclee * 648 786 lclee * Notes: 649 786 lclee * Assumes a default label based on capacity for non-removable devices. 650 786 lclee * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC 651 786 lclee * for the architecture). 652 786 lclee * 653 786 lclee * For removable devices, default label type is assumed to be VTOC 654 786 lclee * type. Create minor nodes based on a default label type. 655 786 lclee * Label on the media is not validated. 656 786 lclee * minor number consists of: 657 786 lclee * if _SUNOS_VTOC_8 is defined 658 786 lclee * lowest 3 bits is taken as partition number 659 786 lclee * the rest is instance number 660 786 lclee * if _SUNOS_VTOC_16 is defined 661 786 lclee * lowest 6 bits is taken as partition number 662 786 lclee * the rest is instance number 663 786 lclee * 664 786 lclee * 665 786 lclee * Return values: 666 786 lclee * 0 Success 667 786 lclee * ENXIO creating minor nodes failed. 668 3525 shidokht * EINVAL invalid arg, unsupported tg_ops version 669 786 lclee */ 670 786 lclee int 671 786 lclee cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type, 672 8863 Edward boolean_t is_removable, boolean_t is_hotpluggable, char *node_type, 673 3525 shidokht int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie) 674 3525 shidokht { 675 3525 shidokht 676 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 677 786 lclee diskaddr_t cap; 678 786 lclee int status; 679 8863 Edward 680 8863 Edward ASSERT(VALID_BOOLEAN(is_removable)); 681 8863 Edward ASSERT(VALID_BOOLEAN(is_hotpluggable)); 682 786 lclee 683 3525 shidokht if (tgopsp->tg_version < TG_DK_OPS_VERSION_1) 684 3525 shidokht return (EINVAL); 685 3525 shidokht 686 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 687 3525 shidokht 688 3525 shidokht CMLB_DEVINFO(cl) = devi; 689 3525 shidokht cl->cmlb_tg_ops = tgopsp; 690 3525 shidokht cl->cl_device_type = device_type; 691 3525 shidokht cl->cl_is_removable = is_removable; 692 3525 shidokht cl->cl_is_hotpluggable = is_hotpluggable; 693 3525 shidokht cl->cl_node_type = node_type; 694 3525 shidokht cl->cl_sys_blocksize = DEV_BSIZE; 695 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 696 3525 shidokht cl->cl_def_labeltype = CMLB_LABEL_VTOC; 697 3525 shidokht cl->cl_alter_behavior = alter_behavior; 698 3525 shidokht cl->cl_reserved = -1; 699 7563 Prasad cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN; 700 10021 Sheshadri #if defined(__i386) || defined(__amd64) 701 10021 Sheshadri cl->cl_logical_drive_count = 0; 702 10021 Sheshadri #endif 703 7563 Prasad 704 8863 Edward if (!is_removable) { 705 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 706 3525 shidokht status = DK_TG_GETCAP(cl, &cap, tg_cookie); 707 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 708 7563 Prasad if (status == 0 && cap > CMLB_EXTVTOC_LIMIT) { 709 7563 Prasad /* set default EFI if > 2TB */ 710 3525 shidokht cl->cl_def_labeltype = CMLB_LABEL_EFI; 711 786 lclee } 712 786 lclee } 713 786 lclee 714 786 lclee /* create minor nodes based on default label type */ 715 3525 shidokht cl->cl_last_labeltype = CMLB_LABEL_UNDEF; 716 3525 shidokht cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 717 3525 shidokht 718 3525 shidokht if (cmlb_create_minor_nodes(cl) != 0) { 719 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 720 786 lclee return (ENXIO); 721 786 lclee } 722 786 lclee 723 7224 cth /* Define the dynamic properties for devinfo spapshots. */ 724 7224 cth i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn); 725 7224 cth 726 3525 shidokht cl->cl_state = CMLB_ATTACHED; 727 3525 shidokht 728 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 729 786 lclee return (0); 730 786 lclee } 731 786 lclee 732 786 lclee /* 733 786 lclee * cmlb_detach: 734 786 lclee * 735 786 lclee * Invalidate in-core labeling data and remove all minor nodes for 736 786 lclee * the device associate with handle. 737 786 lclee * 738 786 lclee * Arguments: 739 786 lclee * cmlbhandle cmlb handle associated with device. 740 786 lclee * 741 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 742 3525 shidokht * driver when we call back to it through tg_ops. 743 3525 shidokht * 744 3525 shidokht */ 745 3525 shidokht /*ARGSUSED1*/ 746 786 lclee void 747 3525 shidokht cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie) 748 3525 shidokht { 749 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 750 3525 shidokht 751 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 752 3525 shidokht cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 753 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 754 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 755 7224 cth i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL); 756 3525 shidokht cl->cl_state = CMLB_INITED; 757 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 758 786 lclee } 759 786 lclee 760 786 lclee /* 761 786 lclee * cmlb_validate: 762 786 lclee * 763 786 lclee * Validates label. 764 786 lclee * 765 786 lclee * Arguments 766 786 lclee * cmlbhandle cmlb handle associated with device. 767 3525 shidokht * 768 3525 shidokht * flags operation flags. used for verbosity control 769 3525 shidokht * 770 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 771 3525 shidokht * driver when we call back to it through tg_ops. 772 3525 shidokht * 773 786 lclee * 774 786 lclee * Notes: 775 786 lclee * If new label type is different from the current, adjust minor nodes 776 786 lclee * accordingly. 777 786 lclee * 778 786 lclee * Return values: 779 786 lclee * 0 success 780 786 lclee * Note: having fdisk but no solaris partition is assumed 781 786 lclee * success. 782 786 lclee * 783 786 lclee * ENOMEM memory allocation failed 784 786 lclee * EIO i/o errors during read or get capacity 785 786 lclee * EACCESS reservation conflicts 786 786 lclee * EINVAL label was corrupt, or no default label was assumed 787 786 lclee * ENXIO invalid handle 788 786 lclee */ 789 786 lclee int 790 3525 shidokht cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie) 791 3525 shidokht { 792 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 793 786 lclee int rval; 794 786 lclee int ret = 0; 795 786 lclee 796 786 lclee /* 797 3525 shidokht * Temp work-around checking cl for NULL since there is a bug 798 786 lclee * in sd_detach calling this routine from taskq_dispatch 799 786 lclee * inited function. 800 786 lclee */ 801 3525 shidokht if (cl == NULL) 802 786 lclee return (ENXIO); 803 786 lclee 804 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 805 3525 shidokht if (cl->cl_state < CMLB_ATTACHED) { 806 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 807 786 lclee return (ENXIO); 808 786 lclee } 809 786 lclee 810 8863 Edward rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, B_TRUE, 811 3525 shidokht flags, tg_cookie); 812 786 lclee 813 786 lclee if (rval == ENOTSUP) { 814 8863 Edward if (cl->cl_f_geometry_is_valid) { 815 3525 shidokht cl->cl_cur_labeltype = CMLB_LABEL_EFI; 816 786 lclee ret = 0; 817 786 lclee } else { 818 786 lclee ret = EINVAL; 819 786 lclee } 820 786 lclee } else { 821 786 lclee ret = rval; 822 786 lclee if (ret == 0) 823 3525 shidokht cl->cl_cur_labeltype = CMLB_LABEL_VTOC; 824 786 lclee } 825 786 lclee 826 786 lclee if (ret == 0) 827 3525 shidokht (void) cmlb_create_minor_nodes(cl); 828 3525 shidokht 829 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 830 786 lclee return (ret); 831 786 lclee } 832 786 lclee 833 786 lclee /* 834 786 lclee * cmlb_invalidate: 835 786 lclee * Invalidate in core label data 836 786 lclee * 837 786 lclee * Arguments: 838 786 lclee * cmlbhandle cmlb handle associated with device. 839 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 840 3525 shidokht * driver when we call back to it through tg_ops. 841 3525 shidokht */ 842 3525 shidokht /*ARGSUSED1*/ 843 786 lclee void 844 3525 shidokht cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie) 845 3525 shidokht { 846 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 847 3525 shidokht 848 3525 shidokht if (cl == NULL) 849 786 lclee return; 850 786 lclee 851 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 852 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 853 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 854 3525 shidokht } 855 3525 shidokht 856 3525 shidokht /* 857 3525 shidokht * cmlb_is_valid 858 3525 shidokht * Get status on whether the incore label/geom data is valid 859 3525 shidokht * 860 3525 shidokht * Arguments: 861 3525 shidokht * cmlbhandle cmlb handle associated with device. 862 3525 shidokht * 863 3525 shidokht * Return values: 864 8863 Edward * B_TRUE if incore label/geom data is valid. 865 8863 Edward * B_FALSE otherwise. 866 8863 Edward * 867 8863 Edward */ 868 8863 Edward 869 8863 Edward 870 8863 Edward boolean_t 871 3525 shidokht cmlb_is_valid(cmlb_handle_t cmlbhandle) 872 3525 shidokht { 873 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 874 3525 shidokht 875 3525 shidokht if (cmlbhandle == NULL) 876 8863 Edward return (B_FALSE); 877 3525 shidokht 878 3525 shidokht return (cl->cl_f_geometry_is_valid); 879 3525 shidokht 880 3525 shidokht } 881 3525 shidokht 882 3525 shidokht 883 786 lclee 884 786 lclee /* 885 786 lclee * cmlb_close: 886 786 lclee * 887 786 lclee * Close the device, revert to a default label minor node for the device, 888 786 lclee * if it is removable. 889 786 lclee * 890 786 lclee * Arguments: 891 786 lclee * cmlbhandle cmlb handle associated with device. 892 786 lclee * 893 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 894 3525 shidokht * driver when we call back to it through tg_ops. 895 786 lclee * Return values: 896 786 lclee * 0 Success 897 786 lclee * ENXIO Re-creating minor node failed. 898 786 lclee */ 899 3525 shidokht /*ARGSUSED1*/ 900 3525 shidokht int 901 3525 shidokht cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie) 902 3525 shidokht { 903 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 904 3525 shidokht 905 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 906 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 907 786 lclee 908 786 lclee /* revert to default minor node for this device */ 909 3525 shidokht if (ISREMOVABLE(cl)) { 910 3525 shidokht cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 911 3525 shidokht (void) cmlb_create_minor_nodes(cl); 912 3525 shidokht } 913 3525 shidokht 914 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 915 786 lclee return (0); 916 786 lclee } 917 786 lclee 918 786 lclee /* 919 786 lclee * cmlb_get_devid_block: 920 786 lclee * get the block number where device id is stored. 921 786 lclee * 922 786 lclee * Arguments: 923 786 lclee * cmlbhandle cmlb handle associated with device. 924 786 lclee * devidblockp pointer to block number. 925 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 926 3525 shidokht * driver when we call back to it through tg_ops. 927 786 lclee * 928 786 lclee * Notes: 929 786 lclee * It stores the block number of device id in the area pointed to 930 786 lclee * by devidblockp. 931 786 lclee * with the block number of device id. 932 786 lclee * 933 786 lclee * Return values: 934 786 lclee * 0 success 935 786 lclee * EINVAL device id does not apply to current label type. 936 786 lclee */ 937 3525 shidokht /*ARGSUSED2*/ 938 3525 shidokht int 939 3525 shidokht cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp, 940 3525 shidokht void *tg_cookie) 941 786 lclee { 942 786 lclee daddr_t spc, blk, head, cyl; 943 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 944 3525 shidokht 945 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 946 3525 shidokht if (cl->cl_state < CMLB_ATTACHED) { 947 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 948 3525 shidokht return (EINVAL); 949 3525 shidokht } 950 3525 shidokht 951 8863 Edward if ((!cl->cl_f_geometry_is_valid) || 952 3525 shidokht (cl->cl_solaris_size < DK_LABEL_LOC)) { 953 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 954 3525 shidokht return (EINVAL); 955 3525 shidokht } 956 3525 shidokht 957 3525 shidokht if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) { 958 3525 shidokht if (cl->cl_reserved != -1) { 959 3525 shidokht blk = cl->cl_map[cl->cl_reserved].dkl_cylno; 960 3525 shidokht } else { 961 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 962 3525 shidokht return (EINVAL); 963 3525 shidokht } 964 3525 shidokht } else { 965 6513 ml40262 /* if the disk is unlabeled, don't write a devid to it */ 966 7563 Prasad if (cl->cl_label_from_media != CMLB_LABEL_VTOC) { 967 6513 ml40262 mutex_exit(CMLB_MUTEX(cl)); 968 6513 ml40262 return (EINVAL); 969 6513 ml40262 } 970 6513 ml40262 971 786 lclee /* this geometry doesn't allow us to write a devid */ 972 3525 shidokht if (cl->cl_g.dkg_acyl < 2) { 973 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 974 786 lclee return (EINVAL); 975 786 lclee } 976 786 lclee 977 786 lclee /* 978 786 lclee * Subtract 2 guarantees that the next to last cylinder 979 786 lclee * is used 980 786 lclee */ 981 3525 shidokht cyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl - 2; 982 3525 shidokht spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 983 3525 shidokht head = cl->cl_g.dkg_nhead - 1; 984 6513 ml40262 blk = cl->cl_solaris_offset + 985 6513 ml40262 (cyl * (spc - cl->cl_g.dkg_apc)) + 986 3525 shidokht (head * cl->cl_g.dkg_nsect) + 1; 987 3525 shidokht } 988 3525 shidokht 989 786 lclee *devidblockp = blk; 990 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 991 786 lclee return (0); 992 786 lclee } 993 786 lclee 994 786 lclee /* 995 786 lclee * cmlb_partinfo: 996 786 lclee * Get partition info for specified partition number. 997 786 lclee * 998 786 lclee * Arguments: 999 786 lclee * cmlbhandle cmlb handle associated with device. 1000 786 lclee * part partition number 1001 786 lclee * nblocksp pointer to number of blocks 1002 786 lclee * startblockp pointer to starting block 1003 786 lclee * partnamep pointer to name of partition 1004 786 lclee * tagp pointer to tag info 1005 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 1006 3525 shidokht * driver when we call back to it through tg_ops. 1007 786 lclee * 1008 786 lclee * 1009 786 lclee * Notes: 1010 786 lclee * If in-core label is not valid, this functions tries to revalidate 1011 786 lclee * the label. If label is valid, it stores the total number of blocks 1012 786 lclee * in this partition in the area pointed to by nblocksp, starting 1013 786 lclee * block number in area pointed to by startblockp, pointer to partition 1014 786 lclee * name in area pointed to by partnamep, and tag value in area 1015 786 lclee * pointed by tagp. 1016 786 lclee * For EFI labels, tag value will be set to 0. 1017 786 lclee * 1018 786 lclee * For all nblocksp, startblockp and partnamep, tagp, a value of NULL 1019 786 lclee * indicates the corresponding info is not requested. 1020 786 lclee * 1021 786 lclee * 1022 786 lclee * Return values: 1023 786 lclee * 0 success 1024 786 lclee * EINVAL no valid label or requested partition number is invalid. 1025 786 lclee * 1026 786 lclee */ 1027 786 lclee int 1028 786 lclee cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp, 1029 3525 shidokht diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie) 1030 3525 shidokht { 1031 3525 shidokht 1032 3525 shidokht struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 1033 786 lclee int rval; 1034 10021 Sheshadri #if defined(__i386) || defined(__amd64) 1035 10021 Sheshadri int ext_part; 1036 10021 Sheshadri #endif 1037 786 lclee 1038 3525 shidokht ASSERT(cl != NULL); 1039 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 1040 3525 shidokht if (cl->cl_state < CMLB_ATTACHED) { 1041 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1042 786 lclee return (EINVAL); 1043 786 lclee } 1044 786 lclee 1045 786 lclee if (part < 0 || part >= MAXPART) { 1046 786 lclee rval = EINVAL; 1047 786 lclee } else { 1048 8863 Edward if (!cl->cl_f_geometry_is_valid) 1049 8863 Edward (void) cmlb_validate_geometry((struct cmlb_lun *)cl, 1050 8863 Edward B_FALSE, 0, tg_cookie); 1051 8863 Edward 1052 8863 Edward #if defined(_SUNOS_VTOC_16) 1053 8863 Edward if (((!cl->cl_f_geometry_is_valid) || 1054 7563 Prasad (part < NDKMAP && cl->cl_solaris_size == 0)) && 1055 7563 Prasad (part != P0_RAW_DISK)) { 1056 7563 Prasad #else 1057 8863 Edward if ((!cl->cl_f_geometry_is_valid) || 1058 3525 shidokht (part < NDKMAP && cl->cl_solaris_size == 0)) { 1059 7563 Prasad #endif 1060 786 lclee rval = EINVAL; 1061 786 lclee } else { 1062 786 lclee if (startblockp != NULL) 1063 3525 shidokht *startblockp = (diskaddr_t)cl->cl_offset[part]; 1064 786 lclee 1065 786 lclee if (nblocksp != NULL) 1066 786 lclee *nblocksp = (diskaddr_t) 1067 3525 shidokht cl->cl_map[part].dkl_nblk; 1068 786 lclee 1069 786 lclee if (tagp != NULL) 1070 3525 shidokht if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 1071 786 lclee *tagp = V_UNASSIGNED; 1072 786 lclee else 1073 3525 shidokht *tagp = cl->cl_vtoc.v_part[part].p_tag; 1074 786 lclee rval = 0; 1075 786 lclee } 1076 786 lclee 1077 786 lclee /* consistent with behavior of sd for getting minor name */ 1078 10021 Sheshadri if (partnamep != NULL) { 1079 10021 Sheshadri #if defined(__i386) || defined(__amd64) 1080 10021 Sheshadri #if defined(_FIRMWARE_NEEDS_FDISK) 1081 10021 Sheshadri if (part > FDISK_P4) { 1082 10021 Sheshadri ext_part = part-FDISK_P4-1; 1083 10021 Sheshadri *partnamep = dk_ext_minor_data[ext_part].name; 1084 10021 Sheshadri } else 1085 10021 Sheshadri #endif 1086 10021 Sheshadri #endif 1087 786 lclee *partnamep = dk_minor_data[part].name; 1088 10021 Sheshadri } 1089 786 lclee 1090 6590 yl194034 } 1091 6590 yl194034 1092 6590 yl194034 mutex_exit(CMLB_MUTEX(cl)); 1093 6590 yl194034 return (rval); 1094 6590 yl194034 } 1095 6590 yl194034 1096 6590 yl194034 /* 1097 6590 yl194034 * cmlb_efi_label_capacity: 1098 6590 yl194034 * Get capacity stored in EFI disk label. 1099 6590 yl194034 * 1100 6590 yl194034 * Arguments: 1101 6590 yl194034 * cmlbhandle cmlb handle associated with device. 1102 6590 yl194034 * capacity pointer to capacity stored in EFI disk label. 1103 6590 yl194034 * tg_cookie cookie from target driver to be passed back to target 1104 6590 yl194034 * driver when we call back to it through tg_ops. 1105 6590 yl194034 * 1106 6590 yl194034 * 1107 6590 yl194034 * Notes: 1108 6590 yl194034 * If in-core label is not valid, this functions tries to revalidate 1109 6590 yl194034 * the label. If label is valid and is an EFI label, it stores the capacity 1110 6590 yl194034 * in disk label in the area pointed to by capacity. 1111 6590 yl194034 * 1112 6590 yl194034 * 1113 6590 yl194034 * Return values: 1114 6590 yl194034 * 0 success 1115 6590 yl194034 * EINVAL no valid EFI label or capacity is NULL. 1116 6590 yl194034 * 1117 6590 yl194034 */ 1118 6590 yl194034 int 1119 6590 yl194034 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity, 1120 6590 yl194034 void *tg_cookie) 1121 6590 yl194034 { 1122 6590 yl194034 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 1123 6590 yl194034 int rval; 1124 6590 yl194034 1125 6590 yl194034 ASSERT(cl != NULL); 1126 6590 yl194034 mutex_enter(CMLB_MUTEX(cl)); 1127 6590 yl194034 if (cl->cl_state < CMLB_ATTACHED) { 1128 6590 yl194034 mutex_exit(CMLB_MUTEX(cl)); 1129 6590 yl194034 return (EINVAL); 1130 6590 yl194034 } 1131 6590 yl194034 1132 8863 Edward if (!cl->cl_f_geometry_is_valid) 1133 8863 Edward (void) cmlb_validate_geometry((struct cmlb_lun *)cl, B_FALSE, 1134 6590 yl194034 0, tg_cookie); 1135 6590 yl194034 1136 8863 Edward if ((!cl->cl_f_geometry_is_valid) || (capacity == NULL) || 1137 6590 yl194034 (cl->cl_cur_labeltype != CMLB_LABEL_EFI)) { 1138 6590 yl194034 rval = EINVAL; 1139 6590 yl194034 } else { 1140 6590 yl194034 *capacity = (diskaddr_t)cl->cl_map[WD_NODE].dkl_nblk; 1141 6590 yl194034 rval = 0; 1142 786 lclee } 1143 786 lclee 1144 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1145 3525 shidokht return (rval); 1146 3525 shidokht } 1147 3525 shidokht 1148 3525 shidokht /* Caller should make sure Test Unit Ready succeeds before calling this. */ 1149 3525 shidokht /*ARGSUSED*/ 1150 786 lclee int 1151 786 lclee cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, 1152 3525 shidokht int flag, cred_t *cred_p, int *rval_p, void *tg_cookie) 1153 786 lclee { 1154 786 lclee 1155 786 lclee int err; 1156 3525 shidokht struct cmlb_lun *cl; 1157 3525 shidokht 1158 3525 shidokht cl = (struct cmlb_lun *)cmlbhandle; 1159 3525 shidokht 1160 3525 shidokht ASSERT(cl != NULL); 1161 3525 shidokht 1162 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 1163 3525 shidokht if (cl->cl_state < CMLB_ATTACHED) { 1164 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1165 3525 shidokht return (EIO); 1166 786 lclee } 1167 786 lclee 1168 786 lclee switch (cmd) { 1169 7563 Prasad case DKIOCSEXTVTOC: 1170 3525 shidokht case DKIOCSGEOM: 1171 786 lclee case DKIOCSETEFI: 1172 786 lclee case DKIOCSMBOOT: 1173 10021 Sheshadri #if defined(__i386) || defined(__amd64) 1174 10021 Sheshadri case DKIOCSETEXTPART: 1175 10021 Sheshadri #endif 1176 786 lclee break; 1177 7563 Prasad case DKIOCSVTOC: 1178 7563 Prasad #if defined(__i386) || defined(__amd64) 1179 7563 Prasad case DKIOCPARTINFO: 1180 7563 Prasad #endif 1181 7563 Prasad if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) { 1182 7563 Prasad mutex_exit(CMLB_MUTEX(cl)); 1183 7563 Prasad return (EOVERFLOW); 1184 7563 Prasad } 1185 7563 Prasad break; 1186 786 lclee default: 1187 7563 Prasad (void) cmlb_validate_geometry(cl, 1, CMLB_SILENT, 1188 3903 shidokht tg_cookie); 1189 3525 shidokht 1190 7563 Prasad switch (cmd) { 1191 7563 Prasad case DKIOCGVTOC: 1192 7563 Prasad case DKIOCGAPART: 1193 7563 Prasad case DKIOCSAPART: 1194 7563 Prasad 1195 7563 Prasad if (cl->cl_label_from_media == CMLB_LABEL_EFI) { 1196 7563 Prasad /* GPT label on disk */ 1197 7563 Prasad mutex_exit(CMLB_MUTEX(cl)); 1198 7563 Prasad return (ENOTSUP); 1199 7563 Prasad } else if 1200 7563 Prasad (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) { 1201 7563 Prasad mutex_exit(CMLB_MUTEX(cl)); 1202 7563 Prasad return (EOVERFLOW); 1203 7563 Prasad } 1204 7563 Prasad break; 1205 7563 Prasad 1206 7563 Prasad case DKIOCGGEOM: 1207 7563 Prasad if (cl->cl_label_from_media == CMLB_LABEL_EFI) { 1208 7563 Prasad /* GPT label on disk */ 1209 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1210 786 lclee return (ENOTSUP); 1211 786 lclee } 1212 7563 Prasad break; 1213 7563 Prasad default: 1214 7563 Prasad break; 1215 7563 Prasad } 1216 3525 shidokht } 1217 3525 shidokht 1218 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1219 786 lclee 1220 786 lclee switch (cmd) { 1221 786 lclee case DKIOCGGEOM: 1222 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n"); 1223 3525 shidokht err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie); 1224 786 lclee break; 1225 786 lclee 1226 786 lclee case DKIOCSGEOM: 1227 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n"); 1228 3525 shidokht err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag); 1229 786 lclee break; 1230 786 lclee 1231 786 lclee case DKIOCGAPART: 1232 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n"); 1233 3525 shidokht err = cmlb_dkio_get_partition(cl, (caddr_t)arg, 1234 3525 shidokht flag, tg_cookie); 1235 786 lclee break; 1236 786 lclee 1237 786 lclee case DKIOCSAPART: 1238 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n"); 1239 3525 shidokht err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag); 1240 786 lclee break; 1241 786 lclee 1242 786 lclee case DKIOCGVTOC: 1243 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n"); 1244 3525 shidokht err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie); 1245 786 lclee break; 1246 786 lclee 1247 7563 Prasad case DKIOCGEXTVTOC: 1248 7563 Prasad cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n"); 1249 7563 Prasad err = cmlb_dkio_get_extvtoc(cl, (caddr_t)arg, flag, tg_cookie); 1250 7563 Prasad break; 1251 7563 Prasad 1252 786 lclee case DKIOCGETEFI: 1253 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n"); 1254 3525 shidokht err = cmlb_dkio_get_efi(cl, (caddr_t)arg, flag, tg_cookie); 1255 786 lclee break; 1256 786 lclee 1257 786 lclee case DKIOCPARTITION: 1258 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTITION\n"); 1259 3525 shidokht err = cmlb_dkio_partition(cl, (caddr_t)arg, flag, tg_cookie); 1260 786 lclee break; 1261 786 lclee 1262 786 lclee case DKIOCSVTOC: 1263 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n"); 1264 3525 shidokht err = cmlb_dkio_set_vtoc(cl, dev, (caddr_t)arg, flag, 1265 3525 shidokht tg_cookie); 1266 786 lclee break; 1267 786 lclee 1268 7563 Prasad case DKIOCSEXTVTOC: 1269 7563 Prasad cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n"); 1270 7563 Prasad err = cmlb_dkio_set_extvtoc(cl, dev, (caddr_t)arg, flag, 1271 7563 Prasad tg_cookie); 1272 7563 Prasad break; 1273 7563 Prasad 1274 786 lclee case DKIOCSETEFI: 1275 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEFI\n"); 1276 3525 shidokht err = cmlb_dkio_set_efi(cl, dev, (caddr_t)arg, flag, tg_cookie); 1277 786 lclee break; 1278 786 lclee 1279 786 lclee case DKIOCGMBOOT: 1280 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCGMBOOT\n"); 1281 3525 shidokht err = cmlb_dkio_get_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1282 786 lclee break; 1283 786 lclee 1284 786 lclee case DKIOCSMBOOT: 1285 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCSMBOOT\n"); 1286 3525 shidokht err = cmlb_dkio_set_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1287 786 lclee break; 1288 786 lclee case DKIOCG_PHYGEOM: 1289 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n"); 1290 3525 shidokht #if defined(__i386) || defined(__amd64) 1291 10320 Larry err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag, tg_cookie); 1292 786 lclee #else 1293 786 lclee err = ENOTTY; 1294 786 lclee #endif 1295 786 lclee break; 1296 786 lclee case DKIOCG_VIRTGEOM: 1297 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_VIRTGEOM\n"); 1298 3525 shidokht #if defined(__i386) || defined(__amd64) 1299 3525 shidokht err = cmlb_dkio_get_virtgeom(cl, (caddr_t)arg, flag); 1300 786 lclee #else 1301 786 lclee err = ENOTTY; 1302 786 lclee #endif 1303 786 lclee break; 1304 786 lclee case DKIOCPARTINFO: 1305 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO"); 1306 3525 shidokht #if defined(__i386) || defined(__amd64) 1307 3525 shidokht err = cmlb_dkio_partinfo(cl, dev, (caddr_t)arg, flag); 1308 7563 Prasad #else 1309 7563 Prasad err = ENOTTY; 1310 7563 Prasad #endif 1311 7563 Prasad break; 1312 7563 Prasad case DKIOCEXTPARTINFO: 1313 7563 Prasad cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO"); 1314 7563 Prasad #if defined(__i386) || defined(__amd64) 1315 7563 Prasad err = cmlb_dkio_extpartinfo(cl, dev, (caddr_t)arg, flag); 1316 786 lclee #else 1317 786 lclee err = ENOTTY; 1318 786 lclee #endif 1319 786 lclee break; 1320 10021 Sheshadri #if defined(__i386) || defined(__amd64) 1321 10021 Sheshadri case DKIOCSETEXTPART: 1322 10021 Sheshadri cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEXTPART"); 1323 10021 Sheshadri err = cmlb_dkio_set_ext_part(cl, (caddr_t)arg, flag, tg_cookie); 1324 10021 Sheshadri break; 1325 10021 Sheshadri #endif 1326 786 lclee default: 1327 786 lclee err = ENOTTY; 1328 786 lclee 1329 786 lclee } 1330 7224 cth 1331 7224 cth /* 1332 7224 cth * An ioctl that succeeds and changed ('set') size(9P) information 1333 7224 cth * needs to invalidate the cached devinfo snapshot to avoid having 1334 7224 cth * old information being returned in a snapshots. 1335 7224 cth * 1336 7224 cth * NB: When available, call ddi_change_minor_node() to clear 1337 7224 cth * SSIZEVALID in specfs vnodes via spec_size_invalidate(). 1338 7224 cth */ 1339 7224 cth if (err == 0) { 1340 7224 cth switch (cmd) { 1341 7224 cth case DKIOCSGEOM: 1342 7224 cth case DKIOCSAPART: 1343 7224 cth case DKIOCSVTOC: 1344 7563 Prasad case DKIOCSEXTVTOC: 1345 7224 cth case DKIOCSETEFI: 1346 7224 cth i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl), 1347 7224 cth i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl))); 1348 7224 cth } 1349 7224 cth } 1350 786 lclee return (err); 1351 786 lclee } 1352 786 lclee 1353 786 lclee dev_t 1354 3525 shidokht cmlb_make_device(struct cmlb_lun *cl) 1355 3525 shidokht { 1356 8459 Jerry return (makedevice(ddi_driver_major(CMLB_DEVINFO(cl)), 1357 3525 shidokht ddi_get_instance(CMLB_DEVINFO(cl)) << CMLBUNIT_SHIFT)); 1358 786 lclee } 1359 786 lclee 1360 786 lclee /* 1361 786 lclee * Function: cmlb_check_update_blockcount 1362 786 lclee * 1363 786 lclee * Description: If current capacity value is invalid, obtains the 1364 786 lclee * current capacity from target driver. 1365 786 lclee * 1366 786 lclee * Return Code: 0 success 1367 786 lclee * EIO failure 1368 786 lclee */ 1369 786 lclee static int 1370 3525 shidokht cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie) 1371 786 lclee { 1372 786 lclee int status; 1373 786 lclee diskaddr_t capacity; 1374 3525 shidokht uint32_t lbasize; 1375 3525 shidokht 1376 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1377 3525 shidokht 1378 8863 Edward if (cl->cl_f_geometry_is_valid) 1379 786 lclee return (0); 1380 8863 Edward 1381 8863 Edward mutex_exit(CMLB_MUTEX(cl)); 1382 8863 Edward status = DK_TG_GETCAP(cl, &capacity, tg_cookie); 1383 8863 Edward if (status != 0) { 1384 8863 Edward mutex_enter(CMLB_MUTEX(cl)); 1385 8863 Edward return (EIO); 1386 8863 Edward } 1387 8863 Edward 1388 8863 Edward status = DK_TG_GETBLOCKSIZE(cl, &lbasize, tg_cookie); 1389 8863 Edward mutex_enter(CMLB_MUTEX(cl)); 1390 8863 Edward if (status != 0) 1391 8863 Edward return (EIO); 1392 8863 Edward 1393 8863 Edward if ((capacity != 0) && (lbasize != 0)) { 1394 8863 Edward cl->cl_blockcount = capacity; 1395 8863 Edward cl->cl_tgt_blocksize = lbasize; 1396 9889 Larry if (!cl->cl_is_removable) { 1397 9889 Larry cl->cl_sys_blocksize = lbasize; 1398 9889 Larry } 1399 8863 Edward return (0); 1400 8863 Edward } else { 1401 8863 Edward return (EIO); 1402 8863 Edward } 1403 786 lclee } 1404 786 lclee 1405 6318 edp static int 1406 6318 edp cmlb_create_minor(dev_info_t *dip, char *name, int spec_type, 1407 6318 edp minor_t minor_num, char *node_type, int flag, boolean_t internal) 1408 6318 edp { 1409 8863 Edward ASSERT(VALID_BOOLEAN(internal)); 1410 8863 Edward 1411 6318 edp if (internal) 1412 6318 edp return (ddi_create_internal_pathname(dip, 1413 6318 edp name, spec_type, minor_num)); 1414 6318 edp else 1415 6318 edp return (ddi_create_minor_node(dip, 1416 6318 edp name, spec_type, minor_num, node_type, flag)); 1417 6318 edp } 1418 6318 edp 1419 786 lclee /* 1420 786 lclee * Function: cmlb_create_minor_nodes 1421 786 lclee * 1422 786 lclee * Description: Create or adjust the minor device nodes for the instance. 1423 786 lclee * Minor nodes are created based on default label type, 1424 786 lclee * current label type and last label type we created 1425 786 lclee * minor nodes based on. 1426 786 lclee * 1427 786 lclee * 1428 3525 shidokht * Arguments: cl - driver soft state (unit) structure 1429 786 lclee * 1430 786 lclee * Return Code: 0 success 1431 786 lclee * ENXIO failure. 1432 786 lclee * 1433 786 lclee * Context: Kernel thread context 1434 786 lclee */ 1435 786 lclee static int 1436 3525 shidokht cmlb_create_minor_nodes(struct cmlb_lun *cl) 1437 786 lclee { 1438 786 lclee struct driver_minor_data *dmdp; 1439 786 lclee int instance; 1440 786 lclee char name[48]; 1441 786 lclee cmlb_label_t newlabeltype; 1442 6318 edp boolean_t internal; 1443 6318 edp 1444 6318 edp ASSERT(cl != NULL); 1445 6318 edp ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1446 6318 edp 1447 8863 Edward internal = VOID2BOOLEAN( 1448 8863 Edward (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 1449 786 lclee 1450 786 lclee /* check the most common case */ 1451 3525 shidokht if (cl->cl_cur_labeltype != CMLB_LABEL_UNDEF && 1452 3525 shidokht cl->cl_last_labeltype == cl->cl_cur_labeltype) { 1453 786 lclee /* do nothing */ 1454 786 lclee return (0); 1455 786 lclee } 1456 786 lclee 1457 3525 shidokht if (cl->cl_def_labeltype == CMLB_LABEL_UNDEF) { 1458 786 lclee /* we should never get here */ 1459 786 lclee return (ENXIO); 1460 786 lclee } 1461 786 lclee 1462 3525 shidokht if (cl->cl_last_labeltype == CMLB_LABEL_UNDEF) { 1463 786 lclee /* first time during attach */ 1464 3525 shidokht newlabeltype = cl->cl_def_labeltype; 1465 3525 shidokht 1466 3525 shidokht instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1467 786 lclee 1468 786 lclee /* Create all the minor nodes for this target. */ 1469 786 lclee dmdp = (newlabeltype == CMLB_LABEL_EFI) ? dk_minor_data_efi : 1470 786 lclee dk_minor_data; 1471 786 lclee while (dmdp->name != NULL) { 1472 786 lclee 1473 786 lclee (void) sprintf(name, "%s", dmdp->name); 1474 786 lclee 1475 6318 edp if (cmlb_create_minor(CMLB_DEVINFO(cl), name, 1476 786 lclee dmdp->type, 1477 786 lclee (instance << CMLBUNIT_SHIFT) | dmdp->minor, 1478 6318 edp cl->cl_node_type, NULL, internal) == DDI_FAILURE) { 1479 786 lclee /* 1480 786 lclee * Clean up any nodes that may have been 1481 786 lclee * created, in case this fails in the middle 1482 786 lclee * of the loop. 1483 786 lclee */ 1484 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 1485 786 lclee return (ENXIO); 1486 786 lclee } 1487 786 lclee dmdp++; 1488 786 lclee } 1489 3525 shidokht cl->cl_last_labeltype = newlabeltype; 1490 786 lclee return (0); 1491 786 lclee } 1492 786 lclee 1493 786 lclee /* Not first time */ 1494 3525 shidokht if (cl->cl_cur_labeltype == CMLB_LABEL_UNDEF) { 1495 3525 shidokht if (cl->cl_last_labeltype != cl->cl_def_labeltype) { 1496 786 lclee /* close time, revert to default. */ 1497 3525 shidokht newlabeltype = cl->cl_def_labeltype; 1498 786 lclee } else { 1499 786 lclee /* 1500 786 lclee * do nothing since the type for which we last created 1501 786 lclee * nodes matches the default 1502 786 lclee */ 1503 786 lclee return (0); 1504 786 lclee } 1505 786 lclee } else { 1506 3525 shidokht if (cl->cl_cur_labeltype != cl->cl_last_labeltype) { 1507 786 lclee /* We are not closing, use current label type */ 1508 3525 shidokht newlabeltype = cl->cl_cur_labeltype; 1509 786 lclee } else { 1510 786 lclee /* 1511 786 lclee * do nothing since the type for which we last created 1512 786 lclee * nodes matches the current label type 1513 786 lclee */ 1514 786 lclee return (0); 1515 786 lclee } 1516 786 lclee } 1517 786 lclee 1518 3525 shidokht instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1519 786 lclee 1520 786 lclee /* 1521 786 lclee * Currently we only fix up the s7 node when we are switching 1522 786 lclee * label types from or to EFI. This is consistent with 1523 786 lclee * current behavior of sd. 1524 786 lclee */ 1525 786 lclee if (newlabeltype == CMLB_LABEL_EFI && 1526 3525 shidokht cl->cl_last_labeltype != CMLB_LABEL_EFI) { 1527 786 lclee /* from vtoc to EFI */ 1528 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 1529 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 1530 6318 edp (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 1531 786 lclee S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1532 6318 edp cl->cl_node_type, NULL, internal); 1533 6318 edp (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 1534 786 lclee S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1535 6318 edp cl->cl_node_type, NULL, internal); 1536 786 lclee } else { 1537 786 lclee /* from efi to vtoc */ 1538 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 1539 3525 shidokht ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 1540 6318 edp (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 1541 786 lclee S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1542 6318 edp cl->cl_node_type, NULL, internal); 1543 6318 edp (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 1544 786 lclee S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1545 6318 edp cl->cl_node_type, NULL, internal); 1546 3525 shidokht } 1547 3525 shidokht 1548 3525 shidokht cl->cl_last_labeltype = newlabeltype; 1549 786 lclee return (0); 1550 786 lclee } 1551 786 lclee 1552 786 lclee /* 1553 786 lclee * Function: cmlb_validate_geometry 1554 786 lclee * 1555 786 lclee * Description: Read the label from the disk (if present). Update the unit's 1556 786 lclee * geometry and vtoc information from the data in the label. 1557 786 lclee * Verify that the label is valid. 1558 786 lclee * 1559 3525 shidokht * Arguments: 1560 3525 shidokht * cl driver soft state (unit) structure 1561 3525 shidokht * 1562 3525 shidokht * forcerevalid force revalidation even if we are already valid. 1563 3525 shidokht * flags operation flags from target driver. Used for verbosity 1564 3525 shidokht * control at this time. 1565 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 1566 3525 shidokht * driver when we call back to it through tg_ops. 1567 786 lclee * 1568 786 lclee * Return Code: 0 - Successful completion 1569 3525 shidokht * EINVAL - Invalid value in cl->cl_tgt_blocksize or 1570 3525 shidokht * cl->cl_blockcount; or label on disk is corrupted 1571 786 lclee * or unreadable. 1572 786 lclee * EACCES - Reservation conflict at the device. 1573 786 lclee * ENOMEM - Resource allocation error 1574 786 lclee * ENOTSUP - geometry not applicable 1575 786 lclee * 1576 786 lclee * Context: Kernel thread only (can sleep). 1577 786 lclee */ 1578 786 lclee static int 1579 8863 Edward cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid, int flags, 1580 3525 shidokht void *tg_cookie) 1581 786 lclee { 1582 786 lclee int label_error = 0; 1583 786 lclee diskaddr_t capacity; 1584 786 lclee int count; 1585 3525 shidokht 1586 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1587 8863 Edward ASSERT(VALID_BOOLEAN(forcerevalid)); 1588 8863 Edward 1589 8863 Edward if ((cl->cl_f_geometry_is_valid) && (!forcerevalid)) { 1590 3525 shidokht if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 1591 786 lclee return (ENOTSUP); 1592 786 lclee return (0); 1593 786 lclee } 1594 786 lclee 1595 3525 shidokht if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 1596 3525 shidokht return (EIO); 1597 3525 shidokht 1598 3525 shidokht capacity = cl->cl_blockcount; 1599 786 lclee 1600 786 lclee #if defined(_SUNOS_VTOC_16) 1601 786 lclee /* 1602 786 lclee * Set up the "whole disk" fdisk partition; this should always 1603 786 lclee * exist, regardless of whether the disk contains an fdisk table 1604 786 lclee * or vtoc. 1605 786 lclee */ 1606 3525 shidokht cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 1607 7563 Prasad cl->cl_offset[P0_RAW_DISK] = 0; 1608 7563 Prasad /* 1609 7563 Prasad * note if capacity > int32_max(1TB) we are in 64bit environment 1610 7563 Prasad * so no truncation happens 1611 786 lclee */ 1612 3525 shidokht cl->cl_map[P0_RAW_DISK].dkl_nblk = capacity; 1613 786 lclee #endif 1614 786 lclee /* 1615 786 lclee * Refresh the logical and physical geometry caches. 1616 786 lclee * (data from MODE SENSE format/rigid disk geometry pages, 1617 786 lclee * and scsi_ifgetcap("geometry"). 1618 786 lclee */ 1619 3525 shidokht cmlb_resync_geom_caches(cl, capacity, tg_cookie); 1620 3525 shidokht 1621 7563 Prasad cl->cl_label_from_media = CMLB_LABEL_UNDEF; 1622 3525 shidokht label_error = cmlb_use_efi(cl, capacity, flags, tg_cookie); 1623 786 lclee if (label_error == 0) { 1624 786 lclee 1625 786 lclee /* found a valid EFI label */ 1626 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, 1627 786 lclee "cmlb_validate_geometry: found EFI label\n"); 1628 786 lclee /* 1629 786 lclee * solaris_size and geometry_is_valid are set in 1630 786 lclee * cmlb_use_efi 1631 786 lclee */ 1632 786 lclee return (ENOTSUP); 1633 786 lclee } 1634 786 lclee 1635 786 lclee /* NO EFI label found */ 1636 786 lclee 1637 7563 Prasad if (capacity > CMLB_EXTVTOC_LIMIT) { 1638 786 lclee if (label_error == ESRCH) { 1639 786 lclee /* 1640 7563 Prasad * they've configured a LUN over 2TB, but used 1641 786 lclee * format.dat to restrict format's view of the 1642 7563 Prasad * capacity to be under 2TB in some earlier Solaris 1643 7563 Prasad * release. 1644 7563 Prasad */ 1645 7563 Prasad /* i.e > 2TB with a VTOC < 2TB */ 1646 7563 Prasad if (!(flags & CMLB_SILENT) && 1647 7563 Prasad (cl->cl_msglog_flag & CMLB_ALLOW_2TB_WARN)) { 1648 7563 Prasad 1649 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 1650 7563 Prasad CE_NOTE, "!Disk (%s%d) is limited to 2 TB " 1651 7563 Prasad "due to VTOC label. To use the full " 1652 7563 Prasad "capacity of the disk, use format(1M) to " 1653 7563 Prasad "relabel the disk with EFI/GPT label.\n", 1654 7563 Prasad CMLB_LABEL(cl), 1655 7563 Prasad ddi_get_instance(CMLB_DEVINFO(cl))); 1656 7563 Prasad 1657 7563 Prasad cl->cl_msglog_flag &= ~CMLB_ALLOW_2TB_WARN; 1658 7563 Prasad } 1659 7563 Prasad } else { 1660 3525 shidokht return (ENOTSUP); 1661 786 lclee } 1662 786 lclee } 1663 786 lclee 1664 786 lclee label_error = 0; 1665 786 lclee 1666 786 lclee /* 1667 786 lclee * at this point it is either labeled with a VTOC or it is 1668 3525 shidokht * under 1TB (<= 1TB actually for off-by-1) 1669 3525 shidokht */ 1670 3525 shidokht 1671 3525 shidokht /* 1672 3525 shidokht * Only DIRECT ACCESS devices will have Scl labels. 1673 3525 shidokht * CD's supposedly have a Scl label, too 1674 3525 shidokht */ 1675 3525 shidokht if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 1676 786 lclee struct dk_label *dkl; 1677 786 lclee offset_t label_addr; 1678 786 lclee int rval; 1679 786 lclee size_t buffer_size; 1680 786 lclee 1681 786 lclee /* 1682 3525 shidokht * Note: This will set up cl->cl_solaris_size and 1683 3525 shidokht * cl->cl_solaris_offset. 1684 3525 shidokht */ 1685 3525 shidokht rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 1686 3525 shidokht if ((rval != 0) && !ISCD(cl)) { 1687 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1688 786 lclee return (rval); 1689 786 lclee } 1690 786 lclee 1691 3525 shidokht if (cl->cl_solaris_size <= DK_LABEL_LOC) { 1692 786 lclee /* 1693 786 lclee * Found fdisk table but no Solaris partition entry, 1694 786 lclee * so don't call cmlb_uselabel() and don't create 1695 786 lclee * a default label. 1696 786 lclee */ 1697 786 lclee label_error = 0; 1698 8863 Edward cl->cl_f_geometry_is_valid = B_TRUE; 1699 786 lclee goto no_solaris_partition; 1700 786 lclee } 1701 786 lclee 1702 3525 shidokht label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC); 1703 786 lclee 1704 9889 Larry buffer_size = cl->cl_sys_blocksize; 1705 786 lclee 1706 3525 shidokht cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: " 1707 786 lclee "label_addr: 0x%x allocation size: 0x%x\n", 1708 786 lclee label_addr, buffer_size); 1709 786 lclee 1710 786 lclee if ((dkl = kmem_zalloc(buffer_size, KM_NOSLEEP)) == NULL) 1711 786 lclee return (ENOMEM); 1712 786 lclee 1713 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1714 3525 shidokht rval = DK_TG_READ(cl, dkl, label_addr, buffer_size, tg_cookie); 1715 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 1716 786 lclee 1717 786 lclee switch (rval) { 1718 786 lclee case 0: 1719 786 lclee /* 1720 786 lclee * cmlb_uselabel will establish that the geometry 1721 786 lclee * is valid. 1722 786 lclee */ 1723 3525 shidokht if (cmlb_uselabel(cl, 1724 3525 shidokht (struct dk_label *)(uintptr_t)dkl, flags) != 1725 786 lclee CMLB_LABEL_IS_VALID) { 1726 786 lclee label_error = EINVAL; 1727 786 lclee } else 1728 7563 Prasad cl->cl_label_from_media = CMLB_LABEL_VTOC; 1729 786 lclee break; 1730 786 lclee case EACCES: 1731 786 lclee label_error = EACCES; 1732 786 lclee break; 1733 786 lclee default: 1734 786 lclee label_error = EINVAL; 1735 786 lclee break; 1736 786 lclee } 1737 786 lclee 1738 786 lclee kmem_free(dkl, buffer_size); 1739 786 lclee } 1740 786 lclee 1741 786 lclee /* 1742 786 lclee * If a valid label was not found, AND if no reservation conflict 1743 786 lclee * was detected, then go ahead and create a default label (4069506). 1744 786 lclee * 1745 786 lclee * Note: currently, for VTOC_8 devices, the default label is created 1746 3525 shidokht * for removables and hotpluggables only. For VTOC_16 devices, the 1747 3525 shidokht * default label will be created for all devices. 1748 786 lclee * (see cmlb_build_default_label) 1749 786 lclee */ 1750 786 lclee #if defined(_SUNOS_VTOC_8) 1751 3525 shidokht if ((ISREMOVABLE(cl) || ISHOTPLUGGABLE(cl)) && 1752 3525 shidokht (label_error != EACCES)) { 1753 786 lclee #elif defined(_SUNOS_VTOC_16) 1754 786 lclee if (label_error != EACCES) { 1755 786 lclee #endif 1756 8863 Edward if (!cl->cl_f_geometry_is_valid) { 1757 3525 shidokht cmlb_build_default_label(cl, tg_cookie); 1758 786 lclee } 1759 786 lclee label_error = 0; 1760 786 lclee } 1761 786 lclee 1762 786 lclee no_solaris_partition: 1763 786 lclee 1764 786 lclee #if defined(_SUNOS_VTOC_16) 1765 786 lclee /* 1766 786 lclee * If we have valid geometry, set up the remaining fdisk partitions. 1767 786 lclee * Note that dkl_cylno is not used for the fdisk map entries, so 1768 786 lclee * we set it to an entirely bogus value. 1769 786 lclee */ 1770 10021 Sheshadri for (count = 0; count < FDISK_PARTS; count++) { 1771 7563 Prasad cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT16_MAX; 1772 3525 shidokht cl->cl_map[FDISK_P1 + count].dkl_nblk = 1773 3525 shidokht cl->cl_fmap[count].fmap_nblk; 1774 3525 shidokht 1775 3525 shidokht cl->cl_offset[FDISK_P1 + count] = 1776 3525 shidokht cl->cl_fmap[count].fmap_start; 1777 786 lclee } 1778 786 lclee #endif 1779 786 lclee 1780 786 lclee for (count = 0; count < NDKMAP; count++) { 1781 786 lclee #if defined(_SUNOS_VTOC_8) 1782 3525 shidokht struct dk_map *lp = &cl->cl_map[count]; 1783 3525 shidokht cl->cl_offset[count] = 1784 3525 shidokht cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 1785 3525 shidokht #elif defined(_SUNOS_VTOC_16) 1786 3525 shidokht struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 1787 3525 shidokht 1788 3525 shidokht cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 1789 786 lclee #else 1790 786 lclee #error "No VTOC format defined." 1791 786 lclee #endif 1792 786 lclee } 1793 786 lclee 1794 786 lclee return (label_error); 1795 786 lclee } 1796 786 lclee 1797 786 lclee #if defined(_SUNOS_VTOC_16) 1798 786 lclee /* 1799 786 lclee * Function: cmlb_convert_geometry 1800 786 lclee * 1801 786 lclee * Description: Convert physical geometry into a dk_geom structure. In 1802 786 lclee * other words, make sure we don't wrap 16-bit values. 1803 786 lclee * e.g. converting from geom_cache to dk_geom 1804 786 lclee * 1805 786 lclee * Context: Kernel thread only 1806 786 lclee */ 1807 786 lclee static void 1808 10320 Larry cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity, 1809 10320 Larry struct dk_geom *cl_g, void *tg_cookie) 1810 10320 Larry { 1811 10320 Larry 1812 10320 Larry ASSERT(cl != NULL); 1813 10320 Larry ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1814 786 lclee 1815 786 lclee /* Unlabeled SCSI floppy device */ 1816 786 lclee if (capacity <= 0x1000) { 1817 3525 shidokht cl_g->dkg_nhead = 2; 1818 3525 shidokht cl_g->dkg_ncyl = 80; 1819 3525 shidokht cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl); 1820 786 lclee return; 1821 786 lclee } 1822 786 lclee 1823 786 lclee /* 1824 7563 Prasad * For all devices we calculate cylinders using the heads and sectors 1825 7563 Prasad * we assign based on capacity of the device. The algorithm is 1826 7563 Prasad * designed to be compatible with the way other operating systems 1827 7563 Prasad * lay out fdisk tables for X86 and to insure that the cylinders never 1828 7563 Prasad * exceed 65535 to prevent problems with X86 ioctls that report 1829 7563 Prasad * geometry. 1830 7563 Prasad * For some smaller disk sizes we report geometry that matches those 1831 7563 Prasad * used by X86 BIOS usage. For larger disks, we use SPT that are 1832 7563 Prasad * multiples of 63, since other OSes that are not limited to 16-bits 1833 7563 Prasad * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT. 1834 7563 Prasad * 1835 7563 Prasad * The following table (in order) illustrates some end result 1836 7563 Prasad * calculations: 1837 7563 Prasad * 1838 7563 Prasad * Maximum number of blocks nhead nsect 1839 7563 Prasad * 1840 7563 Prasad * 2097152 (1GB) 64 32 1841 7563 Prasad * 16777216 (8GB) 128 32 1842 7563 Prasad * 1052819775 (502.02GB) 255 63 1843 7563 Prasad * 2105639550 (0.98TB) 255 126 1844 7563 Prasad * 3158459325 (1.47TB) 255 189 1845 7563 Prasad * 4211279100 (1.96TB) 255 252 1846 7563 Prasad * 5264098875 (2.45TB) 255 315 1847 7563 Prasad * ... 1848 10320 Larry * 1849 10320 Larry * For Solid State Drive(SSD), it uses 4K page size inside and may be 1850 10320 Larry * double with every new generation. If the I/O is not aligned with 1851 10320 Larry * page size on SSDs, SSDs perform a lot slower. 1852 10320 Larry * By default, Solaris partition starts from cylinder 1. It will be 1853 10320 Larry * misaligned even with 4K if using heads(255) and SPT(63). To 1854 10320 Larry * workaround the problem, if the device is SSD, we use heads(224) and 1855 10320 Larry * SPT multiple of 56. Thus the default Solaris partition starts from 1856 10320 Larry * a position that aligns with 128K on a 512 bytes sector size SSD. 1857 7563 Prasad */ 1858 7563 Prasad 1859 7563 Prasad if (capacity <= 0x200000) { 1860 7563 Prasad cl_g->dkg_nhead = 64; 1861 7563 Prasad cl_g->dkg_nsect = 32; 1862 7563 Prasad } else if (capacity <= 0x01000000) { 1863 7563 Prasad cl_g->dkg_nhead = 128; 1864 7563 Prasad cl_g->dkg_nsect = 32; 1865 7563 Prasad } else { 1866 10320 Larry tg_attribute_t tgattribute; 1867 10320 Larry int is_solid_state; 1868 10320 Larry unsigned short nhead; 1869 10320 Larry unsigned short nsect; 1870 10320 Larry 1871 10320 Larry bzero(&tgattribute, sizeof (tg_attribute_t)); 1872 10320 Larry 1873 10320 Larry mutex_exit(CMLB_MUTEX(cl)); 1874 10320 Larry is_solid_state = 1875 10320 Larry (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ? 1876 10320 Larry tgattribute.media_is_solid_state : FALSE; 1877 10320 Larry mutex_enter(CMLB_MUTEX(cl)); 1878 10320 Larry 1879 10320 Larry if (is_solid_state) { 1880 10320 Larry nhead = 224; 1881 10320 Larry nsect = 56; 1882 10320 Larry } else { 1883 10320 Larry nhead = 255; 1884 10320 Larry nsect = 63; 1885 10320 Larry } 1886 10320 Larry 1887 10320 Larry cl_g->dkg_nhead = nhead; 1888 10320 Larry 1889 10320 Larry /* make nsect be smallest multiple of nhead */ 1890 7563 Prasad cl_g->dkg_nsect = ((capacity + 1891 10320 Larry (UINT16_MAX * nhead * nsect) - 1) / 1892 10320 Larry (UINT16_MAX * nhead * nsect)) * nsect; 1893 7563 Prasad 1894 7563 Prasad if (cl_g->dkg_nsect == 0) 1895 10320 Larry cl_g->dkg_nsect = (UINT16_MAX / nsect) * nsect; 1896 7563 Prasad } 1897 7563 Prasad 1898 786 lclee } 1899 786 lclee #endif 1900 786 lclee 1901 786 lclee /* 1902 786 lclee * Function: cmlb_resync_geom_caches 1903 786 lclee * 1904 786 lclee * Description: (Re)initialize both geometry caches: the virtual geometry 1905 786 lclee * information is extracted from the HBA (the "geometry" 1906 786 lclee * capability), and the physical geometry cache data is 1907 786 lclee * generated by issuing MODE SENSE commands. 1908 786 lclee * 1909 3525 shidokht * Arguments: 1910 3525 shidokht * cl driver soft state (unit) structure 1911 3525 shidokht * capacity disk capacity in #blocks 1912 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 1913 3525 shidokht * driver when we call back to it through tg_ops. 1914 786 lclee * 1915 786 lclee * Context: Kernel thread only (can sleep). 1916 786 lclee */ 1917 786 lclee static void 1918 3525 shidokht cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 1919 3525 shidokht void *tg_cookie) 1920 786 lclee { 1921 786 lclee struct cmlb_geom pgeom; 1922 786 lclee struct cmlb_geom lgeom; 1923 786 lclee struct cmlb_geom *pgeomp = &pgeom; 1924 786 lclee unsigned short nhead; 1925 786 lclee unsigned short nsect; 1926 786 lclee int spc; 1927 786 lclee int ret; 1928 786 lclee 1929 3525 shidokht ASSERT(cl != NULL); 1930 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1931 786 lclee 1932 786 lclee /* 1933 786 lclee * Ask the controller for its logical geometry. 1934 786 lclee * Note: if the HBA does not support scsi_ifgetcap("geometry"), 1935 786 lclee * then the lgeom cache will be invalid. 1936 786 lclee */ 1937 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1938 786 lclee bzero(&lgeom, sizeof (struct cmlb_geom)); 1939 3525 shidokht ret = DK_TG_GETVIRTGEOM(cl, &lgeom, tg_cookie); 1940 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 1941 3525 shidokht 1942 3525 shidokht bcopy(&lgeom, &cl->cl_lgeom, sizeof (cl->cl_lgeom)); 1943 786 lclee 1944 786 lclee /* 1945 786 lclee * Initialize the pgeom cache from lgeom, so that if MODE SENSE 1946 786 lclee * doesn't work, DKIOCG_PHYSGEOM can return reasonable values. 1947 786 lclee */ 1948 3525 shidokht if (ret != 0 || cl->cl_lgeom.g_nsect == 0 || 1949 3525 shidokht cl->cl_lgeom.g_nhead == 0) { 1950 786 lclee /* 1951 786 lclee * Note: Perhaps this needs to be more adaptive? The rationale 1952 786 lclee * is that, if there's no HBA geometry from the HBA driver, any 1953 786 lclee * guess is good, since this is the physical geometry. If MODE 1954 786 lclee * SENSE fails this gives a max cylinder size for non-LBA access 1955 786 lclee */ 1956 786 lclee nhead = 255; 1957 786 lclee nsect = 63; 1958 786 lclee } else { 1959 3525 shidokht nhead = cl->cl_lgeom.g_nhead; 1960 3525 shidokht nsect = cl->cl_lgeom.g_nsect; 1961 3525 shidokht } 1962 3525 shidokht 1963 3525 shidokht if (ISCD(cl)) { 1964 786 lclee pgeomp->g_nhead = 1; 1965 786 lclee pgeomp->g_nsect = nsect * nhead; 1966 786 lclee } else { 1967 786 lclee pgeomp->g_nhead = nhead; 1968 786 lclee pgeomp->g_nsect = nsect; 1969 786 lclee } 1970 786 lclee 1971 786 lclee spc = pgeomp->g_nhead * pgeomp->g_nsect; 1972 786 lclee pgeomp->g_capacity = capacity; 1973 9811 Sheshadri if (spc == 0) 1974 9811 Sheshadri pgeomp->g_ncyl = 0; 1975 9811 Sheshadri else 1976 9811 Sheshadri pgeomp->g_ncyl = pgeomp->g_capacity / spc; 1977 786 lclee pgeomp->g_acyl = 0; 1978 786 lclee 1979 786 lclee /* 1980 786 lclee * Retrieve fresh geometry data from the hardware, stash it 1981 786 lclee * here temporarily before we rebuild the incore label. 1982 786 lclee * 1983 786 lclee * We want to use the MODE SENSE commands to derive the 1984 786 lclee * physical geometry of the device, but if either command 1985 786 lclee * fails, the logical geometry is used as the fallback for 1986 786 lclee * disk label geometry. 1987 786 lclee */ 1988 786 lclee 1989 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 1990 3525 shidokht (void) DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 1991 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 1992 786 lclee 1993 786 lclee /* 1994 786 lclee * Now update the real copy while holding the mutex. This 1995 786 lclee * way the global copy is never in an inconsistent state. 1996 786 lclee */ 1997 3525 shidokht bcopy(pgeomp, &cl->cl_pgeom, sizeof (cl->cl_pgeom)); 1998 3525 shidokht 1999 3525 shidokht cmlb_dbg(CMLB_INFO, cl, "cmlb_resync_geom_caches: " 2000 786 lclee "(cached from lgeom)\n"); 2001 3525 shidokht cmlb_dbg(CMLB_INFO, cl, 2002 786 lclee " ncyl: %ld; acyl: %d; nhead: %d; nsect: %d\n", 2003 3525 shidokht cl->cl_pgeom.g_ncyl, cl->cl_pgeom.g_acyl, 2004 3525 shidokht cl->cl_pgeom.g_nhead, cl->cl_pgeom.g_nsect); 2005 3525 shidokht cmlb_dbg(CMLB_INFO, cl, " lbasize: %d; capacity: %ld; " 2006 3525 shidokht "intrlv: %d; rpm: %d\n", cl->cl_pgeom.g_secsize, 2007 3525 shidokht cl->cl_pgeom.g_capacity, cl->cl_pgeom.g_intrlv, 2008 3525 shidokht cl->cl_pgeom.g_rpm); 2009 786 lclee } 2010 786 lclee 2011 786 lclee 2012 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2013 10021 Sheshadri /* 2014 10021 Sheshadri * Function: cmlb_update_ext_minor_nodes 2015 10021 Sheshadri * 2016 10021 Sheshadri * Description: Routine to add/remove extended partition device nodes 2017 10021 Sheshadri * 2018 10021 Sheshadri * Arguments: 2019 10021 Sheshadri * cl driver soft state (unit) structure 2020 10021 Sheshadri * num_parts Number of logical drives found on the LUN 2021 10021 Sheshadri * 2022 10021 Sheshadri * Should be called with the mutex held 2023 10021 Sheshadri * 2024 10021 Sheshadri * Return Code: 0 for success 2025 10021 Sheshadri * 2026 10021 Sheshadri * Context: User and Kernel thread 2027 10021 Sheshadri * 2028 10021 Sheshadri */ 2029 10021 Sheshadri static int 2030 10021 Sheshadri cmlb_update_ext_minor_nodes(struct cmlb_lun *cl, int num_parts) 2031 10021 Sheshadri { 2032 10021 Sheshadri int i, count; 2033 10021 Sheshadri char name[48]; 2034 10021 Sheshadri int instance; 2035 10021 Sheshadri struct driver_minor_data *demdp, *demdpr; 2036 10021 Sheshadri char *devnm; 2037 10021 Sheshadri dev_info_t *pdip; 2038 10021 Sheshadri boolean_t internal; 2039 10021 Sheshadri 2040 10021 Sheshadri ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2041 10021 Sheshadri ASSERT(cl->cl_update_ext_minor_nodes == 1); 2042 10021 Sheshadri 2043 10021 Sheshadri internal = VOID2BOOLEAN( 2044 10021 Sheshadri (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 2045 10021 Sheshadri instance = ddi_get_instance(CMLB_DEVINFO(cl)); 2046 10021 Sheshadri demdp = dk_ext_minor_data; 2047 10021 Sheshadri demdpr = &dk_ext_minor_data[MAX_EXT_PARTS]; 2048 10021 Sheshadri 2049 10021 Sheshadri 2050 10021 Sheshadri if (cl->cl_logical_drive_count) { 2051 10021 Sheshadri for (i = 0; i < cl->cl_logical_drive_count; i++) { 2052 10021 Sheshadri (void) sprintf(name, "%s", demdp->name); 2053 10021 Sheshadri ddi_remove_minor_node(CMLB_DEVINFO(cl), name); 2054 10021 Sheshadri (void) sprintf(name, "%s", demdpr->name); 2055 10021 Sheshadri ddi_remove_minor_node(CMLB_DEVINFO(cl), name); 2056 10021 Sheshadri demdp++; 2057 10021 Sheshadri demdpr++; 2058 10021 Sheshadri } 2059 10021 Sheshadri /* There are existing device nodes. Remove them */ 2060 10021 Sheshadri devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 2061 10021 Sheshadri (void) ddi_deviname(cl->cl_devi, devnm); 2062 10021 Sheshadri pdip = ddi_get_parent(cl->cl_devi); 2063 10021 Sheshadri (void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE); 2064 10021 Sheshadri kmem_free(devnm, MAXNAMELEN + 1); 2065 10021 Sheshadri } 2066 10021 Sheshadri 2067 10021 Sheshadri demdp = dk_ext_minor_data; 2068 10021 Sheshadri demdpr = &dk_ext_minor_data[MAX_EXT_PARTS]; 2069 10021 Sheshadri 2070 10021 Sheshadri for (i = 0; i < num_parts; i++) { 2071 10021 Sheshadri (void) sprintf(name, "%s", demdp->name); 2072 10021 Sheshadri if (cmlb_create_minor(CMLB_DEVINFO(cl), name, 2073 10021 Sheshadri demdp->type, 2074 10021 Sheshadri (instance << CMLBUNIT_SHIFT) | demdp->minor, 2075 10021 Sheshadri cl->cl_node_type, NULL, internal) == DDI_FAILURE) { 2076 10021 Sheshadri /* 2077 10021 Sheshadri * Clean up any nodes that may have been 2078 10021 Sheshadri * created, in case this fails in the middle 2079 10021 Sheshadri * of the loop. 2080 10021 Sheshadri */ 2081 10021 Sheshadri ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 2082 10021 Sheshadri cl->cl_logical_drive_count = 0; 2083 10021 Sheshadri return (ENXIO); 2084 10021 Sheshadri } 2085 10021 Sheshadri (void) sprintf(name, "%s", demdpr->name); 2086 10021 Sheshadri if (ddi_create_minor_node(CMLB_DEVINFO(cl), name, 2087 10021 Sheshadri demdpr->type, 2088 10021 Sheshadri (instance << CMLBUNIT_SHIFT) | demdpr->minor, 2089 10021 Sheshadri cl->cl_node_type, NULL) == DDI_FAILURE) { 2090 10021 Sheshadri /* 2091 10021 Sheshadri * Clean up any nodes that may have been 2092 10021 Sheshadri * created, in case this fails in the middle 2093 10021 Sheshadri * of the loop. 2094 10021 Sheshadri */ 2095 10021 Sheshadri ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 2096 10021 Sheshadri cl->cl_logical_drive_count = 0; 2097 10021 Sheshadri return (ENXIO); 2098 10021 Sheshadri } 2099 10021 Sheshadri demdp++; 2100 10021 Sheshadri demdpr++; 2101 10021 Sheshadri } 2102 10021 Sheshadri 2103 10021 Sheshadri /* Update the cl_map array for logical drives */ 2104 10021 Sheshadri for (count = 0; count < MAX_EXT_PARTS; count++) { 2105 10021 Sheshadri cl->cl_map[FDISK_P4 + 1 + count].dkl_cylno = UINT32_MAX; 2106 10021 Sheshadri cl->cl_map[FDISK_P4 + 1 + count].dkl_nblk = 2107 10021 Sheshadri cl->cl_fmap[FD_NUMPART + count].fmap_nblk; 2108 10021 Sheshadri cl->cl_offset[FDISK_P4 + 1 + count] = 2109 10021 Sheshadri cl->cl_fmap[FD_NUMPART + count].fmap_start; 2110 10021 Sheshadri } 2111 10021 Sheshadri 2112 10021 Sheshadri cl->cl_logical_drive_count = i; 2113 10021 Sheshadri cl->cl_update_ext_minor_nodes = 0; 2114 10021 Sheshadri return (0); 2115 10021 Sheshadri } 2116 10021 Sheshadri /* 2117 10021 Sheshadri * Function: cmlb_validate_ext_part 2118 10021 Sheshadri * 2119 10021 Sheshadri * Description: utility routine to validate an extended partition's 2120 10021 Sheshadri * metadata as found on disk 2121 10021 Sheshadri * 2122 10021 Sheshadri * Arguments: 2123 10021 Sheshadri * cl driver soft state (unit) structure 2124 10021 Sheshadri * part partition number of the extended partition 2125 10021 Sheshadri * epart partition number of the logical drive 2126 10021 Sheshadri * start absolute sector number of the start of the logical 2127 10021 Sheshadri * drive being validated 2128 10021 Sheshadri * size size of logical drive being validated 2129 10021 Sheshadri * 2130 10021 Sheshadri * Return Code: 0 for success 2131 10021 Sheshadri * 2132 10021 Sheshadri * Context: User and Kernel thread 2133 10021 Sheshadri * 2134 10021 Sheshadri * Algorithm : 2135 10021 Sheshadri * Error cases are : 2136 10021 Sheshadri * 1. If start block is lesser than or equal to the end block 2137 10021 Sheshadri * 2. If either start block or end block is beyond the bounadry 2138 10021 Sheshadri * of the extended partition. 2139 10021 Sheshadri * 3. start or end block overlap with existing partitions. 2140 10021 Sheshadri * To check this, first make sure that the start block doesnt 2141 10021 Sheshadri * overlap with existing partitions. Then, calculate the 2142 10021 Sheshadri * possible end block for the given start block that doesnt 2143 10021 Sheshadri * overlap with existing partitions. This can be calculated by 2144 10021 Sheshadri * first setting the possible end block to the end of the 2145 10021 Sheshadri * extended partition (optimistic) and then, checking if there 2146 10021 Sheshadri * is any other partition that lies after the start of the 2147 10021 Sheshadri * partition being validated. If so, set the possible end to 2148 10021 Sheshadri * one block less than the beginning of the next nearest partition 2149 10021 Sheshadri * If the actual end block is greater than the calculated end 2150 10021 Sheshadri * block, we have an overlap. 2151 10021 Sheshadri * 2152 10021 Sheshadri */ 2153 10021 Sheshadri static int 2154 10021 Sheshadri cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart, uint32_t start, 2155 10021 Sheshadri uint32_t size) 2156 10021 Sheshadri { 2157 10021 Sheshadri int i; 2158 10021 Sheshadri uint32_t end = start + size - 1; 2159 10021 Sheshadri uint32_t ext_start = cl->cl_fmap[part].fmap_start; 2160 10021 Sheshadri uint32_t ext_end = ext_start + cl->cl_fmap[part].fmap_nblk - 1; 2161 10021 Sheshadri uint32_t ts, te; 2162 10021 Sheshadri uint32_t poss_end = ext_end; 2163 10021 Sheshadri 2164 10021 Sheshadri if (end <= start) { 2165 10021 Sheshadri return (1); 2166 10021 Sheshadri } 2167 10021 Sheshadri 2168 10021 Sheshadri /* 2169 10021 Sheshadri * Check if the logical drive boundaries are within that of the 2170 10021 Sheshadri * extended partition. 2171 10021 Sheshadri */ 2172 10021 Sheshadri if (start <= ext_start || start > ext_end || end <= ext_start || 2173 10021 Sheshadri end > ext_end) { 2174 10021 Sheshadri return (1); 2175 10021 Sheshadri } 2176 10021 Sheshadri 2177 10021 Sheshadri /* 2178 10021 Sheshadri * epart will be equal to FD_NUMPART if it is the first logical drive. 2179 10021 Sheshadri * There is no need to check for overlaps with other logical drives, 2180 10021 Sheshadri * since it is the only logical drive that we have come across so far. 2181 10021 Sheshadri */ 2182 10021 Sheshadri if (epart == FD_NUMPART) { 2183 10021 Sheshadri return (0); 2184 10021 Sheshadri } 2185 10021 Sheshadri 2186 10021 Sheshadri /* Check for overlaps with existing logical drives */ 2187 10021 Sheshadri i = FD_NUMPART; 2188 10021 Sheshadri ts = cl->cl_fmap[FD_NUMPART].fmap_start; 2189 10021 Sheshadri te = ts + cl->cl_fmap[FD_NUMPART].fmap_nblk - 1; 2190 10021 Sheshadri 2191 10021 Sheshadri while ((i < epart) && ts && te) { 2192 10021 Sheshadri if (start >= ts && start <= te) { 2193 10021 Sheshadri return (1); 2194 10021 Sheshadri } 2195 10021 Sheshadri 2196 10021 Sheshadri if ((ts < poss_end) && (ts > start)) { 2197 10021 Sheshadri poss_end = ts - 1; 2198 10021 Sheshadri } 2199 10021 Sheshadri 2200 10021 Sheshadri i++; 2201 10021 Sheshadri ts = cl->cl_fmap[i].fmap_start; 2202 10021 Sheshadri te = ts + cl->cl_fmap[i].fmap_nblk - 1; 2203 10021 Sheshadri } 2204 10021 Sheshadri 2205 10021 Sheshadri if (end > poss_end) { 2206 10021 Sheshadri return (1); 2207 10021 Sheshadri } 2208 10021 Sheshadri 2209 10021 Sheshadri return (0); 2210 10021 Sheshadri } 2211 10021 Sheshadri 2212 10021 Sheshadri 2213 10021 Sheshadri /* 2214 10021 Sheshadri * Function: cmlb_is_linux_swap 2215 10021 Sheshadri * 2216 10021 Sheshadri * Description: utility routine to verify if a partition is a linux swap 2217 10021 Sheshadri * partition or not. 2218 10021 Sheshadri * 2219 10021 Sheshadri * Arguments: 2220 10021 Sheshadri * cl driver soft state (unit) structure 2221 10021 Sheshadri * part_start absolute sector number of the start of the partition 2222 10021 Sheshadri * being verified 2223 10021 Sheshadri * tg_cookie cookie from target driver to be passed back to target 2224 10021 Sheshadri * driver when we call back to it through tg_ops. 2225 10021 Sheshadri * 2226 10021 Sheshadri * Return Code: 0 for success 2227 10021 Sheshadri * 2228 10021 Sheshadri * Context: User and Kernel thread 2229 10021 Sheshadri * 2230 10021 Sheshadri * Notes: 2231 10021 Sheshadri * The linux swap magic "SWAP-SPACE" or "SWAPSPACE2" is found as the 2232 10021 Sheshadri * last 10 bytes of a disk block whose size is that of the linux page 2233 10021 Sheshadri * size. This disk block is found at the beginning of the swap partition. 2234 10021 Sheshadri */ 2235 10021 Sheshadri static int 2236 10021 Sheshadri cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start, void *tg_cookie) 2237 10021 Sheshadri { 2238 10021 Sheshadri int i; 2239 10021 Sheshadri int rval = -1; 2240 10021 Sheshadri uint32_t seek_offset; 2241 10021 Sheshadri uint32_t linux_pg_size; 2242 10021 Sheshadri char *buf, *linux_swap_magic; 2243 10021 Sheshadri int sec_sz = cl->cl_sys_blocksize; 2244 10021 Sheshadri /* Known linux kernel page sizes */ 2245 10021 Sheshadri uint32_t linux_pg_size_arr[] = {4096, }; 2246 10021 Sheshadri 2247 10021 Sheshadri ASSERT(cl != NULL); 2248 10021 Sheshadri ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2249 10021 Sheshadri 2250 10021 Sheshadri if ((buf = kmem_zalloc(sec_sz, KM_NOSLEEP)) == NULL) { 2251 10021 Sheshadri return (ENOMEM); 2252 10021 Sheshadri } 2253 10021 Sheshadri 2254 10682 Sheshadri /* 2255 10682 Sheshadri * Check if there is a sane Solaris VTOC 2256 10682 Sheshadri * If there is a valid vtoc, no need to lookup 2257 10682 Sheshadri * for the linux swap signature. 2258 10682 Sheshadri */ 2259 10682 Sheshadri mutex_exit(CMLB_MUTEX(cl)); 2260 10682 Sheshadri rval = DK_TG_READ(cl, buf, part_start + DK_LABEL_LOC, 2261 10682 Sheshadri sec_sz, tg_cookie); 2262 10682 Sheshadri mutex_enter(CMLB_MUTEX(cl)); 2263 10682 Sheshadri if (rval != 0) { 2264 10682 Sheshadri cmlb_dbg(CMLB_ERROR, cl, 2265 10682 Sheshadri "cmlb_is_linux_swap: disk vtoc read err\n"); 2266 10682 Sheshadri rval = EIO; 2267 10682 Sheshadri goto done; 2268 10682 Sheshadri } 2269 10682 Sheshadri 2270 10682 Sheshadri if ((((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) && 2271 10682 Sheshadri (((struct dk_label *)buf)->dkl_vtoc.v_sanity == VTOC_SANE)) { 2272 10682 Sheshadri rval = -1; 2273 10682 Sheshadri goto done; 2274 10682 Sheshadri } 2275 10682 Sheshadri 2276 10682 Sheshadri 2277 10682 Sheshadri /* No valid vtoc, so check for linux swap signature */ 2278 10021 Sheshadri linux_swap_magic = buf + sec_sz - 10; 2279 10021 Sheshadri 2280 10021 Sheshadri for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) { 2281 10021 Sheshadri linux_pg_size = linux_pg_size_arr[i]; 2282 10021 Sheshadri seek_offset = linux_pg_size/sec_sz - 1; 2283 10021 Sheshadri seek_offset += part_start; 2284 10021 Sheshadri 2285 10021 Sheshadri mutex_exit(CMLB_MUTEX(cl)); 2286 10021 Sheshadri rval = DK_TG_READ(cl, buf, seek_offset, sec_sz, tg_cookie); 2287 10021 Sheshadri mutex_enter(CMLB_MUTEX(cl)); 2288 10021 Sheshadri 2289 10021 Sheshadri if (rval != 0) { 2290 10021 Sheshadri cmlb_dbg(CMLB_ERROR, cl, 2291 10021 Sheshadri "cmlb_is_linux_swap: disk read err\n"); 2292 10021 Sheshadri rval = EIO; 2293 10021 Sheshadri break; 2294 10021 Sheshadri } 2295 10021 Sheshadri 2296 10021 Sheshadri rval = -1; 2297 10021 Sheshadri 2298 10021 Sheshadri if ((strncmp(linux_swap_magic, "SWAP-SPACE", 10) == 0) || 2299 10021 Sheshadri (strncmp(linux_swap_magic, "SWAPSPACE2", 10) == 0)) { 2300 10021 Sheshadri /* Found a linux swap */ 2301 10021 Sheshadri rval = 0; 2302 10021 Sheshadri break; 2303 10021 Sheshadri } 2304 10021 Sheshadri } 2305 10021 Sheshadri 2306 10682 Sheshadri done: 2307 10021 Sheshadri kmem_free(buf, sec_sz); 2308 10021 Sheshadri return (rval); 2309 10021 Sheshadri } 2310 10021 Sheshadri #endif 2311 10021 Sheshadri 2312 786 lclee /* 2313 786 lclee * Function: cmlb_read_fdisk 2314 786 lclee * 2315 786 lclee * Description: utility routine to read the fdisk table. 2316 786 lclee * 2317 3525 shidokht * Arguments: 2318 3525 shidokht * cl driver soft state (unit) structure 2319 3525 shidokht * capacity disk capacity in #blocks 2320 3525 shidokht * tg_cookie cookie from target driver to be passed back to target 2321 3525 shidokht * driver when we call back to it through tg_ops. 2322 786 lclee * 2323 786 lclee * Return Code: 0 for success (includes not reading for no_fdisk_present case 2324 786 lclee * errnos from tg_rw if failed to read the first block. 2325 786 lclee * 2326 786 lclee * Context: Kernel thread only (can sleep). 2327 786 lclee */ 2328 3525 shidokht /*ARGSUSED*/ 2329 3525 shidokht static int 2330 3525 shidokht cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) 2331 786 lclee { 2332 786 lclee #if defined(_NO_FDISK_PRESENT) 2333 786 lclee 2334 3525 shidokht cl->cl_solaris_offset = 0; 2335 3525 shidokht cl->cl_solaris_size = capacity; 2336 3525 shidokht bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 2337 786 lclee return (0); 2338 786 lclee 2339 786 lclee #elif defined(_FIRMWARE_NEEDS_FDISK) 2340 786 lclee 2341 786 lclee struct ipart *fdp; 2342 786 lclee struct mboot *mbp; 2343 786 lclee struct ipart fdisk[FD_NUMPART]; 2344 10021 Sheshadri int i, k; 2345 786 lclee char sigbuf[2]; 2346 786 lclee caddr_t bufp; 2347 786 lclee int uidx; 2348 786 lclee int rval; 2349 786 lclee int lba = 0; 2350 786 lclee uint_t solaris_offset; /* offset to solaris part. */ 2351 786 lclee daddr_t solaris_size; /* size of solaris partition */ 2352 786 lclee uint32_t blocksize; 2353 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2354 10021 Sheshadri struct ipart eparts[2]; 2355 10021 Sheshadri struct ipart *efdp1 = &eparts[0]; 2356 10021 Sheshadri struct ipart *efdp2 = &eparts[1]; 2357 10021 Sheshadri int ext_part_exists = 0; 2358 10021 Sheshadri int ld_count = 0; 2359 10021 Sheshadri #endif 2360 786 lclee 2361 3525 shidokht ASSERT(cl != NULL); 2362 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2363 786 lclee 2364 786 lclee /* 2365 786 lclee * Start off assuming no fdisk table 2366 786 lclee */ 2367 786 lclee solaris_offset = 0; 2368 786 lclee solaris_size = capacity; 2369 786 lclee 2370 3525 shidokht blocksize = cl->cl_tgt_blocksize; 2371 786 lclee 2372 786 lclee bufp = kmem_zalloc(blocksize, KM_SLEEP); 2373 786 lclee 2374 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 2375 3525 shidokht rval = DK_TG_READ(cl, bufp, 0, blocksize, tg_cookie); 2376 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 2377 3525 shidokht 2378 3525 shidokht if (rval != 0) { 2379 3525 shidokht cmlb_dbg(CMLB_ERROR, cl, 2380 786 lclee "cmlb_read_fdisk: fdisk read err\n"); 2381 3525 shidokht bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 2382 3525 shidokht goto done; 2383 786 lclee } 2384 786 lclee 2385 786 lclee mbp = (struct mboot *)bufp; 2386 786 lclee 2387 786 lclee /* 2388 786 lclee * The fdisk table does not begin on a 4-byte boundary within the 2389 786 lclee * master boot record, so we copy it to an aligned structure to avoid 2390 786 lclee * alignment exceptions on some processors. 2391 786 lclee */ 2392 786 lclee bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2393 786 lclee 2394 786 lclee /* 2395 786 lclee * Check for lba support before verifying sig; sig might not be 2396 786 lclee * there, say on a blank disk, but the max_chs mark may still 2397 786 lclee * be present. 2398 786 lclee * 2399 786 lclee * Note: LBA support and BEFs are an x86-only concept but this 2400 786 lclee * code should work OK on SPARC as well. 2401 786 lclee */ 2402 786 lclee 2403 786 lclee /* 2404 786 lclee * First, check for lba-access-ok on root node (or prom root node) 2405 786 lclee * if present there, don't need to search fdisk table. 2406 786 lclee */ 2407 786 lclee if (ddi_getprop(DDI_DEV_T_ANY, ddi_root_node(), 0, 2408 786 lclee "lba-access-ok", 0) != 0) { 2409 786 lclee /* All drives do LBA; don't search fdisk table */ 2410 786 lclee lba = 1; 2411 786 lclee } else { 2412 786 lclee /* Okay, look for mark in fdisk table */ 2413 786 lclee for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2414 786 lclee /* accumulate "lba" value from all partitions */ 2415 786 lclee lba = (lba || cmlb_has_max_chs_vals(fdp)); 2416 786 lclee } 2417 786 lclee } 2418 786 lclee 2419 786 lclee if (lba != 0) { 2420 3525 shidokht dev_t dev = cmlb_make_device(cl); 2421 3525 shidokht 2422 3525 shidokht if (ddi_getprop(dev, CMLB_DEVINFO(cl), DDI_PROP_DONTPASS, 2423 786 lclee "lba-access-ok", 0) == 0) { 2424 786 lclee /* not found; create it */ 2425 3525 shidokht if (ddi_prop_create(dev, CMLB_DEVINFO(cl), 0, 2426 786 lclee "lba-access-ok", (caddr_t)NULL, 0) != 2427 786 lclee DDI_PROP_SUCCESS) { 2428 3525 shidokht cmlb_dbg(CMLB_ERROR, cl, 2429 786 lclee "cmlb_read_fdisk: Can't create lba " 2430 786 lclee "property for instance %d\n", 2431 3525 shidokht ddi_get_instance(CMLB_DEVINFO(cl))); 2432 786 lclee } 2433 786 lclee } 2434 786 lclee } 2435 786 lclee 2436 786 lclee bcopy(&mbp->signature, sigbuf, sizeof (sigbuf)); 2437 786 lclee 2438 786 lclee /* 2439 786 lclee * Endian-independent signature check 2440 786 lclee */ 2441 786 lclee if (((sigbuf[1] & 0xFF) != ((MBB_MAGIC >> 8) & 0xFF)) || 2442 786 lclee (sigbuf[0] != (MBB_MAGIC & 0xFF))) { 2443 3525 shidokht cmlb_dbg(CMLB_ERROR, cl, 2444 786 lclee "cmlb_read_fdisk: no fdisk\n"); 2445 3525 shidokht bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 2446 786 lclee goto done; 2447 786 lclee } 2448 786 lclee 2449 786 lclee #ifdef CMLBDEBUG 2450 3525 shidokht if (cmlb_level_mask & CMLB_LOGMASK_INFO) { 2451 786 lclee fdp = fdisk; 2452 3525 shidokht cmlb_dbg(CMLB_INFO, cl, "cmlb_read_fdisk:\n"); 2453 3525 shidokht cmlb_dbg(CMLB_INFO, cl, " relsect " 2454 786 lclee "numsect sysid bootid\n"); 2455 786 lclee for (i = 0; i < FD_NUMPART; i++, fdp++) { 2456 3525 shidokht cmlb_dbg(CMLB_INFO, cl, 2457 786 lclee " %d: %8d %8d 0x%08x 0x%08x\n", 2458 786 lclee i, fdp->relsect, fdp->numsect, 2459 786 lclee fdp->systid, fdp->bootid); 2460 786 lclee } 2461 786 lclee } 2462 786 lclee #endif 2463 786 lclee 2464 786 lclee /* 2465 786 lclee * Try to find the unix partition 2466 786 lclee */ 2467 786 lclee uidx = -1; 2468 786 lclee solaris_offset = 0; 2469 786 lclee solaris_size = 0; 2470 786 lclee 2471 786 lclee for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2472 7563 Prasad uint32_t relsect; 2473 7563 Prasad uint32_t numsect; 2474 10021 Sheshadri uchar_t systid; 2475 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2476 10021 Sheshadri /* 2477 10021 Sheshadri * Stores relative block offset from the beginning of the 2478 10021 Sheshadri * Extended Partition. 2479 10021 Sheshadri */ 2480 10021 Sheshadri int ext_relsect = 0; 2481 10021 Sheshadri #endif 2482 786 lclee 2483 786 lclee if (fdp->numsect == 0) { 2484 3525 shidokht cl->cl_fmap[i].fmap_start = 0; 2485 3525 shidokht cl->cl_fmap[i].fmap_nblk = 0; 2486 786 lclee continue; 2487 786 lclee } 2488 786 lclee 2489 786 lclee /* 2490 786 lclee * Data in the fdisk table is little-endian. 2491 786 lclee */ 2492 786 lclee relsect = LE_32(fdp->relsect); 2493 786 lclee numsect = LE_32(fdp->numsect); 2494 786 lclee 2495 3525 shidokht cl->cl_fmap[i].fmap_start = relsect; 2496 3525 shidokht cl->cl_fmap[i].fmap_nblk = numsect; 2497 10021 Sheshadri cl->cl_fmap[i].fmap_systid = LE_8(fdp->systid); 2498 10021 Sheshadri 2499 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2500 10021 Sheshadri /* Support only one extended partition per LUN */ 2501 10021 Sheshadri if ((fdp->systid == EXTDOS || fdp->systid == FDISK_EXTLBA) && 2502 10021 Sheshadri (ext_part_exists == 0)) { 2503 10021 Sheshadri int j; 2504 10021 Sheshadri uint32_t logdrive_offset; 2505 10021 Sheshadri uint32_t ext_numsect; 2506 10021 Sheshadri uint32_t abs_secnum; 2507 10021 Sheshadri 2508 10021 Sheshadri ext_part_exists = 1; 2509 10021 Sheshadri 2510 10021 Sheshadri for (j = FD_NUMPART; j < FDISK_PARTS; j++) { 2511 10021 Sheshadri mutex_exit(CMLB_MUTEX(cl)); 2512 10021 Sheshadri rval = DK_TG_READ(cl, bufp, 2513 10021 Sheshadri (relsect + ext_relsect), blocksize, 2514 10021 Sheshadri tg_cookie); 2515 10021 Sheshadri mutex_enter(CMLB_MUTEX(cl)); 2516 10021 Sheshadri 2517 10021 Sheshadri if (rval != 0) { 2518 10021 Sheshadri cmlb_dbg(CMLB_ERROR, cl, 2519 10021 Sheshadri "cmlb_read_fdisk: Extended " 2520 10021 Sheshadri "partition read err\n"); 2521 10021 Sheshadri goto done; 2522 10021 Sheshadri } 2523 10021 Sheshadri /* 2524 10021 Sheshadri * The first ipart entry provides the offset 2525 10021 Sheshadri * at which the logical drive starts off from 2526 10021 Sheshadri * the beginning of the container partition 2527 10021 Sheshadri * and the size of the logical drive. 2528 10021 Sheshadri * The second ipart entry provides the offset 2529 10021 Sheshadri * of the next container partition from the 2530 10021 Sheshadri * beginning of the extended partition. 2531 10021 Sheshadri */ 2532 10021 Sheshadri bcopy(&bufp[FDISK_PART_TABLE_START], eparts, 2533 10021 Sheshadri sizeof (eparts)); 2534 10021 Sheshadri logdrive_offset = LE_32(efdp1->relsect); 2535 10021 Sheshadri ext_numsect = LE_32(efdp1->numsect); 2536 10021 Sheshadri systid = LE_8(efdp1->systid); 2537 10021 Sheshadri if (logdrive_offset <= 0 || ext_numsect <= 0) 2538 10021 Sheshadri break; 2539 10021 Sheshadri abs_secnum = relsect + ext_relsect + 2540 10021 Sheshadri logdrive_offset; 2541 10021 Sheshadri 2542 10021 Sheshadri /* Boundary condition and overlap checking */ 2543 10021 Sheshadri if (cmlb_validate_ext_part(cl, i, j, abs_secnum, 2544 10021 Sheshadri ext_numsect)) { 2545 10021 Sheshadri break; 2546 10021 Sheshadri } 2547 10021 Sheshadri 2548 10021 Sheshadri if ((cl->cl_fmap[j].fmap_start != abs_secnum) || 2549 10021 Sheshadri (cl->cl_fmap[j].fmap_nblk != ext_numsect) || 2550 10021 Sheshadri (cl->cl_fmap[j].fmap_systid != systid)) { 2551 10021 Sheshadri /* 2552 10021 Sheshadri * Indicates change from previous 2553 10021 Sheshadri * partinfo. Need to recreate 2554 10021 Sheshadri * logical device nodes. 2555 10021 Sheshadri */ 2556 10021 Sheshadri cl->cl_update_ext_minor_nodes = 1; 2557 10021 Sheshadri } 2558 10021 Sheshadri cl->cl_fmap[j].fmap_start = abs_secnum; 2559 10021 Sheshadri cl->cl_fmap[j].fmap_nblk = ext_numsect; 2560 10021 Sheshadri cl->cl_fmap[j].fmap_systid = systid; 2561 10021 Sheshadri ld_count++; 2562 10021 Sheshadri 2563 10682 Sheshadri if ((efdp1->systid == SUNIXOS && 2564 10682 Sheshadri (cmlb_is_linux_swap(cl, abs_secnum, 2565 10682 Sheshadri tg_cookie) != 0)) || 2566 10682 Sheshadri efdp1->systid == SUNIXOS2) { 2567 10682 Sheshadri if (uidx == -1) { 2568 10021 Sheshadri uidx = 0; 2569 10021 Sheshadri solaris_offset = abs_secnum; 2570 10021 Sheshadri solaris_size = ext_numsect; 2571 10021 Sheshadri } 2572 10021 Sheshadri } 2573 10021 Sheshadri 2574 10021 Sheshadri if ((ext_relsect = LE_32(efdp2->relsect)) == 0) 2575 10021 Sheshadri break; 2576 10021 Sheshadri } 2577 10021 Sheshadri } 2578 10021 Sheshadri 2579 10021 Sheshadri #endif 2580 786 lclee 2581 786 lclee if (fdp->systid != SUNIXOS && 2582 786 lclee fdp->systid != SUNIXOS2 && 2583 786 lclee fdp->systid != EFI_PMBR) { 2584 786 lclee continue; 2585 786 lclee } 2586 786 lclee 2587 786 lclee /* 2588 786 lclee * use the last active solaris partition id found 2589 786 lclee * (there should only be 1 active partition id) 2590 786 lclee * 2591 786 lclee * if there are no active solaris partition id 2592 786 lclee * then use the first inactive solaris partition id 2593 786 lclee */ 2594 786 lclee if ((uidx == -1) || (fdp->bootid == ACTIVE)) { 2595 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2596 10682 Sheshadri if (fdp->systid != SUNIXOS || 2597 10682 Sheshadri (fdp->systid == SUNIXOS && 2598 10682 Sheshadri (cmlb_is_linux_swap(cl, relsect, 2599 10682 Sheshadri tg_cookie) != 0))) { 2600 10021 Sheshadri #endif 2601 10021 Sheshadri uidx = i; 2602 10021 Sheshadri solaris_offset = relsect; 2603 10021 Sheshadri solaris_size = numsect; 2604 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2605 10021 Sheshadri } 2606 10021 Sheshadri #endif 2607 10021 Sheshadri } 2608 10021 Sheshadri } 2609 10021 Sheshadri #if defined(__i386) || defined(__amd64) 2610 10021 Sheshadri if (ld_count < cl->cl_logical_drive_count) { 2611 10021 Sheshadri /* 2612 10021 Sheshadri * Some/all logical drives were deleted. Clear out 2613 10021 Sheshadri * the fmap entries correspoding to those deleted drives. 2614 10021 Sheshadri */ 2615 10021 Sheshadri for (k = ld_count + FD_NUMPART; 2616 10021 Sheshadri k < cl->cl_logical_drive_count + FD_NUMPART; k++) { 2617 10021 Sheshadri cl->cl_fmap[k].fmap_start = 0; 2618 10021 Sheshadri cl->cl_fmap[k].fmap_nblk = 0; 2619 10021 Sheshadri cl->cl_fmap[k].fmap_systid = 0; 2620 10021 Sheshadri } 2621 10021 Sheshadri cl->cl_update_ext_minor_nodes = 1; 2622 10021 Sheshadri } 2623 10021 Sheshadri if (cl->cl_update_ext_minor_nodes) { 2624 10021 Sheshadri rval = cmlb_update_ext_minor_nodes(cl, ld_count); 2625 10021 Sheshadri if (rval != 0) { 2626 10021 Sheshadri goto done; 2627 10021 Sheshadri } 2628 10021 Sheshadri } 2629 10021 Sheshadri #endif 2630 3525 shidokht cmlb_dbg(CMLB_INFO, cl, "fdisk 0x%x 0x%lx", 2631 3525 shidokht cl->cl_solaris_offset, cl->cl_solaris_size); 2632 786 lclee done: 2633 786 lclee 2634 786 lclee /* 2635 786 lclee * Clear the VTOC info, only if the Solaris partition entry 2636 786 lclee * has moved, changed size, been deleted, or if the size of 2637 786 lclee * the partition is too small to even fit the label sector. 2638 786 lclee */ 2639 3525 shidokht if ((cl->cl_solaris_offset != solaris_offset) || 2640 3525 shidokht (cl->cl_solaris_size != solaris_size) || 2641 786 lclee solaris_size <= DK_LABEL_LOC) { 2642 3525 shidokht cmlb_dbg(CMLB_INFO, cl, "fdisk moved 0x%x 0x%lx", 2643 3525 shidokht solaris_offset, solaris_size); 2644 3525 shidokht bzero(&cl->cl_g, sizeof (struct dk_geom)); 2645 3525 shidokht bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2646 3525 shidokht bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 2647 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 2648 3525 shidokht } 2649 3525 shidokht cl->cl_solaris_offset = solaris_offset; 2650 3525 shidokht cl->cl_solaris_size = solaris_size; 2651 786 lclee kmem_free(bufp, blocksize); 2652 786 lclee return (rval); 2653 786 lclee 2654 786 lclee #else /* #elif defined(_FIRMWARE_NEEDS_FDISK) */ 2655 786 lclee #error "fdisk table presence undetermined for this platform." 2656 786 lclee #endif /* #if defined(_NO_FDISK_PRESENT) */ 2657 786 lclee } 2658 786 lclee 2659 786 lclee static void 2660 786 lclee cmlb_swap_efi_gpt(efi_gpt_t *e) 2661 786 lclee { 2662 786 lclee _NOTE(ASSUMING_PROTECTED(*e)) 2663 786 lclee e->efi_gpt_Signature = LE_64(e->efi_gpt_Signature); 2664 786 lclee e->efi_gpt_Revision = LE_32(e->efi_gpt_Revision); 2665 786 lclee e->efi_gpt_HeaderSize = LE_32(e->efi_gpt_HeaderSize); 2666 786 lclee e->efi_gpt_HeaderCRC32 = LE_32(e->efi_gpt_HeaderCRC32); 2667 786 lclee e->efi_gpt_MyLBA = LE_64(e->efi_gpt_MyLBA); 2668 786 lclee e->efi_gpt_AlternateLBA = LE_64(e->efi_gpt_AlternateLBA); 2669 786 lclee e->efi_gpt_FirstUsableLBA = LE_64(e->efi_gpt_FirstUsableLBA); 2670 786 lclee e->efi_gpt_LastUsableLBA = LE_64(e->efi_gpt_LastUsableLBA); 2671 786 lclee UUID_LE_CONVERT(e->efi_gpt_DiskGUID, e->efi_gpt_DiskGUID); 2672 786 lclee e->efi_gpt_PartitionEntryLBA = LE_64(e->efi_gpt_PartitionEntryLBA); 2673 786 lclee e->efi_gpt_NumberOfPartitionEntries = 2674 786 lclee LE_32(e->efi_gpt_NumberOfPartitionEntries); 2675 786 lclee e->efi_gpt_SizeOfPartitionEntry = 2676 786 lclee LE_32(e->efi_gpt_SizeOfPartitionEntry); 2677 786 lclee e->efi_gpt_PartitionEntryArrayCRC32 = 2678 786 lclee LE_32(e->efi_gpt_PartitionEntryArrayCRC32); 2679 786 lclee } 2680 786 lclee 2681 786 lclee static void 2682 786 lclee cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p) 2683 786 lclee { 2684 786 lclee int i; 2685 786 lclee 2686 786 lclee _NOTE(ASSUMING_PROTECTED(*p)) 2687 786 lclee for (i = 0; i < nparts; i++) { 2688 786 lclee UUID_LE_CONVERT(p[i].efi_gpe_PartitionTypeGUID, 2689 786 lclee p[i].efi_gpe_PartitionTypeGUID); 2690 786 lclee p[i].efi_gpe_StartingLBA = LE_64(p[i].efi_gpe_StartingLBA); 2691 786 lclee p[i].efi_gpe_EndingLBA = LE_64(p[i].efi_gpe_EndingLBA); 2692 786 lclee /* PartitionAttrs */ 2693 786 lclee } 2694 786 lclee } 2695 786 lclee 2696 786 lclee static int 2697 786 lclee cmlb_validate_efi(efi_gpt_t *labp) 2698 786 lclee { 2699 786 lclee if (labp->efi_gpt_Signature != EFI_SIGNATURE) 2700 786 lclee return (EINVAL); 2701 786 lclee /* at least 96 bytes in this version of the spec. */ 2702 786 lclee if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) > 2703 786 lclee labp->efi_gpt_HeaderSize) 2704 786 lclee return (EINVAL); 2705 786 lclee /* this should be 128 bytes */ 2706 786 lclee if (labp->efi_gpt_SizeOfPartitionEntry != sizeof (efi_gpe_t)) 2707 786 lclee return (EINVAL); 2708 786 lclee return (0); 2709 786 lclee } 2710 786 lclee 2711 5624 shidokht /* 2712 8863 Edward * This function returns B_FALSE if there is a valid MBR signature and no 2713 8863 Edward * partition table entries of type EFI_PMBR (0xEE). Otherwise it returns B_TRUE. 2714 5624 shidokht * 2715 5624 shidokht * The EFI spec (1.10 and later) requires having a Protective MBR (PMBR) to 2716 5624 shidokht * recognize the disk as GPT partitioned. However, some other OS creates an MBR 2717 5624 shidokht * where a PMBR entry is not the only one. Also, if the first block has been 2718 5624 shidokht * corrupted, currently best attempt to allow data access would be to try to 2719 5624 shidokht * check for GPT headers. Hence in case of more than one partition entry, but 2720 5624 shidokht * at least one EFI_PMBR partition type or no valid magic number, the function 2721 8863 Edward * returns B_TRUE to continue with looking for GPT header. 2722 8863 Edward */ 2723 8863 Edward 2724 8863 Edward static boolean_t 2725 8863 Edward cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr) 2726 5624 shidokht { 2727 5624 shidokht struct ipart *fdp; 2728 5624 shidokht struct mboot *mbp = (struct mboot *)buf; 2729 5624 shidokht struct ipart fdisk[FD_NUMPART]; 2730 5624 shidokht int i; 2731 5624 shidokht 2732 7563 Prasad if (is_mbr != NULL) 2733 8863 Edward *is_mbr = B_TRUE; 2734 7563 Prasad 2735 7563 Prasad if (LE_16(mbp->signature) != MBB_MAGIC) { 2736 7563 Prasad if (is_mbr != NULL) 2737 8863 Edward *is_mbr = B_FALSE; 2738 8863 Edward return (B_TRUE); 2739 7563 Prasad } 2740 5624 shidokht 2741 5624 shidokht bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2742 5624 shidokht 2743 5624 shidokht for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2744 5624 shidokht if (fdp->systid == EFI_PMBR) 2745 8863 Edward return (B_TRUE); 2746 8863 Edward } 2747 8863 Edward 2748 8863 Edward return (B_FALSE); 2749 5624 shidokht } 2750 5624 shidokht 2751 786 lclee static int 2752 3525 shidokht cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 2753 3525 shidokht void *tg_cookie) 2754 786 lclee { 2755 786 lclee int i; 2756 786 lclee int rval = 0; 2757 786 lclee efi_gpe_t *partitions; 2758 786 lclee uchar_t *buf; 2759 786 lclee uint_t lbasize; /* is really how much to read */ 2760 3525 shidokht diskaddr_t cap = 0; 2761 786 lclee uint_t nparts; 2762 786 lclee diskaddr_t gpe_lba; 2763 6590 yl194034 diskaddr_t alternate_lba; 2764 1071 shidokht int iofailed = 0; 2765 3525 shidokht struct uuid uuid_type_reserved = EFI_RESERVED; 2766 7563 Prasad #if defined(_FIRMWARE_NEEDS_FDISK) 2767 8863 Edward boolean_t is_mbr; 2768 7563 Prasad #endif 2769 3525 shidokht 2770 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2771 3525 shidokht 2772 3525 shidokht lbasize = cl->cl_sys_blocksize; 2773 3525 shidokht 2774 3525 shidokht cl->cl_reserved = -1; 2775 3525 shidokht mutex_exit(CMLB_MUTEX(cl)); 2776 786 lclee 2777 786 lclee buf = kmem_zalloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 2778 3525 shidokht 2779 7563 Prasad rval = DK_TG_READ(cl, buf, 0, lbasize, tg_cookie); 2780 786 lclee if (rval) { 2781 1071 shidokht iofailed = 1; 2782 786 lclee goto done_err; 2783 786 lclee } 2784 786 lclee if (((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) { 2785 786 lclee /* not ours */ 2786 786 lclee rval = ESRCH; 2787 5624 shidokht goto done_err; 2788 5624 shidokht } 2789 5624 shidokht 2790 7563 Prasad #if defined(_FIRMWARE_NEEDS_FDISK) 2791 8863 Edward if (!cmlb_check_efi_mbr(buf, &is_mbr)) { 2792 8863 Edward if (is_mbr) 2793 7563 Prasad rval = ESRCH; 2794 7563 Prasad else 2795 7563 Prasad rval = EINVAL; 2796 7563 Prasad goto done_err; 2797 7563 Prasad } 2798 7563 Prasad #else 2799 8863 Edward if (!cmlb_check_efi_mbr(buf, NULL)) { 2800 5624 shidokht rval = EINVAL; 2801 786 lclee goto done_err; 2802 786 lclee } 2803 7563 Prasad 2804 7563 Prasad #endif 2805 786 lclee 2806 3525 shidokht rval = DK_TG_READ(cl, buf, 1, lbasize, tg_cookie); 2807 786 lclee if (rval) { 2808 1071 shidokht iofailed = 1; 2809 786 lclee goto done_err; 2810 786 lclee } 2811 786 lclee cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2812 786 lclee 2813 786 lclee if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2814 786 lclee /* 2815 786 lclee * Couldn't read the primary, try the backup. Our 2816 786 lclee * capacity at this point could be based on CHS, so 2817 786 lclee * check what the device reports. 2818 786 lclee */ 2819 3525 shidokht rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 2820 786 lclee if (rval) { 2821 1071 shidokht iofailed = 1; 2822 786 lclee goto done_err; 2823 786 lclee } 2824 3525 shidokht 2825 3525 shidokht /* 2826 3525 shidokht * CMLB_OFF_BY_ONE case, we check the next to last block first 2827 3525 shidokht * for backup GPT header, otherwise check the last block. 2828 3525 shidokht */ 2829 3525 shidokht 2830 3525 shidokht if ((rval = DK_TG_READ(cl, buf, 2831 3525 shidokht cap - ((cl->cl_alter_behavior & CMLB_OFF_BY_ONE) ? 2 : 1), 2832 3525 shidokht lbasize, tg_cookie)) 2833 3525 shidokht != 0) { 2834 1071 shidokht iofailed = 1; 2835 786 lclee goto done_err; 2836 786 lclee } 2837 786 lclee cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2838 3525 shidokht 2839 3525 shidokht if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2840 3525 shidokht 2841 3525 shidokht if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE)) 2842 3525 shidokht goto done_err; 2843 3525 shidokht if ((rval = DK_TG_READ(cl, buf, cap - 1, lbasize, 2844 3525 shidokht tg_cookie)) != 0) 2845 3525 shidokht goto done_err; 2846 3525 shidokht cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2847 3525 shidokht if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) 2848 3525 shidokht goto done_err; 2849 3525 shidokht } 2850 3525 shidokht if (!(flags & CMLB_SILENT)) 2851 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2852 3525 shidokht "primary label corrupt; using backup\n"); 2853 786 lclee } 2854 786 lclee 2855 786 lclee nparts = ((efi_gpt_t *)buf)->efi_gpt_NumberOfPartitionEntries; 2856 786 lclee gpe_lba = ((efi_gpt_t *)buf)->efi_gpt_PartitionEntryLBA; 2857 6590 yl194034 alternate_lba = ((efi_gpt_t *)buf)->efi_gpt_AlternateLBA; 2858 786 lclee 2859 3525 shidokht rval = DK_TG_READ(cl, buf, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 2860 786 lclee if (rval) { 2861 1071 shidokht iofailed = 1; 2862 786 lclee goto done_err; 2863 786 lclee } 2864 786 lclee partitions = (efi_gpe_t *)buf; 2865 786 lclee 2866 786 lclee if (nparts > MAXPART) { 2867 786 lclee nparts = MAXPART; 2868 786 lclee } 2869 786 lclee cmlb_swap_efi_gpe(nparts, partitions); 2870 786 lclee 2871 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 2872 786 lclee 2873 786 lclee /* Fill in partition table. */ 2874 786 lclee for (i = 0; i < nparts; i++) { 2875 786 lclee if (partitions->efi_gpe_StartingLBA != 0 || 2876 786 lclee partitions->efi_gpe_EndingLBA != 0) { 2877 3525 shidokht cl->cl_map[i].dkl_cylno = 2878 786 lclee partitions->efi_gpe_StartingLBA; 2879 3525 shidokht cl->cl_map[i].dkl_nblk = 2880 786 lclee partitions->efi_gpe_EndingLBA - 2881 786 lclee partitions->efi_gpe_StartingLBA + 1; 2882 3525 shidokht cl->cl_offset[i] = 2883 786 lclee partitions->efi_gpe_StartingLBA; 2884 786 lclee } 2885 3525 shidokht 2886 3525 shidokht if (cl->cl_reserved == -1) { 2887 3525 shidokht if (bcmp(&partitions->efi_gpe_PartitionTypeGUID, 2888 3525 shidokht &uuid_type_reserved, sizeof (struct uuid)) == 0) { 2889 3525 shidokht cl->cl_reserved = i; 2890 3525 shidokht } 2891 3525 shidokht } 2892 786 lclee if (i == WD_NODE) { 2893 786 lclee /* 2894 786 lclee * minor number 7 corresponds to the whole disk 2895 6590 yl194034 * if the disk capacity is expanded after disk is 2896 6590 yl194034 * labeled, minor number 7 represents the capacity 2897 6590 yl194034 * indicated by the disk label. 2898 786 lclee */ 2899 3525 shidokht cl->cl_map[i].dkl_cylno = 0; 2900 6590 yl194034 if (alternate_lba == 1) { 2901 6590 yl194034 /* 2902 6590 yl194034 * We are using backup label. Since we can 2903 6590 yl194034 * find a valid label at the end of disk, 2904 6590 yl194034 * the disk capacity is not expanded. 2905 6590 yl194034 */ 2906 6590 yl194034 cl->cl_map[i].dkl_nblk = capacity; 2907 6590 yl194034 } else { 2908 6590 yl194034 cl->cl_map[i].dkl_nblk = alternate_lba + 1; 2909 6590 yl194034 } 2910 3525 shidokht cl->cl_offset[i] = 0; 2911 786 lclee } 2912 786 lclee partitions++; 2913 786 lclee } 2914 3525 shidokht cl->cl_solaris_offset = 0; 2915 3525 shidokht cl->cl_solaris_size = capacity; 2916 7563 Prasad cl->cl_label_from_media = CMLB_LABEL_EFI; 2917 8863 Edward cl->cl_f_geometry_is_valid = B_TRUE; 2918 3525 shidokht 2919 3525 shidokht /* clear the vtoc label */ 2920 3525 shidokht bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2921 3525 shidokht 2922 786 lclee kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2923 786 lclee return (0); 2924 786 lclee 2925 786 lclee done_err: 2926 786 lclee kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2927 3525 shidokht mutex_enter(CMLB_MUTEX(cl)); 2928 3525 shidokht done_err1: 2929 786 lclee /* 2930 786 lclee * if we didn't find something that could look like a VTOC 2931 786 lclee * and the disk is over 1TB, we know there isn't a valid label. 2932 786 lclee * Otherwise let cmlb_uselabel decide what to do. We only 2933 786 lclee * want to invalidate this if we're certain the label isn't 2934 786 lclee * valid because cmlb_prop_op will now fail, which in turn 2935 786 lclee * causes things like opens and stats on the partition to fail. 2936 786 lclee */ 2937 7563 Prasad if ((capacity > CMLB_EXTVTOC_LIMIT) && (rval != ESRCH) && !iofailed) { 2938 8863 Edward cl->cl_f_geometry_is_valid = B_FALSE; 2939 786 lclee } 2940 786 lclee return (rval); 2941 786 lclee } 2942 786 lclee 2943 786 lclee 2944 786 lclee /* 2945 786 lclee * Function: cmlb_uselabel 2946 786 lclee * 2947 786 lclee * Description: Validate the disk label and update the relevant data (geometry, 2948 786 lclee * partition, vtoc, and capacity data) in the cmlb_lun struct. 2949 786 lclee * Marks the geometry of the unit as being valid. 2950 786 lclee * 2951 3525 shidokht * Arguments: cl: unit struct. 2952 786 lclee * dk_label: disk label 2953 786 lclee * 2954 786 lclee * Return Code: CMLB_LABEL_IS_VALID: Label read from disk is OK; geometry, 2955 786 lclee * partition, vtoc, and capacity data are good. 2956 786 lclee * 2957 786 lclee * CMLB_LABEL_IS_INVALID: Magic number or checksum error in the 2958 786 lclee * label; or computed capacity does not jibe with capacity 2959 786 lclee * reported from the READ CAPACITY command. 2960 786 lclee * 2961 786 lclee * Context: Kernel thread only (can sleep). 2962 786 lclee */ 2963 786 lclee static int 2964 3525 shidokht cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *labp, int flags) 2965 786 lclee { 2966 786 lclee short *sp; 2967 786 lclee short sum; 2968 786 lclee short count; 2969 786 lclee int label_error = CMLB_LABEL_IS_VALID; 2970 786 lclee int i; 2971 786 lclee diskaddr_t label_capacity; 2972 7563 Prasad uint32_t part_end; 2973 786 lclee diskaddr_t track_capacity; 2974 786 lclee #if defined(_SUNOS_VTOC_16) 2975 786 lclee struct dkl_partition *vpartp; 2976 786 lclee #endif 2977 3525 shidokht ASSERT(cl != NULL); 2978 3525 shidokht ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2979 786 lclee 2980 786 lclee /* Validate the magic number of the label. */ 2981 786 lclee if (labp->dkl_magic != DKL_MAGIC) { 2982 786 lclee #if defined(__sparc) 2983 3525 shidokht if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2984 3525 shidokht if (!(flags & CMLB_SILENT)) 2985 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2986 3525 shidokht CE_WARN, 2987 3525 shidokht "Corrupt label; wrong magic number\n"); 2988 786 lclee } 2989 786 lclee #endif 2990 786 lclee return (CMLB_LABEL_IS_INVALID); 2991 786 lclee } 2992 786 lclee 2993 786 lclee /* Validate the checksum of the label. */ 2994 786 lclee sp = (short *)labp; 2995 786 lclee sum = 0; 2996 786 lclee count = sizeof (struct dk_label) / sizeof (short); 2997 786 lclee while (count--) { 2998 786 lclee sum ^= *sp++; 2999 786 lclee } 3000 786 lclee 3001 786 lclee if (sum != 0) { 3002 786 lclee #if defined(_SUNOS_VTOC_16) 3003 3525 shidokht if (!ISCD(cl)) { 3004 786 lclee #elif defined(_SUNOS_VTOC_8) 3005 3525 shidokht if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 3006 3525 shidokht #endif 3007 3525 shidokht if (!(flags & CMLB_SILENT)) 3008 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 3009 3525 shidokht CE_WARN, 3010 3525 shidokht "Corrupt label - label checksum failed\n"); 3011 786 lclee } 3012 786 lclee return (CMLB_LABEL_IS_INVALID); 3013 786 lclee } 3014 786 lclee 3015 786 lclee 3016 786 lclee /* 3017 786 lclee * Fill in geometry structure with data from label. 3018 786 lclee */ 3019 3525 shidokht bzero(&cl->cl_g, sizeof (struct dk_geom)); 3020 3525 shidokht cl->cl_g.dkg_ncyl = labp->dkl_ncyl; 3021 3525 shidokht cl->cl_g.dkg_acyl = labp->dkl_acyl; 3022 3525 shidokht cl->cl_g.dkg_bcyl = 0; 3023 3525 shidokht cl->cl_g.dkg_nhead = labp->dkl_nhead; 3024 3525 shidokht cl->cl_g.dkg_nsect = labp->dkl_nsect; 3025 3525 shidokht cl->cl_g.dkg_intrlv = labp->dkl_intrlv; 3026 3525 shidokht 3027 3525 shidokht #if defined(_SUNOS_VTOC_8) 3028 3525 shidokht cl->cl_g.dkg_gap1 = labp->dkl_gap1; 3029 3525 shidokht cl->cl_g.dkg_gap2 = labp->dkl_gap2; 3030 3525 shidokht cl->cl_g.dkg_bhead = labp->dkl_bhead; 3031 3525 shidokht #endif 3032 3525 shidokht #if defined(_SUNOS_VTOC_16) 3033 3525 shidokht cl->cl_dkg_skew = labp->dkl_skew; 3034 3525 shidokht #endif 3035 3525 shidokht 3036 3525 shidokht #if defined(__i386) || defined(__amd64) 3037 3525 shidokht cl->cl_g.dkg_apc = labp->dkl_apc; 3038 786 lclee #endif 3039 786 lclee 3040 786 lclee /* 3041 786 lclee * Currently we rely on the values in the label being accurate. If 3042 786 lclee * dkl_rpm or dkl_pcly are zero in the label, use a default value. 3043 786 lclee * 3044 786 lclee * Note: In the future a MODE SENSE may be used to retrieve this data, 3045 786 lclee * although this command is optional in SCSI-2. 3046 786 lclee */ 3047 3525 shidokht cl->cl_g.dkg_rpm = (labp->dkl_rpm != 0) ? labp->dkl_rpm : 3600; 3048 3525 shidokht cl->cl_g.dkg_pcyl = (labp->dkl_pcyl != 0) ? labp->dkl_pcyl : 3049 3525 shidokht (cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl); 3050 786 lclee 3051 786 lclee /* 3052 786 lclee * The Read and Write reinstruct values may not be valid 3053 786 lclee * for older disks. 3054 786 lclee */ 3055 3525 shidokht cl->cl_g.dkg_read_reinstruct = labp->dkl_read_reinstruct; 3056 3525 shidokht cl->cl_g.dkg_write_reinstruct = labp->dkl_write_reinstruct; 3057 786 lclee 3058 786 lclee /* Fill in partition table. */ 3059 786 lclee #if defined(_SUNOS_VTOC_8) 3060 786 lclee for (i = 0; i < NDKMAP; i++) { 3061 3525 shidokht cl->cl_map[i].dkl_cylno = labp->dkl_map[i].dkl_cylno; 3062 3525 shidokht cl->cl_map[i].dkl_nblk = labp->dkl_map[i].dkl_nblk; 3063 786 lclee } 3064 786 lclee #endif 3065 786 lclee #if defined(_SUNOS_VTOC_16) 3066 786 lclee vpartp = labp->dkl_vtoc.v_part; 3067 786 lclee track_capacity = labp->dkl_nhead * labp->dkl_nsect; 3068 786 lclee 3069 3525 shidokht /* Prevent divide by zero */ 3070 3525 shidokht if (track_capacity == 0) { 3071 3525 shidokht if (!(flags & CMLB_SILENT)) 3072 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 3073 3525 shidokht "Corrupt label - zero nhead or nsect value\n"); 3074 3525 shidokht 3075 3525 shidokht return (CMLB_LABEL_IS_INVALID); 3076 3525 shidokht } 3077 3525 shidokht 3078 786 lclee for (i = 0; i < NDKMAP; i++, vpartp++) { 3079 3525 shidokht cl->cl_map[i].dkl_cylno = vpartp->p_start / track_capacity; 3080 3525 shidokht cl->cl_map[i].dkl_nblk = vpartp->p_size; 3081 786 lclee } 3082 786 lclee #endif 3083 786 lclee 3084 786 lclee /* Fill in VTOC Structure. */ 3085 3525 shidokht bcopy(&labp->dkl_vtoc, &cl->cl_vtoc, sizeof (struct dk_vtoc)); 3086 786 lclee #if defined(_SUNOS_VTOC_8) 3087 786 lclee /* 3088 786 lclee * The 8-slice vtoc does not include the ascii label; save it into 3089 786 lclee * the device's soft state structure here. 3090 786 lclee */ 3091 3525 shidokht bcopy(labp->dkl_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 3092 3525 shidokht #endif 3093 3525 shidokht 3094 3525 shidokht /* Now look for a valid capacity. */ 3095 3525 shidokht track_capacity = (cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect); 3096 3525 shidokht label_capacity = (cl->cl_g.dkg_ncyl * track_capacity); 3097 3525 shidokht 3098 3525 shidokht if (cl->cl_g.dkg_acyl) { 3099 3525 shidokht #if defined(__i386) || defined(__amd64) 3100 3525 shidokht /* we may have > 1 alts cylinder */ 3101 3525 shidokht label_capacity += (track_capacity * cl->cl_g.dkg_acyl); 3102 3525 shidokht #else 3103 3525 shidokht label_capacity += track_capacity; 3104 3525 shidokht #endif 3105 3525 shidokht } 3106 3525 shidokht 3107 3525 shidokht /* 3108 3525 shidokht * Force check here to ensure the computed capacity is valid. 3109 3525 shidokht * If capacity is zero, it indicates an invalid label and 3110 3525 shidokht * we should abort updating the relevant data then. 3111 3525 shidokht */ 3112 3525 shidokht if (label_capacity == 0) { 3113 3525 shidokht if (!(flags & CMLB_SILENT)) 3114 3525 shidokht cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 3115 3525 shidokht "Corrupt label - no valid capacity could be " 3116 3525 shidokht "retrieved\n"); 3117 3525 shidokht