blob: 17eca5328822ee06265dafd0caebffde1a42daee [file] [log] [blame]
lclee3ccda642005-10-28 23:47:40 -07001/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
shidokhte8fb11a2007-01-31 14:43:05 -08005 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
lclee3ccda642005-10-28 23:47:40 -07007 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
Garrett D'Amore59d8f102013-11-17 14:26:56 -080023 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
Sharath M Srinivasan7e74b1c2010-01-18 13:03:01 +053024 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
lclee3ccda642005-10-28 23:47:40 -070025 * Use is subject to license terms.
Toomas Soome406fc512015-10-23 09:36:11 +030026 * Copyright 2016 Toomas Soome <tsoome@me.com>
lclee3ccda642005-10-28 23:47:40 -070027 */
28
lclee3ccda642005-10-28 23:47:40 -070029/*
30 * This module provides support for labeling operations for target
31 * drivers.
32 */
33
34#include <sys/scsi/scsi.h>
35#include <sys/sunddi.h>
36#include <sys/dklabel.h>
37#include <sys/dkio.h>
38#include <sys/vtoc.h>
39#include <sys/dktp/fdisk.h>
40#include <sys/vtrace.h>
41#include <sys/efi_partition.h>
42#include <sys/cmlb.h>
43#include <sys/cmlb_impl.h>
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +053044#if defined(__i386) || defined(__amd64)
45#include <sys/fs/dv_node.h>
46#endif
cthb9ccdc52008-07-30 10:30:05 -070047#include <sys/ddi_impldefs.h>
lclee3ccda642005-10-28 23:47:40 -070048
lclee3ccda642005-10-28 23:47:40 -070049/*
50 * Driver minor node structure and data table
51 */
52struct driver_minor_data {
53 char *name;
54 minor_t minor;
55 int type;
56};
57
58static struct driver_minor_data dk_minor_data[] = {
59 {"a", 0, S_IFBLK},
60 {"b", 1, S_IFBLK},
61 {"c", 2, S_IFBLK},
62 {"d", 3, S_IFBLK},
63 {"e", 4, S_IFBLK},
64 {"f", 5, S_IFBLK},
65 {"g", 6, S_IFBLK},
66 {"h", 7, S_IFBLK},
67#if defined(_SUNOS_VTOC_16)
68 {"i", 8, S_IFBLK},
69 {"j", 9, S_IFBLK},
70 {"k", 10, S_IFBLK},
71 {"l", 11, S_IFBLK},
72 {"m", 12, S_IFBLK},
73 {"n", 13, S_IFBLK},
74 {"o", 14, S_IFBLK},
75 {"p", 15, S_IFBLK},
76#endif /* defined(_SUNOS_VTOC_16) */
77#if defined(_FIRMWARE_NEEDS_FDISK)
78 {"q", 16, S_IFBLK},
79 {"r", 17, S_IFBLK},
80 {"s", 18, S_IFBLK},
81 {"t", 19, S_IFBLK},
82 {"u", 20, S_IFBLK},
83#endif /* defined(_FIRMWARE_NEEDS_FDISK) */
84 {"a,raw", 0, S_IFCHR},
85 {"b,raw", 1, S_IFCHR},
86 {"c,raw", 2, S_IFCHR},
87 {"d,raw", 3, S_IFCHR},
88 {"e,raw", 4, S_IFCHR},
89 {"f,raw", 5, S_IFCHR},
90 {"g,raw", 6, S_IFCHR},
91 {"h,raw", 7, S_IFCHR},
92#if defined(_SUNOS_VTOC_16)
93 {"i,raw", 8, S_IFCHR},
94 {"j,raw", 9, S_IFCHR},
95 {"k,raw", 10, S_IFCHR},
96 {"l,raw", 11, S_IFCHR},
97 {"m,raw", 12, S_IFCHR},
98 {"n,raw", 13, S_IFCHR},
99 {"o,raw", 14, S_IFCHR},
100 {"p,raw", 15, S_IFCHR},
101#endif /* defined(_SUNOS_VTOC_16) */
102#if defined(_FIRMWARE_NEEDS_FDISK)
103 {"q,raw", 16, S_IFCHR},
104 {"r,raw", 17, S_IFCHR},
105 {"s,raw", 18, S_IFCHR},
106 {"t,raw", 19, S_IFCHR},
107 {"u,raw", 20, S_IFCHR},
108#endif /* defined(_FIRMWARE_NEEDS_FDISK) */
109 {0}
110};
111
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +0530112#if defined(__i386) || defined(__amd64)
113#if defined(_FIRMWARE_NEEDS_FDISK)
114static struct driver_minor_data dk_ext_minor_data[] = {
115 {"p5", 21, S_IFBLK},
116 {"p6", 22, S_IFBLK},
117 {"p7", 23, S_IFBLK},
118 {"p8", 24, S_IFBLK},
119 {"p9", 25, S_IFBLK},
120 {"p10", 26, S_IFBLK},
121 {"p11", 27, S_IFBLK},
122 {"p12", 28, S_IFBLK},
123 {"p13", 29, S_IFBLK},
124 {"p14", 30, S_IFBLK},
125 {"p15", 31, S_IFBLK},
126 {"p16", 32, S_IFBLK},
127 {"p17", 33, S_IFBLK},
128 {"p18", 34, S_IFBLK},
129 {"p19", 35, S_IFBLK},
130 {"p20", 36, S_IFBLK},
131 {"p21", 37, S_IFBLK},
132 {"p22", 38, S_IFBLK},
133 {"p23", 39, S_IFBLK},
134 {"p24", 40, S_IFBLK},
135 {"p25", 41, S_IFBLK},
136 {"p26", 42, S_IFBLK},
137 {"p27", 43, S_IFBLK},
138 {"p28", 44, S_IFBLK},
139 {"p29", 45, S_IFBLK},
140 {"p30", 46, S_IFBLK},
141 {"p31", 47, S_IFBLK},
142 {"p32", 48, S_IFBLK},
143 {"p33", 49, S_IFBLK},
144 {"p34", 50, S_IFBLK},
145 {"p35", 51, S_IFBLK},
146 {"p36", 52, S_IFBLK},
147 {"p5,raw", 21, S_IFCHR},
148 {"p6,raw", 22, S_IFCHR},
149 {"p7,raw", 23, S_IFCHR},
150 {"p8,raw", 24, S_IFCHR},
151 {"p9,raw", 25, S_IFCHR},
152 {"p10,raw", 26, S_IFCHR},
153 {"p11,raw", 27, S_IFCHR},
154 {"p12,raw", 28, S_IFCHR},
155 {"p13,raw", 29, S_IFCHR},
156 {"p14,raw", 30, S_IFCHR},
157 {"p15,raw", 31, S_IFCHR},
158 {"p16,raw", 32, S_IFCHR},
159 {"p17,raw", 33, S_IFCHR},
160 {"p18,raw", 34, S_IFCHR},
161 {"p19,raw", 35, S_IFCHR},
162 {"p20,raw", 36, S_IFCHR},
163 {"p21,raw", 37, S_IFCHR},
164 {"p22,raw", 38, S_IFCHR},
165 {"p23,raw", 39, S_IFCHR},
166 {"p24,raw", 40, S_IFCHR},
167 {"p25,raw", 41, S_IFCHR},
168 {"p26,raw", 42, S_IFCHR},
169 {"p27,raw", 43, S_IFCHR},
170 {"p28,raw", 44, S_IFCHR},
171 {"p29,raw", 45, S_IFCHR},
172 {"p30,raw", 46, S_IFCHR},
173 {"p31,raw", 47, S_IFCHR},
174 {"p32,raw", 48, S_IFCHR},
175 {"p33,raw", 49, S_IFCHR},
176 {"p34,raw", 50, S_IFCHR},
177 {"p35,raw", 51, S_IFCHR},
178 {"p36,raw", 52, S_IFCHR},
179 {0}
180};
181#endif /* defined(_FIRMWARE_NEEDS_FDISK) */
182#endif /* if defined(__i386) || defined(__amd64) */
183
lclee3ccda642005-10-28 23:47:40 -0700184static struct driver_minor_data dk_minor_data_efi[] = {
185 {"a", 0, S_IFBLK},
186 {"b", 1, S_IFBLK},
187 {"c", 2, S_IFBLK},
188 {"d", 3, S_IFBLK},
189 {"e", 4, S_IFBLK},
190 {"f", 5, S_IFBLK},
191 {"g", 6, S_IFBLK},
192 {"wd", 7, S_IFBLK},
Shidokht Yadegari7e70b432009-02-10 15:18:05 -0800193#if defined(_SUNOS_VTOC_16)
194 {"i", 8, S_IFBLK},
195 {"j", 9, S_IFBLK},
196 {"k", 10, S_IFBLK},
197 {"l", 11, S_IFBLK},
198 {"m", 12, S_IFBLK},
199 {"n", 13, S_IFBLK},
200 {"o", 14, S_IFBLK},
201 {"p", 15, S_IFBLK},
202#endif /* defined(_SUNOS_VTOC_16) */
lclee3ccda642005-10-28 23:47:40 -0700203#if defined(_FIRMWARE_NEEDS_FDISK)
204 {"q", 16, S_IFBLK},
205 {"r", 17, S_IFBLK},
206 {"s", 18, S_IFBLK},
207 {"t", 19, S_IFBLK},
208 {"u", 20, S_IFBLK},
209#endif /* defined(_FIRMWARE_NEEDS_FDISK) */
210 {"a,raw", 0, S_IFCHR},
211 {"b,raw", 1, S_IFCHR},
212 {"c,raw", 2, S_IFCHR},
213 {"d,raw", 3, S_IFCHR},
214 {"e,raw", 4, S_IFCHR},
215 {"f,raw", 5, S_IFCHR},
216 {"g,raw", 6, S_IFCHR},
217 {"wd,raw", 7, S_IFCHR},
Shidokht Yadegari7e70b432009-02-10 15:18:05 -0800218#if defined(_SUNOS_VTOC_16)
219 {"i,raw", 8, S_IFCHR},
220 {"j,raw", 9, S_IFCHR},
221 {"k,raw", 10, S_IFCHR},
222 {"l,raw", 11, S_IFCHR},
223 {"m,raw", 12, S_IFCHR},
224 {"n,raw", 13, S_IFCHR},
225 {"o,raw", 14, S_IFCHR},
226 {"p,raw", 15, S_IFCHR},
227#endif /* defined(_SUNOS_VTOC_16) */
lclee3ccda642005-10-28 23:47:40 -0700228#if defined(_FIRMWARE_NEEDS_FDISK)
229 {"q,raw", 16, S_IFCHR},
230 {"r,raw", 17, S_IFCHR},
231 {"s,raw", 18, S_IFCHR},
232 {"t,raw", 19, S_IFCHR},
233 {"u,raw", 20, S_IFCHR},
234#endif /* defined(_FIRMWARE_NEEDS_FDISK) */
235 {0}
236};
237
cthb9ccdc52008-07-30 10:30:05 -0700238/*
239 * Declare the dynamic properties implemented in prop_op(9E) implementation
240 * that we want to have show up in a di_init(3DEVINFO) device tree snapshot
241 * of drivers that call cmlb_attach().
242 */
243static i_ddi_prop_dyn_t cmlb_prop_dyn[] = {
244 {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK},
245 {"Size", DDI_PROP_TYPE_INT64, S_IFCHR},
246 {"device-nblocks", DDI_PROP_TYPE_INT64},
247 {"device-blksize", DDI_PROP_TYPE_INT},
Garrett D'Amore59d8f102013-11-17 14:26:56 -0800248 {"device-solid-state", DDI_PROP_TYPE_INT},
Yuri Pankovacb450d2017-03-06 00:19:36 +0300249 {"device-rotational", DDI_PROP_TYPE_INT},
cthb9ccdc52008-07-30 10:30:05 -0700250 {NULL}
251};
lclee3ccda642005-10-28 23:47:40 -0700252
edp06bbe1e2008-03-29 11:32:36 -0700253/*
Shidokht Yadegaric31fac72010-02-23 11:23:12 -0800254 * This implies an upper limit of 8192 GPT partitions
255 * in one transfer for GUID Partition Entry Array.
256 */
257len_t cmlb_tg_max_efi_xfer = 1024 * 1024;
258
259/*
edp06bbe1e2008-03-29 11:32:36 -0700260 * External kernel interfaces
261 */
lclee3ccda642005-10-28 23:47:40 -0700262extern struct mod_ops mod_miscops;
263
edp06bbe1e2008-03-29 11:32:36 -0700264extern int ddi_create_internal_pathname(dev_info_t *dip, char *name,
265 int spec_type, minor_t minor_num);
266
lclee3ccda642005-10-28 23:47:40 -0700267/*
268 * Global buffer and mutex for debug logging
269 */
270static char cmlb_log_buffer[1024];
271static kmutex_t cmlb_log_mutex;
272
273
shidokhte8fb11a2007-01-31 14:43:05 -0800274struct cmlb_lun *cmlb_debug_cl = NULL;
lclee3ccda642005-10-28 23:47:40 -0700275uint_t cmlb_level_mask = 0x0;
276
277int cmlb_rot_delay = 4; /* default rotational delay */
278
279static struct modlmisc modlmisc = {
280 &mod_miscops, /* Type of module */
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700281 "Common Labeling module"
lclee3ccda642005-10-28 23:47:40 -0700282};
283
284static struct modlinkage modlinkage = {
285 MODREV_1, (void *)&modlmisc, NULL
286};
287
288/* Local function prototypes */
shidokhte8fb11a2007-01-31 14:43:05 -0800289static dev_t cmlb_make_device(struct cmlb_lun *cl);
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800290static int cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid,
shidokhte8fb11a2007-01-31 14:43:05 -0800291 int flags, void *tg_cookie);
292static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity,
293 void *tg_cookie);
294static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity,
295 void *tg_cookie);
lclee3ccda642005-10-28 23:47:40 -0700296static void cmlb_swap_efi_gpt(efi_gpt_t *e);
297static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p);
298static int cmlb_validate_efi(efi_gpt_t *labp);
shidokhte8fb11a2007-01-31 14:43:05 -0800299static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags,
300 void *tg_cookie);
301static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie);
302static int cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *l, int flags);
303#if defined(_SUNOS_VTOC_8)
304static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
305#endif
306static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
307static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie);
308static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl,
309 void *tg_cookie);
310static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie);
311static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie);
312static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie);
313static int cmlb_create_minor_nodes(struct cmlb_lun *cl);
314static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie);
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800315static boolean_t cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr);
lclee3ccda642005-10-28 23:47:40 -0700316
317#if defined(__i386) || defined(__amd64)
shidokhte8fb11a2007-01-31 14:43:05 -0800318static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie);
lclee3ccda642005-10-28 23:47:40 -0700319#endif
320
321#if defined(_FIRMWARE_NEEDS_FDISK)
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800322static boolean_t cmlb_has_max_chs_vals(struct ipart *fdp);
lclee3ccda642005-10-28 23:47:40 -0700323#endif
324
325#if defined(_SUNOS_VTOC_16)
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +0800326static void cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity,
327 struct dk_geom *cl_g, void *tg_cookie);
lclee3ccda642005-10-28 23:47:40 -0700328#endif
329
shidokhte8fb11a2007-01-31 14:43:05 -0800330static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag,
331 void *tg_cookie);
332static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag);
333static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
334 void *tg_cookie);
335static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag);
336static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag,
337 void *tg_cookie);
338static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
339 int flag, void *tg_cookie);
340static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
341 void *tg_cookie);
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700342static int cmlb_dkio_get_extvtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
343 void *tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -0800344static int cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
345 int flag, void *tg_cookie);
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700346static int cmlb_dkio_set_extvtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
347 int flag, void *tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -0800348static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
349 void *tg_cookie);
350static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
351 void *tg_cookie);
352static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
353 void *tg_cookie);
lclee3ccda642005-10-28 23:47:40 -0700354
355#if defined(__i386) || defined(__amd64)
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +0530356static int cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag,
357 void *tg_cookie);
358static int cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart,
359 uint32_t start, uint32_t size);
360static int cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start,
361 void *tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -0800362static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag);
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +0800363static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag,
364 void *tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -0800365static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
lclee3ccda642005-10-28 23:47:40 -0700366 int flag);
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700367static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
368 int flag);
lclee3ccda642005-10-28 23:47:40 -0700369#endif
370
shidokhte8fb11a2007-01-31 14:43:05 -0800371static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...);
Shidokht Yadegaric31fac72010-02-23 11:23:12 -0800372static void cmlb_v_log(dev_info_t *dev, const char *label, uint_t level,
lclee3ccda642005-10-28 23:47:40 -0700373 const char *fmt, va_list ap);
Shidokht Yadegaric31fac72010-02-23 11:23:12 -0800374static void cmlb_log(dev_info_t *dev, const char *label, uint_t level,
lclee3ccda642005-10-28 23:47:40 -0700375 const char *fmt, ...);
376
377int
378_init(void)
379{
380 mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL);
381 return (mod_install(&modlinkage));
382}
383
384int
385_info(struct modinfo *modinfop)
386{
387 return (mod_info(&modlinkage, modinfop));
388}
389
390int
391_fini(void)
392{
393 int err;
394
395 if ((err = mod_remove(&modlinkage)) != 0) {
396 return (err);
397 }
398
399 mutex_destroy(&cmlb_log_mutex);
400 return (err);
401}
402
403/*
404 * cmlb_dbg is used for debugging to log additional info
405 * Level of output is controlled via cmlb_level_mask setting.
406 */
407static void
shidokhte8fb11a2007-01-31 14:43:05 -0800408cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...)
lclee3ccda642005-10-28 23:47:40 -0700409{
410 va_list ap;
411 dev_info_t *dev;
412 uint_t level_mask = 0;
413
shidokhte8fb11a2007-01-31 14:43:05 -0800414 ASSERT(cl != NULL);
415 dev = CMLB_DEVINFO(cl);
lclee3ccda642005-10-28 23:47:40 -0700416 ASSERT(dev != NULL);
417 /*
418 * Filter messages based on the global component and level masks,
shidokhte8fb11a2007-01-31 14:43:05 -0800419 * also print if cl matches the value of cmlb_debug_cl, or if
420 * cmlb_debug_cl is set to NULL.
lclee3ccda642005-10-28 23:47:40 -0700421 */
422 if (comp & CMLB_TRACE)
423 level_mask |= CMLB_LOGMASK_TRACE;
424
425 if (comp & CMLB_INFO)
426 level_mask |= CMLB_LOGMASK_INFO;
427
428 if (comp & CMLB_ERROR)
429 level_mask |= CMLB_LOGMASK_ERROR;
430
431 if ((cmlb_level_mask & level_mask) &&
shidokhte8fb11a2007-01-31 14:43:05 -0800432 ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) {
lclee3ccda642005-10-28 23:47:40 -0700433 va_start(ap, fmt);
shidokhte8fb11a2007-01-31 14:43:05 -0800434 cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap);
lclee3ccda642005-10-28 23:47:40 -0700435 va_end(ap);
436 }
437}
438
439/*
440 * cmlb_log is basically a duplicate of scsi_log. It is redefined here
441 * so that this module does not depend on scsi module.
442 */
443static void
Shidokht Yadegaric31fac72010-02-23 11:23:12 -0800444cmlb_log(dev_info_t *dev, const char *label, uint_t level, const char *fmt, ...)
lclee3ccda642005-10-28 23:47:40 -0700445{
446 va_list ap;
447
448 va_start(ap, fmt);
449 cmlb_v_log(dev, label, level, fmt, ap);
450 va_end(ap);
451}
452
453static void
Shidokht Yadegaric31fac72010-02-23 11:23:12 -0800454cmlb_v_log(dev_info_t *dev, const char *label, uint_t level, const char *fmt,
lclee3ccda642005-10-28 23:47:40 -0700455 va_list ap)
456{
457 static char name[256];
458 int log_only = 0;
459 int boot_only = 0;
460 int console_only = 0;
461
462 mutex_enter(&cmlb_log_mutex);
463
464 if (dev) {
465 if (level == CE_PANIC || level == CE_WARN ||
466 level == CE_NOTE) {
467 (void) sprintf(name, "%s (%s%d):\n",
468 ddi_pathname(dev, cmlb_log_buffer),
469 label, ddi_get_instance(dev));
470 } else {
471 name[0] = '\0';
472 }
473 } else {
474 (void) sprintf(name, "%s:", label);
475 }
476
477 (void) vsprintf(cmlb_log_buffer, fmt, ap);
478
479 switch (cmlb_log_buffer[0]) {
480 case '!':
481 log_only = 1;
482 break;
483 case '?':
484 boot_only = 1;
485 break;
486 case '^':
487 console_only = 1;
488 break;
489 }
490
491 switch (level) {
492 case CE_NOTE:
493 level = CE_CONT;
494 /* FALLTHROUGH */
495 case CE_CONT:
496 case CE_WARN:
497 case CE_PANIC:
498 if (boot_only) {
499 cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]);
500 } else if (console_only) {
501 cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]);
502 } else if (log_only) {
503 cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]);
504 } else {
505 cmn_err(level, "%s\t%s", name, cmlb_log_buffer);
506 }
507 break;
508 case CE_IGNORE:
509 break;
510 default:
511 cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer);
512 break;
513 }
514 mutex_exit(&cmlb_log_mutex);
515}
516
517
518/*
519 * cmlb_alloc_handle:
520 *
521 * Allocates a handle.
522 *
523 * Arguments:
524 * cmlbhandlep pointer to handle
525 *
526 * Notes:
527 * Allocates a handle and stores the allocated handle in the area
528 * pointed to by cmlbhandlep
529 *
530 * Context:
531 * Kernel thread only (can sleep).
532 */
533void
534cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep)
535{
shidokhte8fb11a2007-01-31 14:43:05 -0800536 struct cmlb_lun *cl;
lclee3ccda642005-10-28 23:47:40 -0700537
shidokhte8fb11a2007-01-31 14:43:05 -0800538 cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP);
lclee3ccda642005-10-28 23:47:40 -0700539 ASSERT(cmlbhandlep != NULL);
540
shidokhte8fb11a2007-01-31 14:43:05 -0800541 cl->cl_state = CMLB_INITED;
542 cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
543 mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL);
lclee3ccda642005-10-28 23:47:40 -0700544
shidokhte8fb11a2007-01-31 14:43:05 -0800545 *cmlbhandlep = (cmlb_handle_t)(cl);
lclee3ccda642005-10-28 23:47:40 -0700546}
547
548/*
549 * cmlb_free_handle
550 *
551 * Frees handle.
552 *
553 * Arguments:
554 * cmlbhandlep pointer to handle
555 */
556void
557cmlb_free_handle(cmlb_handle_t *cmlbhandlep)
558{
shidokhte8fb11a2007-01-31 14:43:05 -0800559 struct cmlb_lun *cl;
lclee3ccda642005-10-28 23:47:40 -0700560
shidokhte8fb11a2007-01-31 14:43:05 -0800561 cl = (struct cmlb_lun *)*cmlbhandlep;
562 if (cl != NULL) {
563 mutex_destroy(CMLB_MUTEX(cl));
564 kmem_free(cl, sizeof (struct cmlb_lun));
lclee3ccda642005-10-28 23:47:40 -0700565 }
566
567}
568
569/*
570 * cmlb_attach:
571 *
572 * Attach handle to device, create minor nodes for device.
573 *
574 * Arguments:
575 * devi pointer to device's dev_info structure.
576 * tgopsp pointer to array of functions cmlb can use to callback
577 * to target driver.
578 *
579 * device_type Peripheral device type as defined in
580 * scsi/generic/inquiry.h
581 *
582 * is_removable whether or not device is removable.
lclee3ccda642005-10-28 23:47:40 -0700583 *
shidokhte8fb11a2007-01-31 14:43:05 -0800584 * is_hotpluggable whether or not device is hotpluggable.
shidokhte8fb11a2007-01-31 14:43:05 -0800585 *
lclee3ccda642005-10-28 23:47:40 -0700586 * node_type minor node type (as used by ddi_create_minor_node)
587 *
588 * alter_behavior
589 * bit flags:
590 *
591 * CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create
592 * an alternate slice for the default label, if
593 * device type is DTYPE_DIRECT an architectures default
594 * label type is VTOC16.
595 * Otherwise alternate slice will no be created.
596 *
597 *
598 * CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default
599 * geometry and label for DKIOCGGEOM and DKIOCGVTOC
600 * on architecture with VTOC8 label types.
601 *
shidokhte8fb11a2007-01-31 14:43:05 -0800602 * CMLB_OFF_BY_ONE: do the workaround for legacy off-by-
603 * one bug in obtaining capacity (in sd):
604 * SCSI READ_CAPACITY command returns the LBA number of the
605 * last logical block, but sd once treated this number as
606 * disks' capacity on x86 platform. And LBAs are addressed
607 * based 0. So the last block was lost on x86 platform.
608 *
609 * Now, we remove this workaround. In order for present sd
610 * driver to work with disks which are labeled/partitioned
611 * via previous sd, we add workaround as follows:
612 *
613 * 1) Locate backup EFI label: cmlb searches the next to
614 * last
615 * block for backup EFI label. If fails, it will
616 * turn to the last block for backup EFI label;
617 *
618 * 2) Clear backup EFI label: cmlb first search the last
619 * block for backup EFI label, and will search the
620 * next to last block only if failed for the last
621 * block.
622 *
623 * 3) Calculate geometry:refer to cmlb_convert_geometry()
624 * If capacity increasing by 1 causes disks' capacity
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700625 * to cross over the limits in geometry calculation,
shidokhte8fb11a2007-01-31 14:43:05 -0800626 * geometry info will change. This will raise an issue:
627 * In case that primary VTOC label is destroyed, format
628 * commandline can restore it via backup VTOC labels.
629 * And format locates backup VTOC labels by use of
630 * geometry. So changing geometry will
631 * prevent format from finding backup VTOC labels. To
632 * eliminate this side effect for compatibility,
633 * sd uses (capacity -1) to calculate geometry;
634 *
635 * 4) 1TB disks: some important data structures use
636 * 32-bit signed long/int (for example, daddr_t),
637 * so that sd doesn't support a disk with capacity
638 * larger than 1TB on 32-bit platform. However,
639 * for exactly 1TB disk, it was treated as (1T - 512)B
640 * in the past, and could have valid Solaris
641 * partitions. To workaround this, if an exactly 1TB
642 * disk has Solaris fdisk partition, it will be allowed
643 * to work with sd.
644 *
645 *
lclee3ccda642005-10-28 23:47:40 -0700646 *
johnlev843e1982007-09-18 15:46:43 -0700647 * CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering
648 * the entire disk, if there is no valid partition info.
649 * If there is a valid Solaris partition, s0 and s2 will
650 * only cover the entire Solaris partition.
651 *
Toomas Soome406fc512015-10-23 09:36:11 +0300652 * CMLB_CREATE_P0_MINOR_NODE: create p0 node covering
653 * the entire disk. Used by lofi to ensure presence of
654 * whole disk device node in case of LOFI_MAP_FILE ioctl.
johnlev843e1982007-09-18 15:46:43 -0700655 *
lclee3ccda642005-10-28 23:47:40 -0700656 * cmlbhandle cmlb handle associated with device
657 *
shidokhte8fb11a2007-01-31 14:43:05 -0800658 * tg_cookie cookie from target driver to be passed back to target
659 * driver when we call back to it through tg_ops.
660 *
lclee3ccda642005-10-28 23:47:40 -0700661 * Notes:
662 * Assumes a default label based on capacity for non-removable devices.
663 * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
664 * for the architecture).
665 *
666 * For removable devices, default label type is assumed to be VTOC
667 * type. Create minor nodes based on a default label type.
668 * Label on the media is not validated.
669 * minor number consists of:
670 * if _SUNOS_VTOC_8 is defined
671 * lowest 3 bits is taken as partition number
672 * the rest is instance number
673 * if _SUNOS_VTOC_16 is defined
674 * lowest 6 bits is taken as partition number
675 * the rest is instance number
676 *
677 *
678 * Return values:
679 * 0 Success
680 * ENXIO creating minor nodes failed.
shidokhte8fb11a2007-01-31 14:43:05 -0800681 * EINVAL invalid arg, unsupported tg_ops version
lclee3ccda642005-10-28 23:47:40 -0700682 */
683int
684cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800685 boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
shidokhte8fb11a2007-01-31 14:43:05 -0800686 int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700687{
688
shidokhte8fb11a2007-01-31 14:43:05 -0800689 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700690 diskaddr_t cap;
691 int status;
692
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800693 ASSERT(VALID_BOOLEAN(is_removable));
694 ASSERT(VALID_BOOLEAN(is_hotpluggable));
695
shidokhte8fb11a2007-01-31 14:43:05 -0800696 if (tgopsp->tg_version < TG_DK_OPS_VERSION_1)
697 return (EINVAL);
lclee3ccda642005-10-28 23:47:40 -0700698
shidokhte8fb11a2007-01-31 14:43:05 -0800699 mutex_enter(CMLB_MUTEX(cl));
700
701 CMLB_DEVINFO(cl) = devi;
702 cl->cmlb_tg_ops = tgopsp;
703 cl->cl_device_type = device_type;
704 cl->cl_is_removable = is_removable;
705 cl->cl_is_hotpluggable = is_hotpluggable;
706 cl->cl_node_type = node_type;
707 cl->cl_sys_blocksize = DEV_BSIZE;
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800708 cl->cl_f_geometry_is_valid = B_FALSE;
shidokhte8fb11a2007-01-31 14:43:05 -0800709 cl->cl_def_labeltype = CMLB_LABEL_VTOC;
710 cl->cl_alter_behavior = alter_behavior;
711 cl->cl_reserved = -1;
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700712 cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN;
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +0530713#if defined(__i386) || defined(__amd64)
714 cl->cl_logical_drive_count = 0;
715#endif
lclee3ccda642005-10-28 23:47:40 -0700716
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800717 if (!is_removable) {
shidokhte8fb11a2007-01-31 14:43:05 -0800718 mutex_exit(CMLB_MUTEX(cl));
719 status = DK_TG_GETCAP(cl, &cap, tg_cookie);
720 mutex_enter(CMLB_MUTEX(cl));
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700721 if (status == 0 && cap > CMLB_EXTVTOC_LIMIT) {
722 /* set default EFI if > 2TB */
shidokhte8fb11a2007-01-31 14:43:05 -0800723 cl->cl_def_labeltype = CMLB_LABEL_EFI;
lclee3ccda642005-10-28 23:47:40 -0700724 }
725 }
726
727 /* create minor nodes based on default label type */
shidokhte8fb11a2007-01-31 14:43:05 -0800728 cl->cl_last_labeltype = CMLB_LABEL_UNDEF;
729 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
lclee3ccda642005-10-28 23:47:40 -0700730
shidokhte8fb11a2007-01-31 14:43:05 -0800731 if (cmlb_create_minor_nodes(cl) != 0) {
732 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700733 return (ENXIO);
734 }
735
cthb9ccdc52008-07-30 10:30:05 -0700736 /* Define the dynamic properties for devinfo spapshots. */
737 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
738
shidokhte8fb11a2007-01-31 14:43:05 -0800739 cl->cl_state = CMLB_ATTACHED;
lclee3ccda642005-10-28 23:47:40 -0700740
shidokhte8fb11a2007-01-31 14:43:05 -0800741 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700742 return (0);
743}
744
745/*
746 * cmlb_detach:
747 *
748 * Invalidate in-core labeling data and remove all minor nodes for
749 * the device associate with handle.
750 *
751 * Arguments:
752 * cmlbhandle cmlb handle associated with device.
753 *
shidokhte8fb11a2007-01-31 14:43:05 -0800754 * tg_cookie cookie from target driver to be passed back to target
755 * driver when we call back to it through tg_ops.
756 *
lclee3ccda642005-10-28 23:47:40 -0700757 */
shidokhte8fb11a2007-01-31 14:43:05 -0800758/*ARGSUSED1*/
lclee3ccda642005-10-28 23:47:40 -0700759void
shidokhte8fb11a2007-01-31 14:43:05 -0800760cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700761{
shidokhte8fb11a2007-01-31 14:43:05 -0800762 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700763
shidokhte8fb11a2007-01-31 14:43:05 -0800764 mutex_enter(CMLB_MUTEX(cl));
765 cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800766 cl->cl_f_geometry_is_valid = B_FALSE;
shidokhte8fb11a2007-01-31 14:43:05 -0800767 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
cthb9ccdc52008-07-30 10:30:05 -0700768 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
shidokhte8fb11a2007-01-31 14:43:05 -0800769 cl->cl_state = CMLB_INITED;
770 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700771}
772
773/*
774 * cmlb_validate:
775 *
776 * Validates label.
777 *
778 * Arguments
779 * cmlbhandle cmlb handle associated with device.
780 *
shidokhte8fb11a2007-01-31 14:43:05 -0800781 * flags operation flags. used for verbosity control
782 *
783 * tg_cookie cookie from target driver to be passed back to target
784 * driver when we call back to it through tg_ops.
785 *
786 *
lclee3ccda642005-10-28 23:47:40 -0700787 * Notes:
788 * If new label type is different from the current, adjust minor nodes
789 * accordingly.
790 *
791 * Return values:
792 * 0 success
793 * Note: having fdisk but no solaris partition is assumed
794 * success.
795 *
796 * ENOMEM memory allocation failed
797 * EIO i/o errors during read or get capacity
798 * EACCESS reservation conflicts
799 * EINVAL label was corrupt, or no default label was assumed
800 * ENXIO invalid handle
801 */
802int
shidokhte8fb11a2007-01-31 14:43:05 -0800803cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700804{
shidokhte8fb11a2007-01-31 14:43:05 -0800805 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700806 int rval;
807 int ret = 0;
808
809 /*
shidokhte8fb11a2007-01-31 14:43:05 -0800810 * Temp work-around checking cl for NULL since there is a bug
lclee3ccda642005-10-28 23:47:40 -0700811 * in sd_detach calling this routine from taskq_dispatch
812 * inited function.
813 */
shidokhte8fb11a2007-01-31 14:43:05 -0800814 if (cl == NULL)
lclee3ccda642005-10-28 23:47:40 -0700815 return (ENXIO);
816
shidokhte8fb11a2007-01-31 14:43:05 -0800817 mutex_enter(CMLB_MUTEX(cl));
818 if (cl->cl_state < CMLB_ATTACHED) {
819 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700820 return (ENXIO);
821 }
822
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800823 rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, B_TRUE,
shidokhte8fb11a2007-01-31 14:43:05 -0800824 flags, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -0700825
826 if (rval == ENOTSUP) {
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800827 if (cl->cl_f_geometry_is_valid) {
shidokhte8fb11a2007-01-31 14:43:05 -0800828 cl->cl_cur_labeltype = CMLB_LABEL_EFI;
lclee3ccda642005-10-28 23:47:40 -0700829 ret = 0;
830 } else {
831 ret = EINVAL;
832 }
833 } else {
834 ret = rval;
835 if (ret == 0)
shidokhte8fb11a2007-01-31 14:43:05 -0800836 cl->cl_cur_labeltype = CMLB_LABEL_VTOC;
lclee3ccda642005-10-28 23:47:40 -0700837 }
838
839 if (ret == 0)
shidokhte8fb11a2007-01-31 14:43:05 -0800840 (void) cmlb_create_minor_nodes(cl);
lclee3ccda642005-10-28 23:47:40 -0700841
shidokhte8fb11a2007-01-31 14:43:05 -0800842 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700843 return (ret);
844}
845
846/*
847 * cmlb_invalidate:
848 * Invalidate in core label data
849 *
850 * Arguments:
851 * cmlbhandle cmlb handle associated with device.
shidokhte8fb11a2007-01-31 14:43:05 -0800852 * tg_cookie cookie from target driver to be passed back to target
853 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -0700854 */
shidokhte8fb11a2007-01-31 14:43:05 -0800855/*ARGSUSED1*/
lclee3ccda642005-10-28 23:47:40 -0700856void
shidokhte8fb11a2007-01-31 14:43:05 -0800857cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700858{
shidokhte8fb11a2007-01-31 14:43:05 -0800859 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700860
shidokhte8fb11a2007-01-31 14:43:05 -0800861 if (cl == NULL)
lclee3ccda642005-10-28 23:47:40 -0700862 return;
863
shidokhte8fb11a2007-01-31 14:43:05 -0800864 mutex_enter(CMLB_MUTEX(cl));
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800865 cl->cl_f_geometry_is_valid = B_FALSE;
shidokhte8fb11a2007-01-31 14:43:05 -0800866 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700867}
868
869/*
shidokhte8fb11a2007-01-31 14:43:05 -0800870 * cmlb_is_valid
871 * Get status on whether the incore label/geom data is valid
872 *
873 * Arguments:
874 * cmlbhandle cmlb handle associated with device.
875 *
876 * Return values:
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800877 * B_TRUE if incore label/geom data is valid.
878 * B_FALSE otherwise.
shidokhte8fb11a2007-01-31 14:43:05 -0800879 *
880 */
881
882
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800883boolean_t
shidokhte8fb11a2007-01-31 14:43:05 -0800884cmlb_is_valid(cmlb_handle_t cmlbhandle)
885{
886 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
887
888 if (cmlbhandle == NULL)
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800889 return (B_FALSE);
shidokhte8fb11a2007-01-31 14:43:05 -0800890
891 return (cl->cl_f_geometry_is_valid);
892
893}
894
895
896
897/*
lclee3ccda642005-10-28 23:47:40 -0700898 * cmlb_close:
899 *
900 * Close the device, revert to a default label minor node for the device,
901 * if it is removable.
902 *
903 * Arguments:
904 * cmlbhandle cmlb handle associated with device.
905 *
shidokhte8fb11a2007-01-31 14:43:05 -0800906 * tg_cookie cookie from target driver to be passed back to target
907 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -0700908 * Return values:
909 * 0 Success
910 * ENXIO Re-creating minor node failed.
911 */
shidokhte8fb11a2007-01-31 14:43:05 -0800912/*ARGSUSED1*/
lclee3ccda642005-10-28 23:47:40 -0700913int
shidokhte8fb11a2007-01-31 14:43:05 -0800914cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700915{
shidokhte8fb11a2007-01-31 14:43:05 -0800916 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700917
shidokhte8fb11a2007-01-31 14:43:05 -0800918 mutex_enter(CMLB_MUTEX(cl));
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800919 cl->cl_f_geometry_is_valid = B_FALSE;
lclee3ccda642005-10-28 23:47:40 -0700920
921 /* revert to default minor node for this device */
shidokhte8fb11a2007-01-31 14:43:05 -0800922 if (ISREMOVABLE(cl)) {
923 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
924 (void) cmlb_create_minor_nodes(cl);
lclee3ccda642005-10-28 23:47:40 -0700925 }
926
shidokhte8fb11a2007-01-31 14:43:05 -0800927 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700928 return (0);
929}
930
931/*
932 * cmlb_get_devid_block:
933 * get the block number where device id is stored.
934 *
935 * Arguments:
936 * cmlbhandle cmlb handle associated with device.
937 * devidblockp pointer to block number.
shidokhte8fb11a2007-01-31 14:43:05 -0800938 * tg_cookie cookie from target driver to be passed back to target
939 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -0700940 *
941 * Notes:
942 * It stores the block number of device id in the area pointed to
943 * by devidblockp.
944 * with the block number of device id.
945 *
946 * Return values:
947 * 0 success
948 * EINVAL device id does not apply to current label type.
949 */
shidokhte8fb11a2007-01-31 14:43:05 -0800950/*ARGSUSED2*/
lclee3ccda642005-10-28 23:47:40 -0700951int
shidokhte8fb11a2007-01-31 14:43:05 -0800952cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp,
953 void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -0700954{
955 daddr_t spc, blk, head, cyl;
shidokhte8fb11a2007-01-31 14:43:05 -0800956 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -0700957
shidokhte8fb11a2007-01-31 14:43:05 -0800958 mutex_enter(CMLB_MUTEX(cl));
959 if (cl->cl_state < CMLB_ATTACHED) {
960 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700961 return (EINVAL);
962 }
963
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -0800964 if ((!cl->cl_f_geometry_is_valid) ||
shidokhte8fb11a2007-01-31 14:43:05 -0800965 (cl->cl_solaris_size < DK_LABEL_LOC)) {
966 mutex_exit(CMLB_MUTEX(cl));
967 return (EINVAL);
968 }
969
shidokhte8fb11a2007-01-31 14:43:05 -0800970 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) {
971 if (cl->cl_reserved != -1) {
972 blk = cl->cl_map[cl->cl_reserved].dkl_cylno;
973 } else {
974 mutex_exit(CMLB_MUTEX(cl));
975 return (EINVAL);
976 }
977 } else {
ml402625d224222008-04-29 11:20:44 -0700978 /* if the disk is unlabeled, don't write a devid to it */
Prasad Singamsetty342440e2008-09-11 18:00:50 -0700979 if (cl->cl_label_from_media != CMLB_LABEL_VTOC) {
ml402625d224222008-04-29 11:20:44 -0700980 mutex_exit(CMLB_MUTEX(cl));
981 return (EINVAL);
982 }
983
lclee3ccda642005-10-28 23:47:40 -0700984 /* this geometry doesn't allow us to write a devid */
shidokhte8fb11a2007-01-31 14:43:05 -0800985 if (cl->cl_g.dkg_acyl < 2) {
986 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -0700987 return (EINVAL);
988 }
989
990 /*
991 * Subtract 2 guarantees that the next to last cylinder
992 * is used
993 */
shidokhte8fb11a2007-01-31 14:43:05 -0800994 cyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl - 2;
995 spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect;
996 head = cl->cl_g.dkg_nhead - 1;
ml402625d224222008-04-29 11:20:44 -0700997 blk = cl->cl_solaris_offset +
998 (cyl * (spc - cl->cl_g.dkg_apc)) +
shidokhte8fb11a2007-01-31 14:43:05 -0800999 (head * cl->cl_g.dkg_nsect) + 1;
lclee3ccda642005-10-28 23:47:40 -07001000 }
shidokhte8fb11a2007-01-31 14:43:05 -08001001
lclee3ccda642005-10-28 23:47:40 -07001002 *devidblockp = blk;
shidokhte8fb11a2007-01-31 14:43:05 -08001003 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001004 return (0);
1005}
1006
1007/*
1008 * cmlb_partinfo:
1009 * Get partition info for specified partition number.
1010 *
1011 * Arguments:
1012 * cmlbhandle cmlb handle associated with device.
1013 * part partition number
1014 * nblocksp pointer to number of blocks
1015 * startblockp pointer to starting block
1016 * partnamep pointer to name of partition
1017 * tagp pointer to tag info
shidokhte8fb11a2007-01-31 14:43:05 -08001018 * tg_cookie cookie from target driver to be passed back to target
1019 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -07001020 *
1021 *
1022 * Notes:
1023 * If in-core label is not valid, this functions tries to revalidate
1024 * the label. If label is valid, it stores the total number of blocks
1025 * in this partition in the area pointed to by nblocksp, starting
1026 * block number in area pointed to by startblockp, pointer to partition
1027 * name in area pointed to by partnamep, and tag value in area
1028 * pointed by tagp.
1029 * For EFI labels, tag value will be set to 0.
1030 *
1031 * For all nblocksp, startblockp and partnamep, tagp, a value of NULL
1032 * indicates the corresponding info is not requested.
1033 *
1034 *
1035 * Return values:
1036 * 0 success
1037 * EINVAL no valid label or requested partition number is invalid.
1038 *
1039 */
1040int
1041cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
shidokhte8fb11a2007-01-31 14:43:05 -08001042 diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001043{
1044
shidokhte8fb11a2007-01-31 14:43:05 -08001045 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -07001046 int rval;
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301047#if defined(__i386) || defined(__amd64)
1048 int ext_part;
1049#endif
lclee3ccda642005-10-28 23:47:40 -07001050
shidokhte8fb11a2007-01-31 14:43:05 -08001051 ASSERT(cl != NULL);
1052 mutex_enter(CMLB_MUTEX(cl));
1053 if (cl->cl_state < CMLB_ATTACHED) {
1054 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001055 return (EINVAL);
1056 }
1057
1058 if (part < 0 || part >= MAXPART) {
1059 rval = EINVAL;
1060 } else {
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001061 if (!cl->cl_f_geometry_is_valid)
1062 (void) cmlb_validate_geometry((struct cmlb_lun *)cl,
1063 B_FALSE, 0, tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -08001064
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001065 if (((!cl->cl_f_geometry_is_valid) ||
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001066 (part < NDKMAP && cl->cl_solaris_size == 0)) &&
1067 (part != P0_RAW_DISK)) {
lclee3ccda642005-10-28 23:47:40 -07001068 rval = EINVAL;
1069 } else {
1070 if (startblockp != NULL)
shidokhte8fb11a2007-01-31 14:43:05 -08001071 *startblockp = (diskaddr_t)cl->cl_offset[part];
lclee3ccda642005-10-28 23:47:40 -07001072
1073 if (nblocksp != NULL)
1074 *nblocksp = (diskaddr_t)
shidokhte8fb11a2007-01-31 14:43:05 -08001075 cl->cl_map[part].dkl_nblk;
lclee3ccda642005-10-28 23:47:40 -07001076
1077 if (tagp != NULL)
Shidokht Yadegaric31fac72010-02-23 11:23:12 -08001078 *tagp =
1079 ((cl->cl_cur_labeltype == CMLB_LABEL_EFI) ||
1080 (part >= NDKMAP)) ? V_UNASSIGNED :
1081 cl->cl_vtoc.v_part[part].p_tag;
lclee3ccda642005-10-28 23:47:40 -07001082 rval = 0;
1083 }
1084
1085 /* consistent with behavior of sd for getting minor name */
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301086 if (partnamep != NULL) {
1087#if defined(__i386) || defined(__amd64)
1088#if defined(_FIRMWARE_NEEDS_FDISK)
1089 if (part > FDISK_P4) {
1090 ext_part = part-FDISK_P4-1;
1091 *partnamep = dk_ext_minor_data[ext_part].name;
1092 } else
1093#endif
1094#endif
lclee3ccda642005-10-28 23:47:40 -07001095 *partnamep = dk_minor_data[part].name;
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301096 }
lclee3ccda642005-10-28 23:47:40 -07001097
1098 }
1099
shidokhte8fb11a2007-01-31 14:43:05 -08001100 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001101 return (rval);
1102}
1103
yl194034af007052008-05-08 23:19:58 -07001104/*
1105 * cmlb_efi_label_capacity:
1106 * Get capacity stored in EFI disk label.
1107 *
1108 * Arguments:
1109 * cmlbhandle cmlb handle associated with device.
1110 * capacity pointer to capacity stored in EFI disk label.
1111 * tg_cookie cookie from target driver to be passed back to target
1112 * driver when we call back to it through tg_ops.
1113 *
1114 *
1115 * Notes:
1116 * If in-core label is not valid, this functions tries to revalidate
1117 * the label. If label is valid and is an EFI label, it stores the capacity
1118 * in disk label in the area pointed to by capacity.
1119 *
1120 *
1121 * Return values:
1122 * 0 success
1123 * EINVAL no valid EFI label or capacity is NULL.
1124 *
1125 */
1126int
1127cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity,
1128 void *tg_cookie)
1129{
1130 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
1131 int rval;
1132
1133 ASSERT(cl != NULL);
1134 mutex_enter(CMLB_MUTEX(cl));
1135 if (cl->cl_state < CMLB_ATTACHED) {
1136 mutex_exit(CMLB_MUTEX(cl));
1137 return (EINVAL);
1138 }
1139
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001140 if (!cl->cl_f_geometry_is_valid)
1141 (void) cmlb_validate_geometry((struct cmlb_lun *)cl, B_FALSE,
yl194034af007052008-05-08 23:19:58 -07001142 0, tg_cookie);
1143
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001144 if ((!cl->cl_f_geometry_is_valid) || (capacity == NULL) ||
yl194034af007052008-05-08 23:19:58 -07001145 (cl->cl_cur_labeltype != CMLB_LABEL_EFI)) {
1146 rval = EINVAL;
1147 } else {
1148 *capacity = (diskaddr_t)cl->cl_map[WD_NODE].dkl_nblk;
1149 rval = 0;
1150 }
1151
1152 mutex_exit(CMLB_MUTEX(cl));
1153 return (rval);
1154}
1155
shidokhte8fb11a2007-01-31 14:43:05 -08001156/* Caller should make sure Test Unit Ready succeeds before calling this. */
1157/*ARGSUSED*/
lclee3ccda642005-10-28 23:47:40 -07001158int
1159cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg,
shidokhte8fb11a2007-01-31 14:43:05 -08001160 int flag, cred_t *cred_p, int *rval_p, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001161{
1162
1163 int err;
shidokhte8fb11a2007-01-31 14:43:05 -08001164 struct cmlb_lun *cl;
lclee3ccda642005-10-28 23:47:40 -07001165
shidokhte8fb11a2007-01-31 14:43:05 -08001166 cl = (struct cmlb_lun *)cmlbhandle;
lclee3ccda642005-10-28 23:47:40 -07001167
shidokhte8fb11a2007-01-31 14:43:05 -08001168 ASSERT(cl != NULL);
lclee3ccda642005-10-28 23:47:40 -07001169
shidokhte8fb11a2007-01-31 14:43:05 -08001170 mutex_enter(CMLB_MUTEX(cl));
1171 if (cl->cl_state < CMLB_ATTACHED) {
1172 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001173 return (EIO);
1174 }
1175
lclee3ccda642005-10-28 23:47:40 -07001176 switch (cmd) {
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001177 case DKIOCSEXTVTOC:
shidokhte8fb11a2007-01-31 14:43:05 -08001178 case DKIOCSGEOM:
lclee3ccda642005-10-28 23:47:40 -07001179 case DKIOCSETEFI:
1180 case DKIOCSMBOOT:
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301181#if defined(__i386) || defined(__amd64)
1182 case DKIOCSETEXTPART:
1183#endif
lclee3ccda642005-10-28 23:47:40 -07001184 break;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001185 case DKIOCSVTOC:
1186#if defined(__i386) || defined(__amd64)
1187 case DKIOCPARTINFO:
1188#endif
1189 if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
1190 mutex_exit(CMLB_MUTEX(cl));
1191 return (EOVERFLOW);
1192 }
1193 break;
lclee3ccda642005-10-28 23:47:40 -07001194 default:
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001195 (void) cmlb_validate_geometry(cl, 1, CMLB_SILENT,
shidokhtadc076a2007-03-27 11:00:42 -07001196 tg_cookie);
shidokhte8fb11a2007-01-31 14:43:05 -08001197
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001198 switch (cmd) {
1199 case DKIOCGVTOC:
1200 case DKIOCGAPART:
1201 case DKIOCSAPART:
shidokhte8fb11a2007-01-31 14:43:05 -08001202
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001203 if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
1204 /* GPT label on disk */
1205 mutex_exit(CMLB_MUTEX(cl));
1206 return (ENOTSUP);
1207 } else if
1208 (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
1209 mutex_exit(CMLB_MUTEX(cl));
1210 return (EOVERFLOW);
1211 }
1212 break;
shidokhte8fb11a2007-01-31 14:43:05 -08001213
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001214 case DKIOCGGEOM:
1215 if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
1216 /* GPT label on disk */
shidokhte8fb11a2007-01-31 14:43:05 -08001217 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001218 return (ENOTSUP);
1219 }
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001220 break;
1221 default:
1222 break;
lclee3ccda642005-10-28 23:47:40 -07001223 }
lclee3ccda642005-10-28 23:47:40 -07001224 }
1225
shidokhte8fb11a2007-01-31 14:43:05 -08001226 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001227
1228 switch (cmd) {
1229 case DKIOCGGEOM:
shidokhte8fb11a2007-01-31 14:43:05 -08001230 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n");
1231 err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001232 break;
1233
1234 case DKIOCSGEOM:
shidokhte8fb11a2007-01-31 14:43:05 -08001235 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n");
1236 err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag);
lclee3ccda642005-10-28 23:47:40 -07001237 break;
1238
1239 case DKIOCGAPART:
shidokhte8fb11a2007-01-31 14:43:05 -08001240 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n");
1241 err = cmlb_dkio_get_partition(cl, (caddr_t)arg,
1242 flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001243 break;
1244
1245 case DKIOCSAPART:
shidokhte8fb11a2007-01-31 14:43:05 -08001246 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n");
1247 err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag);
lclee3ccda642005-10-28 23:47:40 -07001248 break;
1249
1250 case DKIOCGVTOC:
shidokhte8fb11a2007-01-31 14:43:05 -08001251 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
1252 err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001253 break;
1254
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001255 case DKIOCGEXTVTOC:
1256 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
1257 err = cmlb_dkio_get_extvtoc(cl, (caddr_t)arg, flag, tg_cookie);
1258 break;
1259
lclee3ccda642005-10-28 23:47:40 -07001260 case DKIOCGETEFI:
shidokhte8fb11a2007-01-31 14:43:05 -08001261 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n");
1262 err = cmlb_dkio_get_efi(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001263 break;
1264
1265 case DKIOCPARTITION:
shidokhte8fb11a2007-01-31 14:43:05 -08001266 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTITION\n");
1267 err = cmlb_dkio_partition(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001268 break;
1269
1270 case DKIOCSVTOC:
shidokhte8fb11a2007-01-31 14:43:05 -08001271 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n");
1272 err = cmlb_dkio_set_vtoc(cl, dev, (caddr_t)arg, flag,
1273 tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001274 break;
1275
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001276 case DKIOCSEXTVTOC:
1277 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n");
1278 err = cmlb_dkio_set_extvtoc(cl, dev, (caddr_t)arg, flag,
1279 tg_cookie);
1280 break;
1281
lclee3ccda642005-10-28 23:47:40 -07001282 case DKIOCSETEFI:
shidokhte8fb11a2007-01-31 14:43:05 -08001283 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEFI\n");
1284 err = cmlb_dkio_set_efi(cl, dev, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001285 break;
1286
1287 case DKIOCGMBOOT:
shidokhte8fb11a2007-01-31 14:43:05 -08001288 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGMBOOT\n");
1289 err = cmlb_dkio_get_mboot(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001290 break;
1291
1292 case DKIOCSMBOOT:
shidokhte8fb11a2007-01-31 14:43:05 -08001293 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSMBOOT\n");
1294 err = cmlb_dkio_set_mboot(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001295 break;
1296 case DKIOCG_PHYGEOM:
shidokhte8fb11a2007-01-31 14:43:05 -08001297 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n");
lclee3ccda642005-10-28 23:47:40 -07001298#if defined(__i386) || defined(__amd64)
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001299 err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001300#else
1301 err = ENOTTY;
1302#endif
1303 break;
1304 case DKIOCG_VIRTGEOM:
shidokhte8fb11a2007-01-31 14:43:05 -08001305 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_VIRTGEOM\n");
lclee3ccda642005-10-28 23:47:40 -07001306#if defined(__i386) || defined(__amd64)
shidokhte8fb11a2007-01-31 14:43:05 -08001307 err = cmlb_dkio_get_virtgeom(cl, (caddr_t)arg, flag);
lclee3ccda642005-10-28 23:47:40 -07001308#else
1309 err = ENOTTY;
1310#endif
1311 break;
1312 case DKIOCPARTINFO:
shidokhte8fb11a2007-01-31 14:43:05 -08001313 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO");
lclee3ccda642005-10-28 23:47:40 -07001314#if defined(__i386) || defined(__amd64)
shidokhte8fb11a2007-01-31 14:43:05 -08001315 err = cmlb_dkio_partinfo(cl, dev, (caddr_t)arg, flag);
lclee3ccda642005-10-28 23:47:40 -07001316#else
1317 err = ENOTTY;
1318#endif
1319 break;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001320 case DKIOCEXTPARTINFO:
1321 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO");
1322#if defined(__i386) || defined(__amd64)
1323 err = cmlb_dkio_extpartinfo(cl, dev, (caddr_t)arg, flag);
1324#else
1325 err = ENOTTY;
1326#endif
1327 break;
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301328#if defined(__i386) || defined(__amd64)
1329 case DKIOCSETEXTPART:
1330 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEXTPART");
1331 err = cmlb_dkio_set_ext_part(cl, (caddr_t)arg, flag, tg_cookie);
1332 break;
1333#endif
lclee3ccda642005-10-28 23:47:40 -07001334 default:
1335 err = ENOTTY;
1336
1337 }
cthb9ccdc52008-07-30 10:30:05 -07001338
1339 /*
1340 * An ioctl that succeeds and changed ('set') size(9P) information
1341 * needs to invalidate the cached devinfo snapshot to avoid having
1342 * old information being returned in a snapshots.
1343 *
1344 * NB: When available, call ddi_change_minor_node() to clear
1345 * SSIZEVALID in specfs vnodes via spec_size_invalidate().
1346 */
1347 if (err == 0) {
1348 switch (cmd) {
1349 case DKIOCSGEOM:
1350 case DKIOCSAPART:
1351 case DKIOCSVTOC:
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001352 case DKIOCSEXTVTOC:
cthb9ccdc52008-07-30 10:30:05 -07001353 case DKIOCSETEFI:
1354 i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl),
1355 i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl)));
1356 }
1357 }
lclee3ccda642005-10-28 23:47:40 -07001358 return (err);
1359}
1360
1361dev_t
shidokhte8fb11a2007-01-31 14:43:05 -08001362cmlb_make_device(struct cmlb_lun *cl)
lclee3ccda642005-10-28 23:47:40 -07001363{
Toomas Soome406fc512015-10-23 09:36:11 +03001364 if (cl->cl_alter_behavior & CMLB_CREATE_P0_MINOR_NODE) {
1365 return (makedevice(ddi_driver_major(CMLB_DEVINFO(cl)),
1366 ddi_get_instance(
1367 CMLB_DEVINFO(cl)) << CMLBUNIT_FORCE_P0_SHIFT));
1368 } else {
1369 return (makedevice(ddi_driver_major(CMLB_DEVINFO(cl)),
1370 ddi_get_instance(CMLB_DEVINFO(cl)) << CMLBUNIT_SHIFT));
1371 }
lclee3ccda642005-10-28 23:47:40 -07001372}
1373
1374/*
1375 * Function: cmlb_check_update_blockcount
1376 *
1377 * Description: If current capacity value is invalid, obtains the
1378 * current capacity from target driver.
1379 *
1380 * Return Code: 0 success
1381 * EIO failure
1382 */
1383static int
shidokhte8fb11a2007-01-31 14:43:05 -08001384cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001385{
1386 int status;
1387 diskaddr_t capacity;
shidokhte8fb11a2007-01-31 14:43:05 -08001388 uint32_t lbasize;
lclee3ccda642005-10-28 23:47:40 -07001389
shidokhte8fb11a2007-01-31 14:43:05 -08001390 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
lclee3ccda642005-10-28 23:47:40 -07001391
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001392 if (cl->cl_f_geometry_is_valid)
lclee3ccda642005-10-28 23:47:40 -07001393 return (0);
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001394
1395 mutex_exit(CMLB_MUTEX(cl));
1396 status = DK_TG_GETCAP(cl, &capacity, tg_cookie);
1397 if (status != 0) {
1398 mutex_enter(CMLB_MUTEX(cl));
1399 return (EIO);
1400 }
1401
1402 status = DK_TG_GETBLOCKSIZE(cl, &lbasize, tg_cookie);
1403 mutex_enter(CMLB_MUTEX(cl));
1404 if (status != 0)
1405 return (EIO);
1406
1407 if ((capacity != 0) && (lbasize != 0)) {
1408 cl->cl_blockcount = capacity;
1409 cl->cl_tgt_blocksize = lbasize;
yu, larry liu - Sun Microsystems - Beijing China65908c72009-06-17 19:20:05 +08001410 if (!cl->cl_is_removable) {
1411 cl->cl_sys_blocksize = lbasize;
1412 }
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001413 return (0);
1414 } else {
1415 return (EIO);
1416 }
lclee3ccda642005-10-28 23:47:40 -07001417}
1418
edp06bbe1e2008-03-29 11:32:36 -07001419static int
1420cmlb_create_minor(dev_info_t *dip, char *name, int spec_type,
1421 minor_t minor_num, char *node_type, int flag, boolean_t internal)
1422{
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001423 ASSERT(VALID_BOOLEAN(internal));
1424
edp06bbe1e2008-03-29 11:32:36 -07001425 if (internal)
1426 return (ddi_create_internal_pathname(dip,
1427 name, spec_type, minor_num));
1428 else
1429 return (ddi_create_minor_node(dip,
1430 name, spec_type, minor_num, node_type, flag));
1431}
1432
lclee3ccda642005-10-28 23:47:40 -07001433/*
1434 * Function: cmlb_create_minor_nodes
1435 *
1436 * Description: Create or adjust the minor device nodes for the instance.
1437 * Minor nodes are created based on default label type,
1438 * current label type and last label type we created
1439 * minor nodes based on.
1440 *
1441 *
shidokhte8fb11a2007-01-31 14:43:05 -08001442 * Arguments: cl - driver soft state (unit) structure
lclee3ccda642005-10-28 23:47:40 -07001443 *
1444 * Return Code: 0 success
1445 * ENXIO failure.
1446 *
1447 * Context: Kernel thread context
1448 */
1449static int
shidokhte8fb11a2007-01-31 14:43:05 -08001450cmlb_create_minor_nodes(struct cmlb_lun *cl)
lclee3ccda642005-10-28 23:47:40 -07001451{
1452 struct driver_minor_data *dmdp;
Toomas Soome406fc512015-10-23 09:36:11 +03001453 int instance, shift;
lclee3ccda642005-10-28 23:47:40 -07001454 char name[48];
1455 cmlb_label_t newlabeltype;
edp06bbe1e2008-03-29 11:32:36 -07001456 boolean_t internal;
lclee3ccda642005-10-28 23:47:40 -07001457
shidokhte8fb11a2007-01-31 14:43:05 -08001458 ASSERT(cl != NULL);
1459 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
lclee3ccda642005-10-28 23:47:40 -07001460
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001461 internal = VOID2BOOLEAN(
1462 (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0);
lclee3ccda642005-10-28 23:47:40 -07001463
Toomas Soome406fc512015-10-23 09:36:11 +03001464 if (cl->cl_alter_behavior & CMLB_CREATE_P0_MINOR_NODE)
1465 shift = CMLBUNIT_FORCE_P0_SHIFT;
1466 else
1467 shift = CMLBUNIT_SHIFT;
1468
lclee3ccda642005-10-28 23:47:40 -07001469 /* check the most common case */
shidokhte8fb11a2007-01-31 14:43:05 -08001470 if (cl->cl_cur_labeltype != CMLB_LABEL_UNDEF &&
1471 cl->cl_last_labeltype == cl->cl_cur_labeltype) {
lclee3ccda642005-10-28 23:47:40 -07001472 /* do nothing */
1473 return (0);
1474 }
1475
shidokhte8fb11a2007-01-31 14:43:05 -08001476 if (cl->cl_def_labeltype == CMLB_LABEL_UNDEF) {
lclee3ccda642005-10-28 23:47:40 -07001477 /* we should never get here */
1478 return (ENXIO);
1479 }
1480
shidokhte8fb11a2007-01-31 14:43:05 -08001481 if (cl->cl_last_labeltype == CMLB_LABEL_UNDEF) {
lclee3ccda642005-10-28 23:47:40 -07001482 /* first time during attach */
shidokhte8fb11a2007-01-31 14:43:05 -08001483 newlabeltype = cl->cl_def_labeltype;
lclee3ccda642005-10-28 23:47:40 -07001484
shidokhte8fb11a2007-01-31 14:43:05 -08001485 instance = ddi_get_instance(CMLB_DEVINFO(cl));
lclee3ccda642005-10-28 23:47:40 -07001486
1487 /* Create all the minor nodes for this target. */
1488 dmdp = (newlabeltype == CMLB_LABEL_EFI) ? dk_minor_data_efi :
1489 dk_minor_data;
1490 while (dmdp->name != NULL) {
1491
1492 (void) sprintf(name, "%s", dmdp->name);
1493
edp06bbe1e2008-03-29 11:32:36 -07001494 if (cmlb_create_minor(CMLB_DEVINFO(cl), name,
lclee3ccda642005-10-28 23:47:40 -07001495 dmdp->type,
Toomas Soome406fc512015-10-23 09:36:11 +03001496 (instance << shift) | dmdp->minor,
edp06bbe1e2008-03-29 11:32:36 -07001497 cl->cl_node_type, NULL, internal) == DDI_FAILURE) {
lclee3ccda642005-10-28 23:47:40 -07001498 /*
1499 * Clean up any nodes that may have been
1500 * created, in case this fails in the middle
1501 * of the loop.
1502 */
shidokhte8fb11a2007-01-31 14:43:05 -08001503 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
lclee3ccda642005-10-28 23:47:40 -07001504 return (ENXIO);
1505 }
1506 dmdp++;
1507 }
shidokhte8fb11a2007-01-31 14:43:05 -08001508 cl->cl_last_labeltype = newlabeltype;
Toomas Soome406fc512015-10-23 09:36:11 +03001509#if defined(_SUNOS_VTOC_8)
1510 /*
1511 * "emulate" p0 device for sparc, used by lofi
1512 */
1513 if (cl->cl_alter_behavior & CMLB_CREATE_P0_MINOR_NODE) {
1514 if (cmlb_create_minor(CMLB_DEVINFO(cl), "q", S_IFBLK,
1515 (instance << CMLBUNIT_FORCE_P0_SHIFT) | P0_RAW_DISK,
1516 cl->cl_node_type, NULL, internal) == DDI_FAILURE) {
1517 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
1518 return (ENXIO);
1519 }
1520
1521 if (cmlb_create_minor(CMLB_DEVINFO(cl), "q,raw",
1522 S_IFCHR,
1523 (instance << CMLBUNIT_FORCE_P0_SHIFT) | P0_RAW_DISK,
1524 cl->cl_node_type, NULL, internal) == DDI_FAILURE) {
1525 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
1526 return (ENXIO);
1527 }
1528 }
1529#endif /* defined(_SUNOS_VTOC_8) */
lclee3ccda642005-10-28 23:47:40 -07001530 return (0);
1531 }
1532
1533 /* Not first time */
shidokhte8fb11a2007-01-31 14:43:05 -08001534 if (cl->cl_cur_labeltype == CMLB_LABEL_UNDEF) {
1535 if (cl->cl_last_labeltype != cl->cl_def_labeltype) {
lclee3ccda642005-10-28 23:47:40 -07001536 /* close time, revert to default. */
shidokhte8fb11a2007-01-31 14:43:05 -08001537 newlabeltype = cl->cl_def_labeltype;
lclee3ccda642005-10-28 23:47:40 -07001538 } else {
1539 /*
1540 * do nothing since the type for which we last created
1541 * nodes matches the default
1542 */
1543 return (0);
1544 }
1545 } else {
shidokhte8fb11a2007-01-31 14:43:05 -08001546 if (cl->cl_cur_labeltype != cl->cl_last_labeltype) {
lclee3ccda642005-10-28 23:47:40 -07001547 /* We are not closing, use current label type */
shidokhte8fb11a2007-01-31 14:43:05 -08001548 newlabeltype = cl->cl_cur_labeltype;
lclee3ccda642005-10-28 23:47:40 -07001549 } else {
1550 /*
1551 * do nothing since the type for which we last created
1552 * nodes matches the current label type
1553 */
1554 return (0);
1555 }
1556 }
1557
shidokhte8fb11a2007-01-31 14:43:05 -08001558 instance = ddi_get_instance(CMLB_DEVINFO(cl));
lclee3ccda642005-10-28 23:47:40 -07001559
1560 /*
1561 * Currently we only fix up the s7 node when we are switching
1562 * label types from or to EFI. This is consistent with
1563 * current behavior of sd.
1564 */
1565 if (newlabeltype == CMLB_LABEL_EFI &&
shidokhte8fb11a2007-01-31 14:43:05 -08001566 cl->cl_last_labeltype != CMLB_LABEL_EFI) {
lclee3ccda642005-10-28 23:47:40 -07001567 /* from vtoc to EFI */
shidokhte8fb11a2007-01-31 14:43:05 -08001568 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h");
1569 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw");
edp06bbe1e2008-03-29 11:32:36 -07001570 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd",
Toomas Soome406fc512015-10-23 09:36:11 +03001571 S_IFBLK, (instance << shift) | WD_NODE,
edp06bbe1e2008-03-29 11:32:36 -07001572 cl->cl_node_type, NULL, internal);
1573 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw",
Toomas Soome406fc512015-10-23 09:36:11 +03001574 S_IFCHR, (instance << shift) | WD_NODE,
edp06bbe1e2008-03-29 11:32:36 -07001575 cl->cl_node_type, NULL, internal);
lclee3ccda642005-10-28 23:47:40 -07001576 } else {
1577 /* from efi to vtoc */
shidokhte8fb11a2007-01-31 14:43:05 -08001578 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd");
1579 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw");
edp06bbe1e2008-03-29 11:32:36 -07001580 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h",
Toomas Soome406fc512015-10-23 09:36:11 +03001581 S_IFBLK, (instance << shift) | WD_NODE,
edp06bbe1e2008-03-29 11:32:36 -07001582 cl->cl_node_type, NULL, internal);
1583 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw",
Toomas Soome406fc512015-10-23 09:36:11 +03001584 S_IFCHR, (instance << shift) | WD_NODE,
edp06bbe1e2008-03-29 11:32:36 -07001585 cl->cl_node_type, NULL, internal);
lclee3ccda642005-10-28 23:47:40 -07001586 }
1587
shidokhte8fb11a2007-01-31 14:43:05 -08001588 cl->cl_last_labeltype = newlabeltype;
lclee3ccda642005-10-28 23:47:40 -07001589 return (0);
1590}
1591
1592/*
1593 * Function: cmlb_validate_geometry
1594 *
1595 * Description: Read the label from the disk (if present). Update the unit's
1596 * geometry and vtoc information from the data in the label.
1597 * Verify that the label is valid.
1598 *
shidokhte8fb11a2007-01-31 14:43:05 -08001599 * Arguments:
1600 * cl driver soft state (unit) structure
1601 *
1602 * forcerevalid force revalidation even if we are already valid.
1603 * flags operation flags from target driver. Used for verbosity
1604 * control at this time.
1605 * tg_cookie cookie from target driver to be passed back to target
1606 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -07001607 *
1608 * Return Code: 0 - Successful completion
shidokhte8fb11a2007-01-31 14:43:05 -08001609 * EINVAL - Invalid value in cl->cl_tgt_blocksize or
1610 * cl->cl_blockcount; or label on disk is corrupted
lclee3ccda642005-10-28 23:47:40 -07001611 * or unreadable.
1612 * EACCES - Reservation conflict at the device.
1613 * ENOMEM - Resource allocation error
1614 * ENOTSUP - geometry not applicable
1615 *
1616 * Context: Kernel thread only (can sleep).
1617 */
1618static int
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001619cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid, int flags,
shidokhte8fb11a2007-01-31 14:43:05 -08001620 void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001621{
1622 int label_error = 0;
1623 diskaddr_t capacity;
1624 int count;
1625
shidokhte8fb11a2007-01-31 14:43:05 -08001626 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001627 ASSERT(VALID_BOOLEAN(forcerevalid));
lclee3ccda642005-10-28 23:47:40 -07001628
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001629 if ((cl->cl_f_geometry_is_valid) && (!forcerevalid)) {
shidokhte8fb11a2007-01-31 14:43:05 -08001630 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI)
lclee3ccda642005-10-28 23:47:40 -07001631 return (ENOTSUP);
1632 return (0);
1633 }
1634
shidokhte8fb11a2007-01-31 14:43:05 -08001635 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0)
lclee3ccda642005-10-28 23:47:40 -07001636 return (EIO);
1637
shidokhte8fb11a2007-01-31 14:43:05 -08001638 capacity = cl->cl_blockcount;
lclee3ccda642005-10-28 23:47:40 -07001639
lclee3ccda642005-10-28 23:47:40 -07001640 /*
1641 * Set up the "whole disk" fdisk partition; this should always
1642 * exist, regardless of whether the disk contains an fdisk table
1643 * or vtoc.
1644 */
shidokhte8fb11a2007-01-31 14:43:05 -08001645 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001646 cl->cl_offset[P0_RAW_DISK] = 0;
lclee3ccda642005-10-28 23:47:40 -07001647 /*
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001648 * note if capacity > int32_max(1TB) we are in 64bit environment
1649 * so no truncation happens
lclee3ccda642005-10-28 23:47:40 -07001650 */
shidokhte8fb11a2007-01-31 14:43:05 -08001651 cl->cl_map[P0_RAW_DISK].dkl_nblk = capacity;
Toomas Soome406fc512015-10-23 09:36:11 +03001652
lclee3ccda642005-10-28 23:47:40 -07001653 /*
1654 * Refresh the logical and physical geometry caches.
1655 * (data from MODE SENSE format/rigid disk geometry pages,
1656 * and scsi_ifgetcap("geometry").
1657 */
shidokhte8fb11a2007-01-31 14:43:05 -08001658 cmlb_resync_geom_caches(cl, capacity, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001659
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001660 cl->cl_label_from_media = CMLB_LABEL_UNDEF;
shidokhte8fb11a2007-01-31 14:43:05 -08001661 label_error = cmlb_use_efi(cl, capacity, flags, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001662 if (label_error == 0) {
1663
1664 /* found a valid EFI label */
shidokhte8fb11a2007-01-31 14:43:05 -08001665 cmlb_dbg(CMLB_TRACE, cl,
lclee3ccda642005-10-28 23:47:40 -07001666 "cmlb_validate_geometry: found EFI label\n");
1667 /*
1668 * solaris_size and geometry_is_valid are set in
1669 * cmlb_use_efi
1670 */
1671 return (ENOTSUP);
1672 }
1673
1674 /* NO EFI label found */
1675
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001676 if (capacity > CMLB_EXTVTOC_LIMIT) {
lclee3ccda642005-10-28 23:47:40 -07001677 if (label_error == ESRCH) {
1678 /*
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001679 * they've configured a LUN over 2TB, but used
lclee3ccda642005-10-28 23:47:40 -07001680 * format.dat to restrict format's view of the
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001681 * capacity to be under 2TB in some earlier Solaris
1682 * release.
lclee3ccda642005-10-28 23:47:40 -07001683 */
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001684 /* i.e > 2TB with a VTOC < 2TB */
1685 if (!(flags & CMLB_SILENT) &&
1686 (cl->cl_msglog_flag & CMLB_ALLOW_2TB_WARN)) {
lclee3ccda642005-10-28 23:47:40 -07001687
shidokhte8fb11a2007-01-31 14:43:05 -08001688 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl),
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001689 CE_NOTE, "!Disk (%s%d) is limited to 2 TB "
1690 "due to VTOC label. To use the full "
1691 "capacity of the disk, use format(1M) to "
1692 "relabel the disk with EFI/GPT label.\n",
1693 CMLB_LABEL(cl),
1694 ddi_get_instance(CMLB_DEVINFO(cl)));
1695
1696 cl->cl_msglog_flag &= ~CMLB_ALLOW_2TB_WARN;
shidokhte8fb11a2007-01-31 14:43:05 -08001697 }
lclee3ccda642005-10-28 23:47:40 -07001698 } else {
shidokhte8fb11a2007-01-31 14:43:05 -08001699 return (ENOTSUP);
lclee3ccda642005-10-28 23:47:40 -07001700 }
1701 }
1702
1703 label_error = 0;
1704
1705 /*
1706 * at this point it is either labeled with a VTOC or it is
shidokhte8fb11a2007-01-31 14:43:05 -08001707 * under 1TB (<= 1TB actually for off-by-1)
lclee3ccda642005-10-28 23:47:40 -07001708 */
1709
1710 /*
shidokhte8fb11a2007-01-31 14:43:05 -08001711 * Only DIRECT ACCESS devices will have Scl labels.
1712 * CD's supposedly have a Scl label, too
lclee3ccda642005-10-28 23:47:40 -07001713 */
shidokhte8fb11a2007-01-31 14:43:05 -08001714 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) {
lclee3ccda642005-10-28 23:47:40 -07001715 struct dk_label *dkl;
1716 offset_t label_addr;
1717 int rval;
1718 size_t buffer_size;
1719
1720 /*
shidokhte8fb11a2007-01-31 14:43:05 -08001721 * Note: This will set up cl->cl_solaris_size and
1722 * cl->cl_solaris_offset.
lclee3ccda642005-10-28 23:47:40 -07001723 */
shidokhte8fb11a2007-01-31 14:43:05 -08001724 rval = cmlb_read_fdisk(cl, capacity, tg_cookie);
1725 if ((rval != 0) && !ISCD(cl)) {
1726 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
lclee3ccda642005-10-28 23:47:40 -07001727 return (rval);
1728 }
1729
shidokhte8fb11a2007-01-31 14:43:05 -08001730 if (cl->cl_solaris_size <= DK_LABEL_LOC) {
lclee3ccda642005-10-28 23:47:40 -07001731 /*
1732 * Found fdisk table but no Solaris partition entry,
1733 * so don't call cmlb_uselabel() and don't create
1734 * a default label.
1735 */
1736 label_error = 0;
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001737 cl->cl_f_geometry_is_valid = B_TRUE;
lclee3ccda642005-10-28 23:47:40 -07001738 goto no_solaris_partition;
1739 }
1740
shidokhte8fb11a2007-01-31 14:43:05 -08001741 label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC);
1742
yu, larry liu - Sun Microsystems - Beijing China65908c72009-06-17 19:20:05 +08001743 buffer_size = cl->cl_sys_blocksize;
lclee3ccda642005-10-28 23:47:40 -07001744
shidokhte8fb11a2007-01-31 14:43:05 -08001745 cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: "
lclee3ccda642005-10-28 23:47:40 -07001746 "label_addr: 0x%x allocation size: 0x%x\n",
1747 label_addr, buffer_size);
1748
1749 if ((dkl = kmem_zalloc(buffer_size, KM_NOSLEEP)) == NULL)
1750 return (ENOMEM);
1751
shidokhte8fb11a2007-01-31 14:43:05 -08001752 mutex_exit(CMLB_MUTEX(cl));
1753 rval = DK_TG_READ(cl, dkl, label_addr, buffer_size, tg_cookie);
1754 mutex_enter(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001755
1756 switch (rval) {
1757 case 0:
1758 /*
1759 * cmlb_uselabel will establish that the geometry
1760 * is valid.
1761 */
shidokhte8fb11a2007-01-31 14:43:05 -08001762 if (cmlb_uselabel(cl,
1763 (struct dk_label *)(uintptr_t)dkl, flags) !=
lclee3ccda642005-10-28 23:47:40 -07001764 CMLB_LABEL_IS_VALID) {
1765 label_error = EINVAL;
1766 } else
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001767 cl->cl_label_from_media = CMLB_LABEL_VTOC;
lclee3ccda642005-10-28 23:47:40 -07001768 break;
1769 case EACCES:
1770 label_error = EACCES;
1771 break;
1772 default:
1773 label_error = EINVAL;
1774 break;
1775 }
1776
1777 kmem_free(dkl, buffer_size);
1778 }
1779
1780 /*
1781 * If a valid label was not found, AND if no reservation conflict
1782 * was detected, then go ahead and create a default label (4069506).
1783 *
1784 * Note: currently, for VTOC_8 devices, the default label is created
shidokhte8fb11a2007-01-31 14:43:05 -08001785 * for removables and hotpluggables only. For VTOC_16 devices, the
1786 * default label will be created for all devices.
lclee3ccda642005-10-28 23:47:40 -07001787 * (see cmlb_build_default_label)
1788 */
1789#if defined(_SUNOS_VTOC_8)
shidokhte8fb11a2007-01-31 14:43:05 -08001790 if ((ISREMOVABLE(cl) || ISHOTPLUGGABLE(cl)) &&
1791 (label_error != EACCES)) {
lclee3ccda642005-10-28 23:47:40 -07001792#elif defined(_SUNOS_VTOC_16)
1793 if (label_error != EACCES) {
1794#endif
Edward Pilatowicz7f0b8302008-11-17 14:55:44 -08001795 if (!cl->cl_f_geometry_is_valid) {
shidokhte8fb11a2007-01-31 14:43:05 -08001796 cmlb_build_default_label(cl, tg_cookie);
lclee3ccda642005-10-28 23:47:40 -07001797 }
1798 label_error = 0;
1799 }
1800
1801no_solaris_partition:
1802
1803#if defined(_SUNOS_VTOC_16)
1804 /*
1805 * If we have valid geometry, set up the remaining fdisk partitions.
1806 * Note that dkl_cylno is not used for the fdisk map entries, so
1807 * we set it to an entirely bogus value.
1808 */
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05301809 for (count = 0; count < FDISK_PARTS; count++) {
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001810 cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT16_MAX;
shidokhte8fb11a2007-01-31 14:43:05 -08001811 cl->cl_map[FDISK_P1 + count].dkl_nblk =
1812 cl->cl_fmap[count].fmap_nblk;
lclee3ccda642005-10-28 23:47:40 -07001813
shidokhte8fb11a2007-01-31 14:43:05 -08001814 cl->cl_offset[FDISK_P1 + count] =
1815 cl->cl_fmap[count].fmap_start;
lclee3ccda642005-10-28 23:47:40 -07001816 }
1817#endif
1818
1819 for (count = 0; count < NDKMAP; count++) {
1820#if defined(_SUNOS_VTOC_8)
shidokhte8fb11a2007-01-31 14:43:05 -08001821 struct dk_map *lp = &cl->cl_map[count];
1822 cl->cl_offset[count] =
1823 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno;
lclee3ccda642005-10-28 23:47:40 -07001824#elif defined(_SUNOS_VTOC_16)
shidokhte8fb11a2007-01-31 14:43:05 -08001825 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count];
lclee3ccda642005-10-28 23:47:40 -07001826
shidokhte8fb11a2007-01-31 14:43:05 -08001827 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset;
lclee3ccda642005-10-28 23:47:40 -07001828#else
1829#error "No VTOC format defined."
1830#endif
1831 }
1832
1833 return (label_error);
1834}
1835
1836#if defined(_SUNOS_VTOC_16)
1837/*
lclee3ccda642005-10-28 23:47:40 -07001838 * Function: cmlb_convert_geometry
1839 *
1840 * Description: Convert physical geometry into a dk_geom structure. In
1841 * other words, make sure we don't wrap 16-bit values.
1842 * e.g. converting from geom_cache to dk_geom
1843 *
1844 * Context: Kernel thread only
1845 */
1846static void
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001847cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity,
1848 struct dk_geom *cl_g, void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001849{
lclee3ccda642005-10-28 23:47:40 -07001850
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001851 ASSERT(cl != NULL);
1852 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
1853
lclee3ccda642005-10-28 23:47:40 -07001854 /* Unlabeled SCSI floppy device */
Shidokht Yadegaric31fac72010-02-23 11:23:12 -08001855 if (capacity < 160) {
1856 /* Less than 80K */
1857 cl_g->dkg_nhead = 1;
1858 cl_g->dkg_ncyl = capacity;
1859 cl_g->dkg_nsect = 1;
1860 return;
1861 } else if (capacity <= 0x1000) {
shidokhte8fb11a2007-01-31 14:43:05 -08001862 cl_g->dkg_nhead = 2;
1863 cl_g->dkg_ncyl = 80;
1864 cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl);
lclee3ccda642005-10-28 23:47:40 -07001865 return;
1866 }
1867
1868 /*
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001869 * For all devices we calculate cylinders using the heads and sectors
1870 * we assign based on capacity of the device. The algorithm is
1871 * designed to be compatible with the way other operating systems
1872 * lay out fdisk tables for X86 and to insure that the cylinders never
1873 * exceed 65535 to prevent problems with X86 ioctls that report
1874 * geometry.
1875 * For some smaller disk sizes we report geometry that matches those
1876 * used by X86 BIOS usage. For larger disks, we use SPT that are
1877 * multiples of 63, since other OSes that are not limited to 16-bits
1878 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
lclee3ccda642005-10-28 23:47:40 -07001879 *
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001880 * The following table (in order) illustrates some end result
1881 * calculations:
1882 *
1883 * Maximum number of blocks nhead nsect
1884 *
1885 * 2097152 (1GB) 64 32
1886 * 16777216 (8GB) 128 32
1887 * 1052819775 (502.02GB) 255 63
1888 * 2105639550 (0.98TB) 255 126
1889 * 3158459325 (1.47TB) 255 189
1890 * 4211279100 (1.96TB) 255 252
1891 * 5264098875 (2.45TB) 255 315
1892 * ...
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001893 *
1894 * For Solid State Drive(SSD), it uses 4K page size inside and may be
1895 * double with every new generation. If the I/O is not aligned with
1896 * page size on SSDs, SSDs perform a lot slower.
1897 * By default, Solaris partition starts from cylinder 1. It will be
1898 * misaligned even with 4K if using heads(255) and SPT(63). To
1899 * workaround the problem, if the device is SSD, we use heads(224) and
1900 * SPT multiple of 56. Thus the default Solaris partition starts from
1901 * a position that aligns with 128K on a 512 bytes sector size SSD.
lclee3ccda642005-10-28 23:47:40 -07001902 */
lclee3ccda642005-10-28 23:47:40 -07001903
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001904 if (capacity <= 0x200000) {
1905 cl_g->dkg_nhead = 64;
1906 cl_g->dkg_nsect = 32;
1907 } else if (capacity <= 0x01000000) {
1908 cl_g->dkg_nhead = 128;
1909 cl_g->dkg_nsect = 32;
1910 } else {
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001911 tg_attribute_t tgattribute;
1912 int is_solid_state;
1913 unsigned short nhead;
1914 unsigned short nsect;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001915
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001916 bzero(&tgattribute, sizeof (tg_attribute_t));
1917
1918 mutex_exit(CMLB_MUTEX(cl));
1919 is_solid_state =
1920 (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ?
1921 tgattribute.media_is_solid_state : FALSE;
1922 mutex_enter(CMLB_MUTEX(cl));
1923
1924 if (is_solid_state) {
1925 nhead = 224;
1926 nsect = 56;
1927 } else {
1928 nhead = 255;
1929 nsect = 63;
1930 }
1931
1932 cl_g->dkg_nhead = nhead;
1933
lu cai - Sun Microsystems - Beijing Chinab132e0a2009-12-21 15:02:17 +08001934 /* make dkg_nsect be smallest multiple of nsect */
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001935 cl_g->dkg_nsect = ((capacity +
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001936 (UINT16_MAX * nhead * nsect) - 1) /
1937 (UINT16_MAX * nhead * nsect)) * nsect;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001938
1939 if (cl_g->dkg_nsect == 0)
yu, larry liu - Sun Microsystems - Beijing Chinab081f1c2009-08-17 10:56:59 +08001940 cl_g->dkg_nsect = (UINT16_MAX / nsect) * nsect;
Prasad Singamsetty342440e2008-09-11 18:00:50 -07001941 }
1942
lclee3ccda642005-10-28 23:47:40 -07001943}
1944#endif
1945
1946/*
1947 * Function: cmlb_resync_geom_caches
1948 *
1949 * Description: (Re)initialize both geometry caches: the virtual geometry
1950 * information is extracted from the HBA (the "geometry"
1951 * capability), and the physical geometry cache data is
1952 * generated by issuing MODE SENSE commands.
1953 *
shidokhte8fb11a2007-01-31 14:43:05 -08001954 * Arguments:
1955 * cl driver soft state (unit) structure
1956 * capacity disk capacity in #blocks
1957 * tg_cookie cookie from target driver to be passed back to target
1958 * driver when we call back to it through tg_ops.
lclee3ccda642005-10-28 23:47:40 -07001959 *
1960 * Context: Kernel thread only (can sleep).
1961 */
1962static void
shidokhte8fb11a2007-01-31 14:43:05 -08001963cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity,
1964 void *tg_cookie)
lclee3ccda642005-10-28 23:47:40 -07001965{
1966 struct cmlb_geom pgeom;
1967 struct cmlb_geom lgeom;
1968 struct cmlb_geom *pgeomp = &pgeom;
1969 unsigned short nhead;
1970 unsigned short nsect;
1971 int spc;
1972 int ret;
1973
shidokhte8fb11a2007-01-31 14:43:05 -08001974 ASSERT(cl != NULL);
1975 ASSERT(mutex_owned(CMLB_MUTEX(cl)));
lclee3ccda642005-10-28 23:47:40 -07001976
1977 /*
1978 * Ask the controller for its logical geometry.
1979 * Note: if the HBA does not support scsi_ifgetcap("geometry"),
1980 * then the lgeom cache will be invalid.
1981 */
shidokhte8fb11a2007-01-31 14:43:05 -08001982 mutex_exit(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001983 bzero(&lgeom, sizeof (struct cmlb_geom));
shidokhte8fb11a2007-01-31 14:43:05 -08001984 ret = DK_TG_GETVIRTGEOM(cl, &lgeom, tg_cookie);
1985 mutex_enter(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07001986
shidokhte8fb11a2007-01-31 14:43:05 -08001987 bcopy(&lgeom, &cl->cl_lgeom, sizeof (cl->cl_lgeom));
lclee3ccda642005-10-28 23:47:40 -07001988
1989 /*
1990 * Initialize the pgeom cache from lgeom, so that if MODE SENSE
1991 * doesn't work, DKIOCG_PHYSGEOM can return reasonable values.
1992 */
shidokhte8fb11a2007-01-31 14:43:05 -08001993 if (ret != 0 || cl->cl_lgeom.g_nsect == 0 ||
1994 cl->cl_lgeom.g_nhead == 0) {
lclee3ccda642005-10-28 23:47:40 -07001995 /*
1996 * Note: Perhaps this needs to be more adaptive? The rationale
1997 * is that, if there's no HBA geometry from the HBA driver, any
1998 * guess is good, since this is the physical geometry. If MODE
1999 * SENSE fails this gives a max cylinder size for non-LBA access
2000 */
2001 nhead = 255;
2002 nsect = 63;
2003 } else {
shidokhte8fb11a2007-01-31 14:43:05 -08002004 nhead = cl->cl_lgeom.g_nhead;
2005 nsect = cl->cl_lgeom.g_nsect;
lclee3ccda642005-10-28 23:47:40 -07002006 }
2007
shidokhte8fb11a2007-01-31 14:43:05 -08002008 if (ISCD(cl)) {
lclee3ccda642005-10-28 23:47:40 -07002009 pgeomp->g_nhead = 1;
2010 pgeomp->g_nsect = nsect * nhead;
2011 } else {
2012 pgeomp->g_nhead = nhead;
2013 pgeomp->g_nsect = nsect;
2014 }
2015
2016 spc = pgeomp->g_nhead * pgeomp->g_nsect;
2017 pgeomp->g_capacity = capacity;
Sheshadri Vasudevan7501b6d2009-06-08 15:32:25 +05302018 if (spc == 0)
2019 pgeomp->g_ncyl = 0;
2020 else
2021 pgeomp->g_ncyl = pgeomp->g_capacity / spc;
lclee3ccda642005-10-28 23:47:40 -07002022 pgeomp->g_acyl = 0;
2023
2024 /*
2025 * Retrieve fresh geometry data from the hardware, stash it
2026 * here temporarily before we rebuild the incore label.
2027 *
2028 * We want to use the MODE SENSE commands to derive the
2029 * physical geometry of the device, but if either command
2030 * fails, the logical geometry is used as the fallback for
2031 * disk label geometry.
2032 */
2033
shidokhte8fb11a2007-01-31 14:43:05 -08002034 mutex_exit(CMLB_MUTEX(cl));
2035 (void) DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie);
2036 mutex_enter(CMLB_MUTEX(cl));
lclee3ccda642005-10-28 23:47:40 -07002037
2038 /*
2039 * Now update the real copy while holding the mutex. This
2040 * way the global copy is never in an inconsistent state.
2041 */
shidokhte8fb11a2007-01-31 14:43:05 -08002042 bcopy(pgeomp, &cl->cl_pgeom, sizeof (cl->cl_pgeom));
lclee3ccda642005-10-28 23:47:40 -07002043
shidokhte8fb11a2007-01-31 14:43:05 -08002044 cmlb_dbg(CMLB_INFO, cl, "cmlb_resync_geom_caches: "
lclee3ccda642005-10-28 23:47:40 -07002045 "(cached from lgeom)\n");
shidokhte8fb11a2007-01-31 14:43:05 -08002046 cmlb_dbg(CMLB_INFO, cl,
lclee3ccda642005-10-28 23:47:40 -07002047 " ncyl: %ld; acyl: %d; nhead: %d; nsect: %d\n",
shidokhte8fb11a2007-01-31 14:43:05 -08002048 cl->cl_pgeom.g_ncyl, cl->cl_pgeom.g_acyl,
2049 cl->cl_pgeom.g_nhead, cl->cl_pgeom.g_nsect);
2050 cmlb_dbg(CMLB_INFO, cl, " lbasize: %d; capacity: %ld; "
2051 "intrlv: %d; rpm: %d\n", cl->cl_pgeom.g_secsize,
2052 cl->cl_pgeom.g_capacity, cl->cl_pgeom.g_intrlv,
2053 cl->cl_pgeom.g_rpm);
lclee3ccda642005-10-28 23:47:40 -07002054}
2055
2056
Sheshadri Vasudevanaa1b14e2009-07-02 08:59:40 +05302057#if defined(__i386) || defined(__amd64)
2058/*
2059 * Function: cmlb_update_ext_minor_nodes
2060 *
2061 * Description: Routine to add/remove extended partition device nodes
2062 *
2063 * Arguments:
2064 * cl driver soft state (unit) structure
2065 * num_parts Number of logical drives found on the LUN
2066 *
2067 * Should be called with the mutex held
2068 *
2069 * Return Code: 0 for success
2070 *
2071 * Context: User and Kernel thread
2072 *
2073 */
2074static int
2075cmlb_update_ext_minor_nodes(struct cmlb_lun *cl, int num_parts)
2076{
Toomas Soome406fc512015-10-23 09:36:11 +03002077 int i, count, shift;
Sheshadri Vasudevan