Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c
+++ new/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 25 * Copyright (c) 2013 by Delphix. All rights reserved.
26 26 */
27 27
28 28 #include <sys/sysmacros.h>
29 29 #include <sys/conf.h>
30 30 #include <sys/file.h>
31 31 #include <sys/ddi.h>
32 32 #include <sys/sunddi.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/scsi/scsi.h>
35 35 #include <sys/scsi/impl/scsi_reset_notify.h>
36 36 #include <sys/disp.h>
37 37 #include <sys/byteorder.h>
38 38 #include <sys/pathname.h>
39 39 #include <sys/atomic.h>
40 40 #include <sys/nvpair.h>
41 41 #include <sys/fs/zfs.h>
42 42 #include <sys/sdt.h>
43 43 #include <sys/dkio.h>
44 44 #include <sys/zfs_ioctl.h>
45 45
46 46 #include <sys/stmf.h>
47 47 #include <sys/lpif.h>
48 48 #include <sys/stmf_ioctl.h>
49 49 #include <sys/stmf_sbd_ioctl.h>
50 50
51 51 #include "stmf_sbd.h"
52 52 #include "sbd_impl.h"
53 53
54 54 #define SBD_IS_ZVOL(zvol) (strncmp("/dev/zvol", zvol, 9))
55 55
56 56 extern sbd_status_t sbd_pgr_meta_init(sbd_lu_t *sl);
57 57 extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl);
58 58 extern void sbd_pgr_reset(sbd_lu_t *sl);
59 59
60 60 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
61 61 void **result);
62 62 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
63 63 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
64 64 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
65 65 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
66 66 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
67 67 cred_t *credp, int *rval);
68 68 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
69 69 stmf_status_t sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg,
70 70 uint32_t proxy_reg_arg_len);
71 71 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
72 72 uint32_t proxy_reg_arg_len);
73 73 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
74 74 uint32_t proxy_arg_len, uint32_t type);
75 75 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
76 76 uint32_t *err_ret);
77 77 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
78 78 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
79 79 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
80 80 int no_register, sbd_lu_t **slr);
81 81 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
82 82 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
83 83 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
84 84 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
85 85 uint32_t *err_ret);
86 86 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
87 87 uint32_t *err_ret);
88 88 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
89 89 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
90 90 static char *sbd_get_zvol_name(sbd_lu_t *);
91 91 static int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup,
92 92 uint32_t *err_ret);
93 93 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
94 94 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
95 95 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
96 96 uint64_t off);
97 97 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
98 98 uint64_t off);
99 99 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
100 100 int sbd_is_zvol(char *path);
101 101 int sbd_zvolget(char *zvol_name, char **comstarprop);
102 102 int sbd_zvolset(char *zvol_name, char *comstarprop);
103 103 char sbd_ctoi(char c);
104 104 void sbd_close_lu(sbd_lu_t *sl);
105 105
106 106 static ldi_ident_t sbd_zfs_ident;
107 107 static stmf_lu_provider_t *sbd_lp;
108 108 static sbd_lu_t *sbd_lu_list = NULL;
109 109 static kmutex_t sbd_lock;
110 110 static dev_info_t *sbd_dip;
111 111 static uint32_t sbd_lu_count = 0;
112 112
113 113 /* Global property settings for the logical unit */
114 114 char sbd_vendor_id[] = "SUN ";
115 115 char sbd_product_id[] = "COMSTAR ";
116 116 char sbd_revision[] = "1.0 ";
117 117 char *sbd_mgmt_url = NULL;
118 118 uint16_t sbd_mgmt_url_alloc_size = 0;
119 119 krwlock_t sbd_global_prop_lock;
120 120
121 121 static char sbd_name[] = "sbd";
122 122
123 123 static struct cb_ops sbd_cb_ops = {
124 124 sbd_open, /* open */
125 125 sbd_close, /* close */
126 126 nodev, /* strategy */
127 127 nodev, /* print */
128 128 nodev, /* dump */
129 129 nodev, /* read */
130 130 nodev, /* write */
131 131 stmf_sbd_ioctl, /* ioctl */
132 132 nodev, /* devmap */
133 133 nodev, /* mmap */
134 134 nodev, /* segmap */
135 135 nochpoll, /* chpoll */
136 136 ddi_prop_op, /* cb_prop_op */
137 137 0, /* streamtab */
138 138 D_NEW | D_MP, /* cb_flag */
139 139 CB_REV, /* rev */
140 140 nodev, /* aread */
141 141 nodev /* awrite */
142 142 };
143 143
144 144 static struct dev_ops sbd_ops = {
145 145 DEVO_REV,
146 146 0,
147 147 sbd_getinfo,
148 148 nulldev, /* identify */
149 149 nulldev, /* probe */
150 150 sbd_attach,
151 151 sbd_detach,
152 152 nodev, /* reset */
153 153 &sbd_cb_ops,
154 154 NULL, /* bus_ops */
155 155 NULL /* power */
156 156 };
157 157
↓ open down ↓ |
157 lines elided |
↑ open up ↑ |
158 158 #define SBD_NAME "COMSTAR SBD"
159 159
160 160 static struct modldrv modldrv = {
161 161 &mod_driverops,
162 162 SBD_NAME,
163 163 &sbd_ops
164 164 };
165 165
166 166 static struct modlinkage modlinkage = {
167 167 MODREV_1,
168 - &modldrv,
169 - NULL
168 + { &modldrv, NULL }
170 169 };
171 170
172 171 int
173 172 _init(void)
174 173 {
175 174 int ret;
176 175
177 176 ret = mod_install(&modlinkage);
178 177 if (ret)
179 178 return (ret);
180 179 sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
181 180 0, 0);
182 181 sbd_lp->lp_lpif_rev = LPIF_REV_2;
183 182 sbd_lp->lp_instance = 0;
184 183 sbd_lp->lp_name = sbd_name;
185 184 sbd_lp->lp_cb = sbd_lp_cb;
186 185 sbd_lp->lp_alua_support = 1;
187 186 sbd_lp->lp_proxy_msg = sbd_proxy_msg;
188 187 sbd_zfs_ident = ldi_ident_from_anon();
189 188
190 189 if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
191 190 (void) mod_remove(&modlinkage);
192 191 stmf_free(sbd_lp);
193 192 return (EINVAL);
194 193 }
195 194 mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
196 195 rw_init(&sbd_global_prop_lock, NULL, RW_DRIVER, NULL);
197 196 return (0);
198 197 }
199 198
200 199 int
201 200 _fini(void)
202 201 {
203 202 int ret;
204 203
205 204 /*
206 205 * If we have registered lus, then make sure they are all offline
207 206 * if so then deregister them. This should drop the sbd_lu_count
208 207 * to zero.
209 208 */
210 209 if (sbd_lu_count) {
211 210 sbd_lu_t *slu;
212 211
213 212 /* See if all of them are offline */
214 213 mutex_enter(&sbd_lock);
215 214 for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
216 215 if ((slu->sl_state != STMF_STATE_OFFLINE) ||
217 216 slu->sl_state_not_acked) {
218 217 mutex_exit(&sbd_lock);
219 218 return (EBUSY);
220 219 }
221 220 }
222 221 mutex_exit(&sbd_lock);
223 222
224 223 #if 0
225 224 /* ok start deregistering them */
226 225 while (sbd_lu_list) {
227 226 sbd_store_t *sst = sbd_lu_list->sl_sst;
228 227 if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
229 228 return (EBUSY);
230 229 }
231 230 #endif
232 231 return (EBUSY);
233 232 }
234 233 if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
235 234 return (EBUSY);
236 235 ret = mod_remove(&modlinkage);
237 236 if (ret != 0) {
238 237 (void) stmf_register_lu_provider(sbd_lp);
239 238 return (ret);
240 239 }
241 240 stmf_free(sbd_lp);
242 241 mutex_destroy(&sbd_lock);
243 242 rw_destroy(&sbd_global_prop_lock);
244 243 ldi_ident_release(sbd_zfs_ident);
245 244 return (0);
246 245 }
247 246
248 247 int
249 248 _info(struct modinfo *modinfop)
250 249 {
251 250 return (mod_info(&modlinkage, modinfop));
252 251 }
253 252
254 253 /* ARGSUSED */
255 254 static int
256 255 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
257 256 {
258 257 switch (cmd) {
259 258 case DDI_INFO_DEVT2DEVINFO:
260 259 *result = sbd_dip;
261 260 break;
262 261 case DDI_INFO_DEVT2INSTANCE:
263 262 *result = (void *)(uintptr_t)ddi_get_instance(sbd_dip);
264 263 break;
265 264 default:
266 265 return (DDI_FAILURE);
267 266 }
268 267
269 268 return (DDI_SUCCESS);
270 269 }
271 270
272 271 static int
273 272 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
274 273 {
275 274 switch (cmd) {
276 275 case DDI_ATTACH:
277 276 sbd_dip = dip;
278 277
279 278 if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
280 279 DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
281 280 break;
282 281 }
283 282 ddi_report_dev(dip);
284 283 return (DDI_SUCCESS);
285 284 }
286 285
287 286 return (DDI_FAILURE);
288 287 }
289 288
290 289 static int
291 290 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
292 291 {
293 292 switch (cmd) {
294 293 case DDI_DETACH:
295 294 ddi_remove_minor_node(dip, 0);
296 295 return (DDI_SUCCESS);
297 296 }
298 297
299 298 return (DDI_FAILURE);
300 299 }
301 300
302 301 /* ARGSUSED */
303 302 static int
304 303 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
305 304 {
306 305 if (otype != OTYP_CHR)
307 306 return (EINVAL);
308 307 return (0);
309 308 }
310 309
311 310 /* ARGSUSED */
312 311 static int
313 312 sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
314 313 {
315 314 return (0);
316 315 }
317 316
318 317 /* ARGSUSED */
319 318 static int
320 319 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
321 320 cred_t *credp, int *rval)
322 321 {
323 322 stmf_iocdata_t *iocd;
324 323 void *ibuf = NULL;
325 324 void *obuf = NULL;
326 325 sbd_lu_t *nsl;
327 326 int i;
328 327 int ret;
329 328
330 329 if (drv_priv(credp) != 0) {
331 330 return (EPERM);
332 331 }
333 332
334 333 ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
335 334 if (ret)
336 335 return (ret);
337 336 iocd->stmf_error = 0;
338 337
339 338 switch (cmd) {
340 339 case SBD_IOCTL_CREATE_AND_REGISTER_LU:
341 340 if (iocd->stmf_ibuf_size <
342 341 (sizeof (sbd_create_and_reg_lu_t) - 8)) {
343 342 ret = EFAULT;
344 343 break;
345 344 }
346 345 if ((iocd->stmf_obuf_size == 0) ||
347 346 (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
348 347 ret = EINVAL;
349 348 break;
350 349 }
351 350 ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *)
352 351 ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error);
353 352 bcopy(ibuf, obuf, iocd->stmf_obuf_size);
354 353 break;
355 354 case SBD_IOCTL_SET_LU_STANDBY:
356 355 if (iocd->stmf_ibuf_size < sizeof (sbd_set_lu_standby_t)) {
357 356 ret = EFAULT;
358 357 break;
359 358 }
360 359 if (iocd->stmf_obuf_size) {
361 360 ret = EINVAL;
362 361 break;
363 362 }
364 363 ret = sbd_set_lu_standby((sbd_set_lu_standby_t *)ibuf,
365 364 &iocd->stmf_error);
366 365 break;
367 366 case SBD_IOCTL_IMPORT_LU:
368 367 if (iocd->stmf_ibuf_size <
369 368 (sizeof (sbd_import_lu_t) - 8)) {
370 369 ret = EFAULT;
371 370 break;
372 371 }
373 372 if ((iocd->stmf_obuf_size == 0) ||
374 373 (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
375 374 ret = EINVAL;
376 375 break;
377 376 }
378 377 ret = sbd_import_lu((sbd_import_lu_t *)ibuf,
379 378 iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL);
380 379 bcopy(ibuf, obuf, iocd->stmf_obuf_size);
381 380 break;
382 381 case SBD_IOCTL_DELETE_LU:
383 382 if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) {
384 383 ret = EFAULT;
385 384 break;
386 385 }
387 386 if (iocd->stmf_obuf_size) {
388 387 ret = EINVAL;
389 388 break;
390 389 }
391 390 ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf,
392 391 iocd->stmf_ibuf_size, &iocd->stmf_error);
393 392 break;
394 393 case SBD_IOCTL_MODIFY_LU:
395 394 if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) {
396 395 ret = EFAULT;
397 396 break;
398 397 }
399 398 if (iocd->stmf_obuf_size) {
400 399 ret = EINVAL;
401 400 break;
402 401 }
403 402 ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf,
404 403 iocd->stmf_ibuf_size, &iocd->stmf_error);
405 404 break;
406 405 case SBD_IOCTL_SET_GLOBAL_LU:
407 406 if (iocd->stmf_ibuf_size < (sizeof (sbd_global_props_t) - 8)) {
408 407 ret = EFAULT;
409 408 break;
410 409 }
411 410 if (iocd->stmf_obuf_size) {
412 411 ret = EINVAL;
413 412 break;
414 413 }
415 414 ret = sbd_set_global_props((sbd_global_props_t *)ibuf,
416 415 iocd->stmf_ibuf_size, &iocd->stmf_error);
417 416 break;
418 417 case SBD_IOCTL_GET_GLOBAL_LU:
419 418 if (iocd->stmf_ibuf_size) {
420 419 ret = EINVAL;
421 420 break;
422 421 }
423 422 if (iocd->stmf_obuf_size < sizeof (sbd_global_props_t)) {
424 423 ret = EINVAL;
425 424 break;
426 425 }
427 426 ret = sbd_get_global_props((sbd_global_props_t *)obuf,
428 427 iocd->stmf_obuf_size, &iocd->stmf_error);
429 428 break;
430 429 case SBD_IOCTL_GET_LU_PROPS:
431 430 if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) {
432 431 ret = EFAULT;
433 432 break;
434 433 }
435 434 if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) {
436 435 ret = EINVAL;
437 436 break;
438 437 }
439 438 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
440 439 iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
441 440 iocd->stmf_obuf_size, &iocd->stmf_error);
442 441 break;
443 442 case SBD_IOCTL_GET_LU_LIST:
444 443 mutex_enter(&sbd_lock);
445 444 iocd->stmf_obuf_max_nentries = sbd_lu_count;
446 445 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
447 446 sbd_lu_count);
448 447 for (nsl = sbd_lu_list, i = 0; nsl &&
449 448 (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
450 449 bcopy(nsl->sl_device_id + 4,
451 450 &(((uint8_t *)obuf)[i << 4]), 16);
452 451 }
453 452 mutex_exit(&sbd_lock);
454 453 ret = 0;
455 454 iocd->stmf_error = 0;
456 455 break;
457 456 case SBD_IOCTL_GET_UNMAP_PROPS:
458 457 if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) {
459 458 ret = EFAULT;
460 459 break;
461 460 }
462 461 if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) {
463 462 ret = EINVAL;
464 463 break;
465 464 }
466 465 ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf,
467 466 (sbd_unmap_props_t *)obuf, &iocd->stmf_error);
468 467 break;
469 468 default:
470 469 ret = ENOTTY;
471 470 }
472 471
473 472 if (ret == 0) {
474 473 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
475 474 } else if (iocd->stmf_error) {
476 475 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
477 476 }
478 477 if (obuf) {
479 478 kmem_free(obuf, iocd->stmf_obuf_size);
480 479 obuf = NULL;
481 480 }
482 481 if (ibuf) {
483 482 kmem_free(ibuf, iocd->stmf_ibuf_size);
484 483 ibuf = NULL;
485 484 }
486 485 kmem_free(iocd, sizeof (stmf_iocdata_t));
487 486 return (ret);
488 487 }
489 488
490 489 /* ARGSUSED */
491 490 void
492 491 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
493 492 {
494 493 nvpair_t *np;
495 494 char *s;
496 495 sbd_import_lu_t *ilu;
497 496 uint32_t ilu_sz;
498 497 uint32_t struct_sz;
499 498 uint32_t err_ret;
500 499 int iret;
501 500
502 501 if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
503 502 return;
504 503 }
505 504
506 505 if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
507 506 return;
508 507 }
509 508
510 509 np = NULL;
511 510 ilu_sz = 1024;
512 511 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
513 512 while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
514 513 if (nvpair_type(np) != DATA_TYPE_STRING) {
515 514 continue;
516 515 }
517 516 if (nvpair_value_string(np, &s) != 0) {
518 517 continue;
519 518 }
520 519 struct_sz = max(8, strlen(s) + 1);
521 520 struct_sz += sizeof (sbd_import_lu_t) - 8;
522 521 if (struct_sz > ilu_sz) {
523 522 kmem_free(ilu, ilu_sz);
524 523 ilu_sz = struct_sz + 32;
525 524 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
526 525 }
527 526 ilu->ilu_struct_size = struct_sz;
528 527 (void) strcpy(ilu->ilu_meta_fname, s);
529 528 iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL);
530 529 if (iret) {
531 530 stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
532 531 "err_ret = %d", iret, err_ret);
533 532 } else {
534 533 stmf_trace(0, "Imported the LU %s", nvpair_name(np));
535 534 }
536 535 }
537 536
538 537 if (ilu) {
539 538 kmem_free(ilu, ilu_sz);
540 539 ilu = NULL;
541 540 }
542 541 }
543 542
544 543 sbd_status_t
545 544 sbd_link_lu(sbd_lu_t *sl)
546 545 {
547 546 sbd_lu_t *nsl;
548 547
549 548 mutex_enter(&sbd_lock);
550 549 mutex_enter(&sl->sl_lock);
551 550 ASSERT(sl->sl_trans_op != SL_OP_NONE);
552 551
553 552 if (sl->sl_flags & SL_LINKED) {
554 553 mutex_exit(&sbd_lock);
555 554 mutex_exit(&sl->sl_lock);
556 555 return (SBD_ALREADY);
557 556 }
558 557 for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) {
559 558 if (strcmp(nsl->sl_name, sl->sl_name) == 0)
560 559 break;
561 560 }
562 561 if (nsl) {
563 562 mutex_exit(&sbd_lock);
564 563 mutex_exit(&sl->sl_lock);
565 564 return (SBD_ALREADY);
566 565 }
567 566 sl->sl_next = sbd_lu_list;
568 567 sbd_lu_list = sl;
569 568 sl->sl_flags |= SL_LINKED;
570 569 mutex_exit(&sbd_lock);
571 570 mutex_exit(&sl->sl_lock);
572 571 return (SBD_SUCCESS);
573 572 }
574 573
575 574 void
576 575 sbd_unlink_lu(sbd_lu_t *sl)
577 576 {
578 577 sbd_lu_t **ppnsl;
579 578
580 579 mutex_enter(&sbd_lock);
581 580 mutex_enter(&sl->sl_lock);
582 581 ASSERT(sl->sl_trans_op != SL_OP_NONE);
583 582
584 583 ASSERT(sl->sl_flags & SL_LINKED);
585 584 for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) {
586 585 if (*ppnsl == sl)
587 586 break;
588 587 }
589 588 ASSERT(*ppnsl);
590 589 *ppnsl = (*ppnsl)->sl_next;
591 590 sl->sl_flags &= ~SL_LINKED;
592 591 mutex_exit(&sbd_lock);
593 592 mutex_exit(&sl->sl_lock);
594 593 }
595 594
596 595 sbd_status_t
597 596 sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op,
598 597 sbd_lu_t **ppsl)
599 598 {
600 599 sbd_lu_t *sl;
601 600 int found = 0;
602 601 sbd_status_t sret;
603 602
604 603 mutex_enter(&sbd_lock);
605 604 for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
606 605 if (guid) {
607 606 found = bcmp(sl->sl_device_id + 4, guid, 16) == 0;
608 607 } else {
609 608 found = strcmp(sl->sl_name, (char *)meta_name) == 0;
610 609 }
611 610 if (found)
612 611 break;
613 612 }
614 613 if (!found) {
615 614 mutex_exit(&sbd_lock);
616 615 return (SBD_NOT_FOUND);
617 616 }
618 617 mutex_enter(&sl->sl_lock);
619 618 if (sl->sl_trans_op == SL_OP_NONE) {
620 619 sl->sl_trans_op = op;
621 620 *ppsl = sl;
622 621 sret = SBD_SUCCESS;
623 622 } else {
624 623 sret = SBD_BUSY;
625 624 }
626 625 mutex_exit(&sl->sl_lock);
627 626 mutex_exit(&sbd_lock);
628 627 return (sret);
629 628 }
630 629
631 630 sbd_status_t
632 631 sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
633 632 {
634 633 uint64_t meta_align;
635 634 uint64_t starting_off;
636 635 uint64_t data_off;
637 636 uint64_t ending_off;
638 637 uint64_t io_size;
639 638 uint8_t *io_buf;
640 639 vnode_t *vp;
641 640 sbd_status_t ret;
642 641 ssize_t resid;
643 642 int vret;
644 643
645 644 ASSERT(sl->sl_flags & SL_META_OPENED);
646 645 if (sl->sl_flags & SL_SHARED_META) {
647 646 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
648 647 vp = sl->sl_data_vp;
649 648 ASSERT(vp);
650 649 } else {
651 650 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
652 651 if ((sl->sl_flags & SL_ZFS_META) == 0) {
653 652 vp = sl->sl_meta_vp;
654 653 ASSERT(vp);
655 654 }
656 655 }
657 656 starting_off = offset & ~(meta_align);
658 657 data_off = offset & meta_align;
659 658 ending_off = (offset + size + meta_align) & (~meta_align);
660 659 if (ending_off > sl->sl_meta_size_used) {
661 660 bzero(buf, size);
662 661 if (starting_off >= sl->sl_meta_size_used) {
663 662 return (SBD_SUCCESS);
664 663 }
665 664 ending_off = (sl->sl_meta_size_used + meta_align) &
666 665 (~meta_align);
667 666 if (size > (ending_off - (starting_off + data_off))) {
668 667 size = ending_off - (starting_off + data_off);
669 668 }
670 669 }
671 670 io_size = ending_off - starting_off;
672 671 io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
673 672 ASSERT((starting_off + io_size) <= sl->sl_total_meta_size);
674 673
675 674 /*
676 675 * Don't proceed if the device has been closed
677 676 * This can occur on an access state change to standby or
678 677 * a delete. The writer lock is acquired before closing the
679 678 * lu. If importing, reading the metadata is valid, hence
680 679 * the check on SL_OP_IMPORT_LU.
681 680 */
682 681 rw_enter(&sl->sl_access_state_lock, RW_READER);
683 682 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
684 683 sl->sl_trans_op != SL_OP_IMPORT_LU) {
685 684 rw_exit(&sl->sl_access_state_lock);
686 685 ret = SBD_FILEIO_FAILURE;
687 686 goto sbd_read_meta_failure;
688 687 }
689 688 if (sl->sl_flags & SL_ZFS_META) {
690 689 if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size,
691 690 starting_off)) != SBD_SUCCESS) {
692 691 rw_exit(&sl->sl_access_state_lock);
693 692 goto sbd_read_meta_failure;
694 693 }
695 694 } else {
696 695 vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size,
697 696 (offset_t)starting_off, UIO_SYSSPACE, FRSYNC,
698 697 RLIM64_INFINITY, CRED(), &resid);
699 698
700 699 if (vret || resid) {
701 700 ret = SBD_FILEIO_FAILURE | vret;
702 701 rw_exit(&sl->sl_access_state_lock);
703 702 goto sbd_read_meta_failure;
704 703 }
705 704 }
706 705 rw_exit(&sl->sl_access_state_lock);
707 706
708 707 bcopy(io_buf + data_off, buf, size);
709 708 ret = SBD_SUCCESS;
710 709
711 710 sbd_read_meta_failure:
712 711 kmem_free(io_buf, io_size);
713 712 return (ret);
714 713 }
715 714
716 715 sbd_status_t
717 716 sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
718 717 {
719 718 uint64_t meta_align;
720 719 uint64_t starting_off;
721 720 uint64_t data_off;
722 721 uint64_t ending_off;
723 722 uint64_t io_size;
724 723 uint8_t *io_buf;
725 724 vnode_t *vp;
726 725 sbd_status_t ret;
727 726 ssize_t resid;
728 727 int vret;
729 728
730 729 ASSERT(sl->sl_flags & SL_META_OPENED);
731 730 if (sl->sl_flags & SL_SHARED_META) {
732 731 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
733 732 vp = sl->sl_data_vp;
734 733 ASSERT(vp);
735 734 } else {
736 735 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
737 736 if ((sl->sl_flags & SL_ZFS_META) == 0) {
738 737 vp = sl->sl_meta_vp;
739 738 ASSERT(vp);
740 739 }
741 740 }
742 741 starting_off = offset & ~(meta_align);
743 742 data_off = offset & meta_align;
744 743 ending_off = (offset + size + meta_align) & (~meta_align);
745 744 io_size = ending_off - starting_off;
746 745 io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
747 746 ret = sbd_read_meta(sl, starting_off, io_size, io_buf);
748 747 if (ret != SBD_SUCCESS) {
749 748 goto sbd_write_meta_failure;
750 749 }
751 750 bcopy(buf, io_buf + data_off, size);
752 751 /*
753 752 * Don't proceed if the device has been closed
754 753 * This can occur on an access state change to standby or
755 754 * a delete. The writer lock is acquired before closing the
756 755 * lu. If importing, reading the metadata is valid, hence
757 756 * the check on SL_OP_IMPORT_LU.
758 757 */
759 758 rw_enter(&sl->sl_access_state_lock, RW_READER);
760 759 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
761 760 sl->sl_trans_op != SL_OP_IMPORT_LU) {
762 761 rw_exit(&sl->sl_access_state_lock);
763 762 ret = SBD_FILEIO_FAILURE;
764 763 goto sbd_write_meta_failure;
765 764 }
766 765 if (sl->sl_flags & SL_ZFS_META) {
767 766 if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size,
768 767 starting_off)) != SBD_SUCCESS) {
769 768 rw_exit(&sl->sl_access_state_lock);
770 769 goto sbd_write_meta_failure;
771 770 }
772 771 } else {
773 772 vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size,
774 773 (offset_t)starting_off, UIO_SYSSPACE, FDSYNC,
775 774 RLIM64_INFINITY, CRED(), &resid);
776 775
777 776 if (vret || resid) {
778 777 ret = SBD_FILEIO_FAILURE | vret;
779 778 rw_exit(&sl->sl_access_state_lock);
780 779 goto sbd_write_meta_failure;
781 780 }
782 781 }
783 782 rw_exit(&sl->sl_access_state_lock);
784 783
785 784 ret = SBD_SUCCESS;
786 785
787 786 sbd_write_meta_failure:
788 787 kmem_free(io_buf, io_size);
789 788 return (ret);
790 789 }
791 790
792 791 uint8_t
793 792 sbd_calc_sum(uint8_t *buf, int size)
794 793 {
795 794 uint8_t s = 0;
796 795
797 796 while (size > 0)
798 797 s += buf[--size];
799 798
800 799 return (s);
801 800 }
802 801
803 802 uint8_t
804 803 sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz)
805 804 {
806 805 uint8_t s, o;
807 806
808 807 o = sm->sms_chksum;
809 808 sm->sms_chksum = 0;
810 809 s = sbd_calc_sum((uint8_t *)sm, sz);
811 810 sm->sms_chksum = o;
812 811
813 812 return (s);
814 813 }
815 814
816 815 uint32_t
817 816 sbd_strlen(char *str, uint32_t maxlen)
818 817 {
819 818 uint32_t i;
820 819
821 820 for (i = 0; i < maxlen; i++) {
822 821 if (str[i] == 0)
823 822 return (i);
824 823 }
825 824 return (i);
826 825 }
827 826
828 827 void
829 828 sbd_swap_meta_start(sbd_meta_start_t *sm)
830 829 {
831 830 if (sm->sm_magic == SBD_MAGIC)
832 831 return;
833 832 sm->sm_magic = BSWAP_64(sm->sm_magic);
834 833 sm->sm_meta_size = BSWAP_64(sm->sm_meta_size);
835 834 sm->sm_meta_size_used = BSWAP_64(sm->sm_meta_size_used);
836 835 sm->sm_ver_major = BSWAP_16(sm->sm_ver_major);
837 836 sm->sm_ver_minor = BSWAP_16(sm->sm_ver_minor);
838 837 sm->sm_ver_subminor = BSWAP_16(sm->sm_ver_subminor);
839 838 }
840 839
841 840 void
842 841 sbd_swap_section_hdr(sm_section_hdr_t *sm)
843 842 {
844 843 if (sm->sms_data_order == SMS_DATA_ORDER)
845 844 return;
846 845 sm->sms_offset = BSWAP_64(sm->sms_offset);
847 846 sm->sms_size = BSWAP_32(sm->sms_size);
848 847 sm->sms_id = BSWAP_16(sm->sms_id);
849 848 sm->sms_chksum += SMS_DATA_ORDER - sm->sms_data_order;
850 849 sm->sms_data_order = SMS_DATA_ORDER;
851 850 }
852 851
853 852 void
854 853 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli)
855 854 {
856 855 sbd_swap_section_hdr(&sli->sli_sms_header);
857 856 if (sli->sli_data_order == SMS_DATA_ORDER)
858 857 return;
859 858 sli->sli_sms_header.sms_chksum += SMS_DATA_ORDER - sli->sli_data_order;
860 859 sli->sli_data_order = SMS_DATA_ORDER;
861 860 sli->sli_total_store_size = BSWAP_64(sli->sli_total_store_size);
862 861 sli->sli_total_meta_size = BSWAP_64(sli->sli_total_meta_size);
863 862 sli->sli_lu_data_offset = BSWAP_64(sli->sli_lu_data_offset);
864 863 sli->sli_lu_data_size = BSWAP_64(sli->sli_lu_data_size);
865 864 sli->sli_flags = BSWAP_32(sli->sli_flags);
866 865 sli->sli_blocksize = BSWAP_16(sli->sli_blocksize);
867 866 }
868 867
869 868 void
870 869 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli)
871 870 {
872 871 sbd_swap_section_hdr(&sli->sli_sms_header);
873 872 if (sli->sli_data_order == SMS_DATA_ORDER)
874 873 return;
875 874 sli->sli_sms_header.sms_chksum += SMS_DATA_ORDER - sli->sli_data_order;
876 875 sli->sli_data_order = SMS_DATA_ORDER;
877 876 sli->sli_flags = BSWAP_32(sli->sli_flags);
878 877 sli->sli_lu_size = BSWAP_64(sli->sli_lu_size);
879 878 sli->sli_meta_fname_offset = BSWAP_64(sli->sli_meta_fname_offset);
880 879 sli->sli_data_fname_offset = BSWAP_64(sli->sli_data_fname_offset);
881 880 sli->sli_serial_offset = BSWAP_64(sli->sli_serial_offset);
882 881 sli->sli_alias_offset = BSWAP_64(sli->sli_alias_offset);
883 882 sli->sli_mgmt_url_offset = BSWAP_64(sli->sli_mgmt_url_offset);
884 883 }
885 884
886 885 sbd_status_t
887 886 sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms)
888 887 {
889 888 sm_section_hdr_t h;
890 889 uint64_t st;
891 890 sbd_status_t ret;
892 891
893 892 for (st = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
894 893 st < sl->sl_meta_size_used; st += h.sms_size) {
895 894 if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t),
896 895 (uint8_t *)&h)) != SBD_SUCCESS) {
897 896 return (ret);
898 897 }
899 898 if (h.sms_data_order != SMS_DATA_ORDER) {
900 899 sbd_swap_section_hdr(&h);
901 900 }
902 901 if ((h.sms_data_order != SMS_DATA_ORDER) ||
903 902 (h.sms_offset != st) || (h.sms_size < sizeof (h)) ||
904 903 ((st + h.sms_size) > sl->sl_meta_size_used)) {
905 904 return (SBD_META_CORRUPTED);
906 905 }
907 906 if (h.sms_id == sms->sms_id) {
908 907 bcopy(&h, sms, sizeof (h));
909 908 return (SBD_SUCCESS);
910 909 }
911 910 }
912 911
913 912 return (SBD_NOT_FOUND);
914 913 }
915 914
916 915 sbd_status_t
917 916 sbd_load_meta_start(sbd_lu_t *sl)
918 917 {
919 918 sbd_meta_start_t *sm;
920 919 sbd_status_t ret;
921 920
922 921 /* Fake meta params initially */
923 922 sl->sl_total_meta_size = (uint64_t)-1;
924 923 sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
925 924
926 925 sm = kmem_zalloc(sizeof (*sm), KM_SLEEP);
927 926 ret = sbd_read_meta(sl, sl->sl_meta_offset, sizeof (*sm),
928 927 (uint8_t *)sm);
929 928 if (ret != SBD_SUCCESS) {
930 929 goto load_meta_start_failed;
931 930 }
932 931
933 932 if (sm->sm_magic != SBD_MAGIC) {
934 933 sbd_swap_meta_start(sm);
935 934 }
936 935
937 936 if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm,
938 937 sizeof (*sm) - 1) != sm->sm_chksum)) {
939 938 ret = SBD_META_CORRUPTED;
940 939 goto load_meta_start_failed;
941 940 }
942 941
943 942 if (sm->sm_ver_major != SBD_VER_MAJOR) {
944 943 ret = SBD_NOT_SUPPORTED;
945 944 goto load_meta_start_failed;
946 945 }
947 946
948 947 sl->sl_total_meta_size = sm->sm_meta_size;
949 948 sl->sl_meta_size_used = sm->sm_meta_size_used;
950 949 ret = SBD_SUCCESS;
951 950
952 951 load_meta_start_failed:
953 952 kmem_free(sm, sizeof (*sm));
954 953 return (ret);
955 954 }
956 955
957 956 sbd_status_t
958 957 sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used)
959 958 {
960 959 sbd_meta_start_t *sm;
961 960 sbd_status_t ret;
962 961
963 962 sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t),
964 963 KM_SLEEP);
965 964
966 965 sm->sm_magic = SBD_MAGIC;
967 966 sm->sm_meta_size = meta_size;
968 967 sm->sm_meta_size_used = meta_size_used;
969 968 sm->sm_ver_major = SBD_VER_MAJOR;
970 969 sm->sm_ver_minor = SBD_VER_MINOR;
971 970 sm->sm_ver_subminor = SBD_VER_SUBMINOR;
972 971 sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1);
973 972
974 973 ret = sbd_write_meta(sl, sl->sl_meta_offset, sizeof (*sm),
975 974 (uint8_t *)sm);
976 975 kmem_free(sm, sizeof (*sm));
977 976
978 977 return (ret);
979 978 }
980 979
981 980 sbd_status_t
982 981 sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id)
983 982 {
984 983 sbd_status_t ret;
985 984 sm_section_hdr_t sms;
986 985 int alloced = 0;
987 986
988 987 mutex_enter(&sl->sl_metadata_lock);
989 988 if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) {
990 989 bzero(&sms, sizeof (sm_section_hdr_t));
991 990 sms.sms_id = sms_id;
992 991 if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) {
993 992 mutex_exit(&sl->sl_metadata_lock);
994 993 return (ret);
995 994 } else {
996 995 if ((*ppsms) == NULL) {
997 996 *ppsms = (sm_section_hdr_t *)kmem_zalloc(
998 997 sms.sms_size, KM_SLEEP);
999 998 alloced = 1;
1000 999 }
1001 1000 bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t));
1002 1001 }
1003 1002 }
1004 1003
1005 1004 ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size,
1006 1005 (uint8_t *)(*ppsms));
1007 1006 if (ret == SBD_SUCCESS) {
1008 1007 uint8_t s;
1009 1008 if ((*ppsms)->sms_data_order != SMS_DATA_ORDER)
1010 1009 sbd_swap_section_hdr(*ppsms);
1011 1010 if ((*ppsms)->sms_id != SMS_ID_UNUSED) {
1012 1011 s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size);
1013 1012 if (s != (*ppsms)->sms_chksum)
1014 1013 ret = SBD_META_CORRUPTED;
1015 1014 }
1016 1015 }
1017 1016 mutex_exit(&sl->sl_metadata_lock);
1018 1017
1019 1018 if ((ret != SBD_SUCCESS) && alloced)
1020 1019 kmem_free(*ppsms, sms.sms_size);
1021 1020 return (ret);
1022 1021 }
1023 1022
1024 1023 sbd_status_t
1025 1024 sbd_load_section_hdr_unbuffered(sbd_lu_t *sl, sm_section_hdr_t *sms)
1026 1025 {
1027 1026 sbd_status_t ret;
1028 1027
1029 1028 /*
1030 1029 * Bypass buffering and re-read the meta data from permanent storage.
1031 1030 */
1032 1031 if (sl->sl_flags & SL_ZFS_META) {
1033 1032 if ((ret = sbd_open_zfs_meta(sl)) != SBD_SUCCESS) {
1034 1033 return (ret);
1035 1034 }
1036 1035 }
1037 1036 /* Re-get the meta sizes into sl */
1038 1037 if ((ret = sbd_load_meta_start(sl)) != SBD_SUCCESS) {
1039 1038 return (ret);
1040 1039 }
1041 1040 return (sbd_load_section_hdr(sl, sms));
1042 1041 }
1043 1042
1044 1043 sbd_status_t
1045 1044 sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms)
1046 1045 {
1047 1046 sm_section_hdr_t t;
1048 1047 uint64_t off, s;
1049 1048 uint64_t unused_start;
1050 1049 sbd_status_t ret;
1051 1050 sbd_status_t write_meta_ret = SBD_SUCCESS;
1052 1051 uint8_t *cb;
1053 1052 int meta_size_changed = 0;
1054 1053 sm_section_hdr_t sms_before_unused = {0};
1055 1054
1056 1055 mutex_enter(&sl->sl_metadata_lock);
1057 1056 write_meta_section_again:
1058 1057 if (sms->sms_offset) {
1059 1058 /*
1060 1059 * If the section already exists and the size is the
1061 1060 * same as this new data then overwrite in place. If
1062 1061 * the sizes are different then mark the existing as
1063 1062 * unused and look for free space.
1064 1063 */
1065 1064 ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t),
1066 1065 (uint8_t *)&t);
1067 1066 if (ret != SBD_SUCCESS) {
1068 1067 mutex_exit(&sl->sl_metadata_lock);
1069 1068 return (ret);
1070 1069 }
1071 1070 if (t.sms_data_order != SMS_DATA_ORDER) {
1072 1071 sbd_swap_section_hdr(&t);
1073 1072 }
1074 1073 if (t.sms_id != sms->sms_id) {
1075 1074 mutex_exit(&sl->sl_metadata_lock);
1076 1075 return (SBD_INVALID_ARG);
1077 1076 }
1078 1077 if (t.sms_size == sms->sms_size) {
1079 1078 ret = sbd_write_meta(sl, sms->sms_offset,
1080 1079 sms->sms_size, (uint8_t *)sms);
1081 1080 mutex_exit(&sl->sl_metadata_lock);
1082 1081 return (ret);
1083 1082 }
1084 1083 sms_before_unused = t;
1085 1084
1086 1085 t.sms_id = SMS_ID_UNUSED;
1087 1086 /*
1088 1087 * For unused sections we only use chksum of the header. for
1089 1088 * all other sections, the chksum is for the entire section.
1090 1089 */
1091 1090 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1092 1091 ret = sbd_write_meta(sl, t.sms_offset, sizeof (t),
1093 1092 (uint8_t *)&t);
1094 1093 if (ret != SBD_SUCCESS) {
1095 1094 mutex_exit(&sl->sl_metadata_lock);
1096 1095 return (ret);
1097 1096 }
1098 1097 sms->sms_offset = 0;
1099 1098 } else {
1100 1099 /* Section location is unknown, search for it. */
1101 1100 t.sms_id = sms->sms_id;
1102 1101 t.sms_data_order = SMS_DATA_ORDER;
1103 1102 ret = sbd_load_section_hdr(sl, &t);
1104 1103 if (ret == SBD_SUCCESS) {
1105 1104 sms->sms_offset = t.sms_offset;
1106 1105 sms->sms_chksum =
1107 1106 sbd_calc_section_sum(sms, sms->sms_size);
1108 1107 goto write_meta_section_again;
1109 1108 } else if (ret != SBD_NOT_FOUND) {
1110 1109 mutex_exit(&sl->sl_metadata_lock);
1111 1110 return (ret);
1112 1111 }
1113 1112 }
1114 1113
1115 1114 /*
1116 1115 * At this point we know that section does not already exist.
1117 1116 * Find space large enough to hold the section or grow meta if
1118 1117 * possible.
1119 1118 */
1120 1119 unused_start = 0;
1121 1120 s = 0; /* size of space found */
1122 1121
1123 1122 /*
1124 1123 * Search all sections for unused space of sufficient size.
1125 1124 * The first one found is taken. Contiguous unused sections
1126 1125 * will be combined.
1127 1126 */
1128 1127 for (off = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1129 1128 off < sl->sl_meta_size_used; off += t.sms_size) {
1130 1129 ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t);
1131 1130 if (ret != SBD_SUCCESS) {
1132 1131 mutex_exit(&sl->sl_metadata_lock);
1133 1132 return (ret);
1134 1133 }
1135 1134 if (t.sms_data_order != SMS_DATA_ORDER)
1136 1135 sbd_swap_section_hdr(&t);
1137 1136 if (t.sms_size == 0) {
1138 1137 mutex_exit(&sl->sl_metadata_lock);
1139 1138 return (SBD_META_CORRUPTED);
1140 1139 }
1141 1140 if (t.sms_id == SMS_ID_UNUSED) {
1142 1141 if (unused_start == 0)
1143 1142 unused_start = off;
1144 1143 /*
1145 1144 * Calculate size of the unused space, break out
1146 1145 * if it satisfies the requirement.
1147 1146 */
1148 1147 s = t.sms_size - unused_start + off;
1149 1148 if ((s == sms->sms_size) || (s >= (sms->sms_size +
1150 1149 sizeof (t)))) {
1151 1150 break;
1152 1151 } else {
1153 1152 s = 0;
1154 1153 }
1155 1154 } else {
1156 1155 unused_start = 0;
1157 1156 }
1158 1157 }
1159 1158
1160 1159 off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start;
1161 1160 /*
1162 1161 * If none found, how much room is at the end?
1163 1162 * See if the data can be expanded.
1164 1163 */
1165 1164 if (s == 0) {
1166 1165 s = sl->sl_total_meta_size - off;
1167 1166 if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) {
1168 1167 s = sms->sms_size;
1169 1168 meta_size_changed = 1;
1170 1169 } else {
1171 1170 s = 0;
1172 1171 }
1173 1172 }
1174 1173
1175 1174 if (s == 0) {
1176 1175 mutex_exit(&sl->sl_metadata_lock);
1177 1176 return (SBD_ALLOC_FAILURE);
1178 1177 }
1179 1178
1180 1179 sms->sms_offset = off;
1181 1180 sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size);
1182 1181 /*
1183 1182 * Since we may have to write more than one section (current +
1184 1183 * any unused), use a combined buffer.
1185 1184 */
1186 1185 cb = kmem_zalloc(s, KM_SLEEP);
1187 1186 bcopy(sms, cb, sms->sms_size);
1188 1187 if (s > sms->sms_size) {
1189 1188 t.sms_offset = off + sms->sms_size;
1190 1189 t.sms_size = s - sms->sms_size;
1191 1190 t.sms_id = SMS_ID_UNUSED;
1192 1191 t.sms_data_order = SMS_DATA_ORDER;
1193 1192 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1194 1193 bcopy(&t, cb + sms->sms_size, sizeof (t));
1195 1194 }
1196 1195 /*
1197 1196 * Two write events & statuses take place. Failure writing the
1198 1197 * meta section takes precedence, can possibly be rolled back,
1199 1198 * & gets reported. Else return status from writing the meta start.
1200 1199 */
1201 1200 ret = SBD_SUCCESS; /* Set a default, it's not always loaded below. */
1202 1201 if (meta_size_changed) {
1203 1202 uint64_t old_meta_size;
1204 1203 uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */
1205 1204 old_meta_size = sl->sl_total_meta_size; /* save a copy */
1206 1205
1207 1206 write_meta_ret = sbd_write_meta(sl, off, s, cb);
1208 1207 if (write_meta_ret == SBD_SUCCESS) {
1209 1208 sl->sl_meta_size_used = off + s;
1210 1209 if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
1211 1210 uint64_t meta_align =
1212 1211 (((uint64_t)1) <<
1213 1212 sl->sl_meta_blocksize_shift) - 1;
1214 1213 sl->sl_total_meta_size =
1215 1214 (sl->sl_meta_size_used + meta_align) &
1216 1215 (~meta_align);
1217 1216 }
1218 1217 ret = sbd_write_meta_start(sl, sl->sl_total_meta_size,
1219 1218 sl->sl_meta_size_used);
1220 1219 if (ret != SBD_SUCCESS) {
1221 1220 sl->sl_meta_size_used = old_sz_used;
1222 1221 sl->sl_total_meta_size = old_meta_size;
1223 1222 }
1224 1223 } else {
1225 1224 sl->sl_meta_size_used = old_sz_used;
1226 1225 sl->sl_total_meta_size = old_meta_size;
1227 1226 }
1228 1227 } else {
1229 1228 write_meta_ret = sbd_write_meta(sl, off, s, cb);
1230 1229 }
1231 1230 if ((write_meta_ret != SBD_SUCCESS) &&
1232 1231 (sms_before_unused.sms_offset != 0)) {
1233 1232 sm_section_hdr_t new_sms;
1234 1233 sm_section_hdr_t *unused_sms;
1235 1234 /*
1236 1235 * On failure writing the meta section attempt to undo
1237 1236 * the change to unused.
1238 1237 * Re-read the meta data from permanent storage.
1239 1238 * The section id can't exist for undo to be possible.
1240 1239 * Read what should be the entire old section data and
1241 1240 * insure the old data's still present by validating
1242 1241 * against it's old checksum.
1243 1242 */
1244 1243 new_sms.sms_id = sms->sms_id;
1245 1244 new_sms.sms_data_order = SMS_DATA_ORDER;
1246 1245 if (sbd_load_section_hdr_unbuffered(sl, &new_sms) !=
1247 1246 SBD_NOT_FOUND) {
1248 1247 goto done;
1249 1248 }
1250 1249 unused_sms = kmem_zalloc(sms_before_unused.sms_size, KM_SLEEP);
1251 1250 if (sbd_read_meta(sl, sms_before_unused.sms_offset,
1252 1251 sms_before_unused.sms_size,
1253 1252 (uint8_t *)unused_sms) != SBD_SUCCESS) {
1254 1253 goto done;
1255 1254 }
1256 1255 if (unused_sms->sms_data_order != SMS_DATA_ORDER) {
1257 1256 sbd_swap_section_hdr(unused_sms);
1258 1257 }
1259 1258 if (unused_sms->sms_id != SMS_ID_UNUSED) {
1260 1259 goto done;
1261 1260 }
1262 1261 if (unused_sms->sms_offset != sms_before_unused.sms_offset) {
1263 1262 goto done;
1264 1263 }
1265 1264 if (unused_sms->sms_size != sms_before_unused.sms_size) {
1266 1265 goto done;
1267 1266 }
1268 1267 unused_sms->sms_id = sms_before_unused.sms_id;
1269 1268 if (sbd_calc_section_sum(unused_sms,
1270 1269 sizeof (sm_section_hdr_t)) !=
1271 1270 sbd_calc_section_sum(&sms_before_unused,
1272 1271 sizeof (sm_section_hdr_t))) {
1273 1272 goto done;
1274 1273 }
1275 1274 unused_sms->sms_chksum =
1276 1275 sbd_calc_section_sum(unused_sms, unused_sms->sms_size);
1277 1276 if (unused_sms->sms_chksum != sms_before_unused.sms_chksum) {
1278 1277 goto done;
1279 1278 }
1280 1279 (void) sbd_write_meta(sl, unused_sms->sms_offset,
1281 1280 sizeof (sm_section_hdr_t), (uint8_t *)unused_sms);
1282 1281 }
1283 1282 done:
1284 1283 mutex_exit(&sl->sl_metadata_lock);
1285 1284 kmem_free(cb, s);
1286 1285 if (write_meta_ret != SBD_SUCCESS) {
1287 1286 return (write_meta_ret);
1288 1287 }
1289 1288 return (ret);
1290 1289 }
1291 1290
1292 1291 sbd_status_t
1293 1292 sbd_write_lu_info(sbd_lu_t *sl)
1294 1293 {
1295 1294 sbd_lu_info_1_1_t *sli;
1296 1295 int s;
1297 1296 uint8_t *p;
1298 1297 char *zvol_name = NULL;
1299 1298 sbd_status_t ret;
1300 1299
1301 1300 mutex_enter(&sl->sl_lock);
1302 1301
1303 1302 s = sl->sl_serial_no_size;
1304 1303 if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1305 1304 if (sl->sl_data_filename) {
1306 1305 s += strlen(sl->sl_data_filename) + 1;
1307 1306 }
1308 1307 }
1309 1308 if (sl->sl_flags & SL_ZFS_META) {
1310 1309 zvol_name = sbd_get_zvol_name(sl);
1311 1310 s += strlen(zvol_name) + 1;
1312 1311 }
1313 1312 if (sl->sl_alias) {
1314 1313 s += strlen(sl->sl_alias) + 1;
1315 1314 }
1316 1315 if (sl->sl_mgmt_url) {
1317 1316 s += strlen(sl->sl_mgmt_url) + 1;
1318 1317 }
1319 1318 sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
1320 1319 p = sli->sli_buf;
1321 1320 if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1322 1321 sli->sli_flags |= SLI_SEPARATE_META;
1323 1322 (void) strcpy((char *)p, sl->sl_data_filename);
1324 1323 sli->sli_data_fname_offset =
1325 1324 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1326 1325 sli->sli_flags |= SLI_DATA_FNAME_VALID;
1327 1326 p += strlen(sl->sl_data_filename) + 1;
1328 1327 }
1329 1328 if (sl->sl_flags & SL_ZFS_META) {
1330 1329 (void) strcpy((char *)p, zvol_name);
1331 1330 sli->sli_meta_fname_offset =
1332 1331 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1333 1332 sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META;
1334 1333 p += strlen(zvol_name) + 1;
1335 1334 kmem_free(zvol_name, strlen(zvol_name) + 1);
1336 1335 zvol_name = NULL;
1337 1336 }
1338 1337 if (sl->sl_alias) {
1339 1338 (void) strcpy((char *)p, sl->sl_alias);
1340 1339 sli->sli_alias_offset =
1341 1340 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1342 1341 sli->sli_flags |= SLI_ALIAS_VALID;
1343 1342 p += strlen(sl->sl_alias) + 1;
1344 1343 }
1345 1344 if (sl->sl_mgmt_url) {
1346 1345 (void) strcpy((char *)p, sl->sl_mgmt_url);
1347 1346 sli->sli_mgmt_url_offset =
1348 1347 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1349 1348 sli->sli_flags |= SLI_MGMT_URL_VALID;
1350 1349 p += strlen(sl->sl_mgmt_url) + 1;
1351 1350 }
1352 1351 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1353 1352 sli->sli_flags |= SLI_WRITE_PROTECTED;
1354 1353 }
1355 1354 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
1356 1355 sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
1357 1356 }
1358 1357 if (sl->sl_flags & SL_VID_VALID) {
1359 1358 bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
1360 1359 sli->sli_flags |= SLI_VID_VALID;
1361 1360 }
1362 1361 if (sl->sl_flags & SL_PID_VALID) {
1363 1362 bcopy(sl->sl_product_id, sli->sli_pid, 16);
1364 1363 sli->sli_flags |= SLI_PID_VALID;
1365 1364 }
1366 1365 if (sl->sl_flags & SL_REV_VALID) {
1367 1366 bcopy(sl->sl_revision, sli->sli_rev, 4);
1368 1367 sli->sli_flags |= SLI_REV_VALID;
1369 1368 }
1370 1369 if (sl->sl_serial_no_size) {
1371 1370 bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
1372 1371 sli->sli_serial_size = sl->sl_serial_no_size;
1373 1372 sli->sli_serial_offset =
1374 1373 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1375 1374 sli->sli_flags |= SLI_SERIAL_VALID;
1376 1375 p += sli->sli_serial_size;
1377 1376 }
1378 1377 sli->sli_lu_size = sl->sl_lu_size;
1379 1378 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1380 1379 sli->sli_data_order = SMS_DATA_ORDER;
1381 1380 bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1382 1381
1383 1382 sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1384 1383 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1385 1384 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1386 1385
1387 1386 mutex_exit(&sl->sl_lock);
1388 1387 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1389 1388 kmem_free(sli, sizeof (*sli) + s);
1390 1389 return (ret);
1391 1390 }
1392 1391
1393 1392 /*
1394 1393 * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
1395 1394 */
1396 1395 static void
1397 1396 do_unmap_setup(sbd_lu_t *sl)
1398 1397 {
1399 1398 ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
1400 1399
1401 1400 if ((sl->sl_flags & SL_ZFS_META) == 0)
1402 1401 return; /* No UNMAP for you. */
1403 1402
1404 1403 sl->sl_flags |= SL_UNMAP_ENABLED;
1405 1404 }
1406 1405
1407 1406 int
1408 1407 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1409 1408 {
1410 1409 stmf_lu_t *lu = sl->sl_lu;
1411 1410 stmf_status_t ret;
1412 1411
1413 1412 do_unmap_setup(sl);
1414 1413
1415 1414 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1416 1415 if (sl->sl_alias) {
1417 1416 lu->lu_alias = sl->sl_alias;
1418 1417 } else {
1419 1418 lu->lu_alias = sl->sl_name;
1420 1419 }
1421 1420 if (sl->sl_access_state == SBD_LU_STANDBY) {
1422 1421 /* call set access state */
1423 1422 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1424 1423 if (ret != STMF_SUCCESS) {
1425 1424 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1426 1425 return (EIO);
1427 1426 }
1428 1427 }
1429 1428 /* set proxy_reg_cb_arg to meta filename */
1430 1429 if (sl->sl_meta_filename) {
1431 1430 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1432 1431 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1433 1432 } else {
1434 1433 lu->lu_proxy_reg_arg = sl->sl_data_filename;
1435 1434 lu->lu_proxy_reg_arg_len = strlen(sl->sl_data_filename) + 1;
1436 1435 }
1437 1436 lu->lu_lp = sbd_lp;
1438 1437 lu->lu_task_alloc = sbd_task_alloc;
1439 1438 lu->lu_new_task = sbd_new_task;
1440 1439 lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1441 1440 lu->lu_send_status_done = sbd_send_status_done;
1442 1441 lu->lu_task_free = sbd_task_free;
1443 1442 lu->lu_abort = sbd_abort;
1444 1443 lu->lu_dbuf_free = sbd_dbuf_free;
1445 1444 lu->lu_ctl = sbd_ctl;
1446 1445 lu->lu_info = sbd_info;
1447 1446 sl->sl_state = STMF_STATE_OFFLINE;
1448 1447
1449 1448 if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1450 1449 stmf_trace(0, "Failed to register with framework, ret=%llx",
1451 1450 ret);
1452 1451 if (ret == STMF_ALREADY) {
1453 1452 *err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
1454 1453 }
1455 1454 return (EIO);
1456 1455 }
1457 1456
1458 1457 *err_ret = 0;
1459 1458 return (0);
1460 1459 }
1461 1460
1462 1461 int
1463 1462 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
1464 1463 int vp_valid, int keep_open)
1465 1464 {
1466 1465 int ret;
1467 1466 int flag;
1468 1467 ulong_t nbits;
1469 1468 uint64_t supported_size;
1470 1469 vattr_t vattr;
1471 1470 enum vtype vt;
1472 1471 struct dk_cinfo dki;
1473 1472 int unused;
1474 1473
1475 1474 mutex_enter(&sl->sl_lock);
1476 1475 if (vp_valid) {
1477 1476 goto odf_over_open;
1478 1477 }
1479 1478 if (sl->sl_data_filename[0] != '/') {
1480 1479 *err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
1481 1480 mutex_exit(&sl->sl_lock);
1482 1481 return (EINVAL);
1483 1482 }
1484 1483 if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
1485 1484 NULLVPP, &sl->sl_data_vp)) != 0) {
1486 1485 *err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
1487 1486 mutex_exit(&sl->sl_lock);
1488 1487 return (ret);
1489 1488 }
1490 1489 sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
1491 1490 VN_RELE(sl->sl_data_vp);
1492 1491 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1493 1492 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1494 1493 mutex_exit(&sl->sl_lock);
1495 1494 return (EINVAL);
1496 1495 }
1497 1496 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1498 1497 flag = FREAD | FOFFMAX;
1499 1498 } else {
1500 1499 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1501 1500 }
1502 1501 if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
1503 1502 &sl->sl_data_vp, 0, 0)) != 0) {
1504 1503 *err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
1505 1504 mutex_exit(&sl->sl_lock);
1506 1505 return (ret);
1507 1506 }
1508 1507 odf_over_open:
1509 1508 vattr.va_mask = AT_SIZE;
1510 1509 if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
1511 1510 *err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
1512 1511 goto odf_close_data_and_exit;
1513 1512 }
1514 1513 if ((vt != VREG) && (vattr.va_size == 0)) {
1515 1514 /*
1516 1515 * Its a zero byte block or char device. This cannot be
1517 1516 * a raw disk.
1518 1517 */
1519 1518 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1520 1519 ret = EINVAL;
1521 1520 goto odf_close_data_and_exit;
1522 1521 }
1523 1522 /* sl_data_readable size includes any metadata. */
1524 1523 sl->sl_data_readable_size = vattr.va_size;
1525 1524
1526 1525 if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
1527 1526 CRED(), NULL) != 0) {
1528 1527 nbits = 0;
1529 1528 }
1530 1529 /* nbits cannot be greater than 64 */
1531 1530 sl->sl_data_fs_nbits = (uint8_t)nbits;
1532 1531 if (lu_size_valid) {
1533 1532 sl->sl_total_data_size = sl->sl_lu_size;
1534 1533 if (sl->sl_flags & SL_SHARED_META) {
1535 1534 sl->sl_total_data_size += SHARED_META_DATA_SIZE;
1536 1535 }
1537 1536 if ((nbits > 0) && (nbits < 64)) {
1538 1537 /*
1539 1538 * The expression below is correct only if nbits is
1540 1539 * positive and less than 64.
1541 1540 */
1542 1541 supported_size = (((uint64_t)1) << nbits) - 1;
1543 1542 if (sl->sl_total_data_size > supported_size) {
1544 1543 *err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
1545 1544 ret = EINVAL;
1546 1545 goto odf_close_data_and_exit;
1547 1546 }
1548 1547 }
1549 1548 } else {
1550 1549 sl->sl_total_data_size = vattr.va_size;
1551 1550 if (sl->sl_flags & SL_SHARED_META) {
1552 1551 if (vattr.va_size > SHARED_META_DATA_SIZE) {
1553 1552 sl->sl_lu_size = vattr.va_size -
1554 1553 SHARED_META_DATA_SIZE;
1555 1554 } else {
1556 1555 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1557 1556 ret = EINVAL;
1558 1557 goto odf_close_data_and_exit;
1559 1558 }
1560 1559 } else {
1561 1560 sl->sl_lu_size = vattr.va_size;
1562 1561 }
1563 1562 }
1564 1563 if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
1565 1564 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1566 1565 ret = EINVAL;
1567 1566 goto odf_close_data_and_exit;
1568 1567 }
1569 1568 if (sl->sl_lu_size &
1570 1569 ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
1571 1570 *err_ret = SBD_RET_FILE_ALIGN_ERROR;
1572 1571 ret = EINVAL;
1573 1572 goto odf_close_data_and_exit;
1574 1573 }
1575 1574 /*
1576 1575 * Get the minor device for direct zvol access
1577 1576 */
1578 1577 if (sl->sl_flags & SL_ZFS_META) {
1579 1578 if ((ret = VOP_IOCTL(sl->sl_data_vp, DKIOCINFO, (intptr_t)&dki,
1580 1579 FKIOCTL, kcred, &unused, NULL)) != 0) {
1581 1580 cmn_err(CE_WARN, "ioctl(DKIOCINFO) failed %d", ret);
1582 1581 /* zvol reserves 0, so this would fail later */
1583 1582 sl->sl_zvol_minor = 0;
1584 1583 } else {
1585 1584 sl->sl_zvol_minor = dki.dki_unit;
1586 1585 if (sbd_zvol_get_volume_params(sl) == 0)
1587 1586 sl->sl_flags |= SL_CALL_ZVOL;
1588 1587 }
1589 1588 }
1590 1589 sl->sl_flags |= SL_MEDIA_LOADED;
1591 1590 mutex_exit(&sl->sl_lock);
1592 1591 return (0);
1593 1592
1594 1593 odf_close_data_and_exit:
1595 1594 if (!keep_open) {
1596 1595 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1597 1596 VN_RELE(sl->sl_data_vp);
1598 1597 }
1599 1598 mutex_exit(&sl->sl_lock);
1600 1599 return (ret);
1601 1600 }
1602 1601
1603 1602 void
1604 1603 sbd_close_lu(sbd_lu_t *sl)
1605 1604 {
1606 1605 int flag;
1607 1606
1608 1607 if (((sl->sl_flags & SL_SHARED_META) == 0) &&
1609 1608 (sl->sl_flags & SL_META_OPENED)) {
1610 1609 if (sl->sl_flags & SL_ZFS_META) {
1611 1610 rw_destroy(&sl->sl_zfs_meta_lock);
1612 1611 if (sl->sl_zfs_meta) {
1613 1612 kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2);
1614 1613 sl->sl_zfs_meta = NULL;
1615 1614 }
1616 1615 } else {
1617 1616 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1618 1617 (void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
1619 1618 CRED(), NULL);
1620 1619 VN_RELE(sl->sl_meta_vp);
1621 1620 }
1622 1621 sl->sl_flags &= ~SL_META_OPENED;
1623 1622 }
1624 1623 if (sl->sl_flags & SL_MEDIA_LOADED) {
1625 1624 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1626 1625 flag = FREAD | FOFFMAX;
1627 1626 } else {
1628 1627 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1629 1628 }
1630 1629 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1631 1630 VN_RELE(sl->sl_data_vp);
1632 1631 sl->sl_flags &= ~SL_MEDIA_LOADED;
1633 1632 if (sl->sl_flags & SL_SHARED_META) {
1634 1633 sl->sl_flags &= ~SL_META_OPENED;
1635 1634 }
1636 1635 }
1637 1636 }
1638 1637
1639 1638 int
1640 1639 sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret)
1641 1640 {
1642 1641 sbd_lu_t *sl;
1643 1642 sbd_status_t sret;
1644 1643 stmf_status_t stret;
1645 1644 uint8_t old_access_state;
1646 1645
1647 1646 sret = sbd_find_and_lock_lu(stlu->stlu_guid, NULL,
1648 1647 SL_OP_MODIFY_LU, &sl);
1649 1648 if (sret != SBD_SUCCESS) {
1650 1649 if (sret == SBD_BUSY) {
1651 1650 *err_ret = SBD_RET_LU_BUSY;
1652 1651 return (EBUSY);
1653 1652 } else if (sret == SBD_NOT_FOUND) {
1654 1653 *err_ret = SBD_RET_NOT_FOUND;
1655 1654 return (ENOENT);
1656 1655 }
1657 1656 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1658 1657 return (EIO);
1659 1658 }
1660 1659
1661 1660 old_access_state = sl->sl_access_state;
1662 1661 sl->sl_access_state = SBD_LU_TRANSITION_TO_STANDBY;
1663 1662 stret = stmf_set_lu_access((stmf_lu_t *)sl->sl_lu, STMF_LU_STANDBY);
1664 1663 if (stret != STMF_SUCCESS) {
1665 1664 sl->sl_trans_op = SL_OP_NONE;
1666 1665 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1667 1666 sl->sl_access_state = old_access_state;
1668 1667 return (EIO);
1669 1668 }
1670 1669
1671 1670 /*
1672 1671 * acquire the writer lock here to ensure we're not pulling
1673 1672 * the rug from the vn_rdwr to the backing store
1674 1673 */
1675 1674 rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1676 1675 sbd_close_lu(sl);
1677 1676 rw_exit(&sl->sl_access_state_lock);
1678 1677
1679 1678 sl->sl_trans_op = SL_OP_NONE;
1680 1679 return (0);
1681 1680 }
1682 1681
1683 1682 int
1684 1683 sbd_close_delete_lu(sbd_lu_t *sl, int ret)
1685 1684 {
1686 1685
1687 1686 /*
1688 1687 * acquire the writer lock here to ensure we're not pulling
1689 1688 * the rug from the vn_rdwr to the backing store
1690 1689 */
1691 1690 rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1692 1691 sbd_close_lu(sl);
1693 1692 rw_exit(&sl->sl_access_state_lock);
1694 1693
1695 1694 if (sl->sl_flags & SL_LINKED)
1696 1695 sbd_unlink_lu(sl);
1697 1696 mutex_destroy(&sl->sl_metadata_lock);
1698 1697 mutex_destroy(&sl->sl_lock);
1699 1698 rw_destroy(&sl->sl_pgr->pgr_lock);
1700 1699 rw_destroy(&sl->sl_access_state_lock);
1701 1700 if (sl->sl_serial_no_alloc_size) {
1702 1701 kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
1703 1702 }
1704 1703 if (sl->sl_data_fname_alloc_size) {
1705 1704 kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
1706 1705 }
1707 1706 if (sl->sl_alias_alloc_size) {
1708 1707 kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
1709 1708 }
1710 1709 if (sl->sl_mgmt_url_alloc_size) {
1711 1710 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
1712 1711 }
1713 1712 stmf_free(sl->sl_lu);
1714 1713 return (ret);
1715 1714 }
1716 1715
1717 1716 int
1718 1717 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
1719 1718 uint32_t *err_ret)
1720 1719 {
1721 1720 char *namebuf;
1722 1721 sbd_lu_t *sl;
1723 1722 stmf_lu_t *lu;
1724 1723 char *p;
1725 1724 int sz;
1726 1725 int alloc_sz;
1727 1726 int ret = EIO;
1728 1727 int flag;
1729 1728 int wcd = 0;
1730 1729 uint32_t hid = 0;
1731 1730 enum vtype vt;
1732 1731
1733 1732 sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
1734 1733
1735 1734 *err_ret = 0;
1736 1735
1737 1736 /* Lets validate various offsets */
1738 1737 if (((slu->slu_meta_fname_valid) &&
1739 1738 (slu->slu_meta_fname_off >= sz)) ||
1740 1739 (slu->slu_data_fname_off >= sz) ||
1741 1740 ((slu->slu_alias_valid) &&
1742 1741 (slu->slu_alias_off >= sz)) ||
1743 1742 ((slu->slu_mgmt_url_valid) &&
1744 1743 (slu->slu_mgmt_url_off >= sz)) ||
1745 1744 ((slu->slu_serial_valid) &&
1746 1745 ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
1747 1746 return (EINVAL);
1748 1747 }
1749 1748
1750 1749 namebuf = kmem_zalloc(sz, KM_SLEEP);
1751 1750 bcopy(slu->slu_buf, namebuf, sz - 1);
1752 1751 namebuf[sz - 1] = 0;
1753 1752
1754 1753 alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1755 1754 if (slu->slu_meta_fname_valid) {
1756 1755 alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
1757 1756 }
1758 1757 alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
1759 1758 if (slu->slu_alias_valid) {
1760 1759 alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
1761 1760 }
1762 1761 if (slu->slu_mgmt_url_valid) {
1763 1762 alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
1764 1763 }
1765 1764 if (slu->slu_serial_valid) {
1766 1765 alloc_sz += slu->slu_serial_size;
1767 1766 }
1768 1767
1769 1768 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
1770 1769 if (lu == NULL) {
1771 1770 kmem_free(namebuf, sz);
1772 1771 return (ENOMEM);
1773 1772 }
1774 1773 sl = (sbd_lu_t *)lu->lu_provider_private;
1775 1774 bzero(sl, alloc_sz);
1776 1775 sl->sl_lu = lu;
1777 1776 sl->sl_alloc_size = alloc_sz;
1778 1777 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1779 1778 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1780 1779 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1781 1780 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
1782 1781 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
1783 1782 p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1784 1783 sl->sl_data_filename = p;
1785 1784 (void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
1786 1785 p += strlen(sl->sl_data_filename) + 1;
1787 1786 sl->sl_meta_offset = SBD_META_OFFSET;
1788 1787 sl->sl_access_state = SBD_LU_ACTIVE;
1789 1788 if (slu->slu_meta_fname_valid) {
1790 1789 sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
1791 1790 (void) strcpy(sl->sl_meta_filename, namebuf +
1792 1791 slu->slu_meta_fname_off);
1793 1792 p += strlen(sl->sl_meta_filename) + 1;
1794 1793 } else {
1795 1794 sl->sl_alias = sl->sl_name = sl->sl_data_filename;
1796 1795 if (sbd_is_zvol(sl->sl_data_filename)) {
1797 1796 sl->sl_flags |= SL_ZFS_META;
1798 1797 sl->sl_meta_offset = 0;
1799 1798 } else {
1800 1799 sl->sl_flags |= SL_SHARED_META;
1801 1800 sl->sl_data_offset = SHARED_META_DATA_SIZE;
1802 1801 sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
1803 1802 sl->sl_meta_size_used = 0;
1804 1803 }
1805 1804 }
1806 1805 if (slu->slu_alias_valid) {
1807 1806 sl->sl_alias = p;
1808 1807 (void) strcpy(p, namebuf + slu->slu_alias_off);
1809 1808 p += strlen(sl->sl_alias) + 1;
1810 1809 }
1811 1810 if (slu->slu_mgmt_url_valid) {
1812 1811 sl->sl_mgmt_url = p;
1813 1812 (void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
1814 1813 p += strlen(sl->sl_mgmt_url) + 1;
1815 1814 }
1816 1815 if (slu->slu_serial_valid) {
1817 1816 sl->sl_serial_no = (uint8_t *)p;
1818 1817 bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
1819 1818 slu->slu_serial_size);
1820 1819 sl->sl_serial_no_size = slu->slu_serial_size;
1821 1820 p += slu->slu_serial_size;
1822 1821 }
1823 1822 kmem_free(namebuf, sz);
1824 1823 if (slu->slu_vid_valid) {
1825 1824 bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
1826 1825 sl->sl_flags |= SL_VID_VALID;
1827 1826 }
1828 1827 if (slu->slu_pid_valid) {
1829 1828 bcopy(slu->slu_pid, sl->sl_product_id, 16);
1830 1829 sl->sl_flags |= SL_PID_VALID;
1831 1830 }
1832 1831 if (slu->slu_rev_valid) {
1833 1832 bcopy(slu->slu_rev, sl->sl_revision, 4);
1834 1833 sl->sl_flags |= SL_REV_VALID;
1835 1834 }
1836 1835 if (slu->slu_write_protected) {
1837 1836 sl->sl_flags |= SL_WRITE_PROTECTED;
1838 1837 }
1839 1838 if (slu->slu_blksize_valid) {
1840 1839 if (!ISP2(slu->slu_blksize) ||
1841 1840 (slu->slu_blksize > (32 * 1024)) ||
1842 1841 (slu->slu_blksize == 0)) {
1843 1842 *err_ret = SBD_RET_INVALID_BLKSIZE;
1844 1843 ret = EINVAL;
1845 1844 goto scm_err_out;
1846 1845 }
1847 1846 while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
1848 1847 sl->sl_data_blocksize_shift++;
1849 1848 }
1850 1849 } else {
1851 1850 sl->sl_data_blocksize_shift = 9; /* 512 by default */
1852 1851 slu->slu_blksize = 512;
1853 1852 }
1854 1853
1855 1854 /* Now lets start creating meta */
1856 1855 sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
1857 1856 if (sbd_link_lu(sl) != SBD_SUCCESS) {
1858 1857 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1859 1858 ret = EALREADY;
1860 1859 goto scm_err_out;
1861 1860 }
1862 1861
1863 1862 /* 1st focus on the data store */
1864 1863 if (slu->slu_lu_size_valid) {
1865 1864 sl->sl_lu_size = slu->slu_lu_size;
1866 1865 }
1867 1866 ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
1868 1867 slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
1869 1868 slu->slu_lu_size = sl->sl_lu_size;
1870 1869 if (ret) {
1871 1870 goto scm_err_out;
1872 1871 }
1873 1872
1874 1873 /*
1875 1874 * Check if we were explicitly asked to disable/enable write
1876 1875 * cache on the device, otherwise get current device setting.
1877 1876 */
1878 1877 if (slu->slu_writeback_cache_disable_valid) {
1879 1878 if (slu->slu_writeback_cache_disable) {
1880 1879 /*
1881 1880 * Set write cache disable on the device. If it fails,
1882 1881 * we'll support it using sync/flush.
1883 1882 */
1884 1883 (void) sbd_wcd_set(1, sl);
1885 1884 wcd = 1;
1886 1885 } else {
1887 1886 /*
1888 1887 * Set write cache enable on the device. If it fails,
1889 1888 * return an error.
1890 1889 */
1891 1890 if (sbd_wcd_set(0, sl) != SBD_SUCCESS) {
1892 1891 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
1893 1892 ret = EFAULT;
1894 1893 goto scm_err_out;
1895 1894 }
1896 1895 }
1897 1896 } else {
1898 1897 sbd_wcd_get(&wcd, sl);
1899 1898 }
1900 1899
1901 1900 if (wcd) {
1902 1901 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1903 1902 SL_SAVED_WRITE_CACHE_DISABLE;
1904 1903 }
1905 1904
1906 1905 if (sl->sl_flags & SL_SHARED_META) {
1907 1906 goto over_meta_open;
1908 1907 }
1909 1908 if (sl->sl_flags & SL_ZFS_META) {
1910 1909 if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
1911 1910 *err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
1912 1911 ret = ENOMEM;
1913 1912 goto scm_err_out;
1914 1913 }
1915 1914 sl->sl_meta_blocksize_shift = 0;
1916 1915 goto over_meta_create;
1917 1916 }
1918 1917 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1919 1918 NULLVPP, &sl->sl_meta_vp)) != 0) {
1920 1919 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1921 1920 goto scm_err_out;
1922 1921 }
1923 1922 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1924 1923 VN_RELE(sl->sl_meta_vp);
1925 1924 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1926 1925 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1927 1926 ret = EINVAL;
1928 1927 goto scm_err_out;
1929 1928 }
1930 1929 if (vt == VREG) {
1931 1930 sl->sl_meta_blocksize_shift = 0;
1932 1931 } else {
1933 1932 sl->sl_meta_blocksize_shift = 9;
1934 1933 }
1935 1934 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1936 1935 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1937 1936 &sl->sl_meta_vp, 0, 0)) != 0) {
1938 1937 *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1939 1938 goto scm_err_out;
1940 1939 }
1941 1940 over_meta_create:
1942 1941 sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1943 1942 sl->sl_total_meta_size +=
1944 1943 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1945 1944 sl->sl_total_meta_size &=
1946 1945 ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
1947 1946 sl->sl_meta_size_used = 0;
1948 1947 over_meta_open:
1949 1948 sl->sl_flags |= SL_META_OPENED;
1950 1949
1951 1950 sl->sl_device_id[3] = 16;
1952 1951 if (slu->slu_guid_valid) {
1953 1952 sl->sl_device_id[0] = 0xf1;
1954 1953 sl->sl_device_id[1] = 3;
1955 1954 sl->sl_device_id[2] = 0;
1956 1955 bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
1957 1956 } else {
1958 1957 if (slu->slu_host_id_valid)
1959 1958 hid = slu->slu_host_id;
1960 1959 if (!slu->slu_company_id_valid)
1961 1960 slu->slu_company_id = COMPANY_ID_SUN;
1962 1961 if (stmf_scsilib_uniq_lu_id2(slu->slu_company_id, hid,
1963 1962 (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
1964 1963 STMF_SUCCESS) {
1965 1964 *err_ret = SBD_RET_META_CREATION_FAILED;
1966 1965 ret = EIO;
1967 1966 goto scm_err_out;
1968 1967 }
1969 1968 bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
1970 1969 }
1971 1970
1972 1971 /* Lets create the meta now */
1973 1972 mutex_enter(&sl->sl_metadata_lock);
1974 1973 if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
1975 1974 sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
1976 1975 mutex_exit(&sl->sl_metadata_lock);
1977 1976 *err_ret = SBD_RET_META_CREATION_FAILED;
1978 1977 ret = EIO;
1979 1978 goto scm_err_out;
1980 1979 }
1981 1980 mutex_exit(&sl->sl_metadata_lock);
1982 1981 sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1983 1982
1984 1983 if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
1985 1984 *err_ret = SBD_RET_META_CREATION_FAILED;
1986 1985 ret = EIO;
1987 1986 goto scm_err_out;
1988 1987 }
1989 1988
1990 1989 if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) {
1991 1990 *err_ret = SBD_RET_META_CREATION_FAILED;
1992 1991 ret = EIO;
1993 1992 goto scm_err_out;
1994 1993 }
1995 1994
1996 1995 /*
1997 1996 * Update the zvol separately as this need only be called upon
1998 1997 * completion of the metadata initialization.
1999 1998 */
2000 1999 if (sl->sl_flags & SL_ZFS_META) {
2001 2000 if (sbd_update_zfs_prop(sl) != SBD_SUCCESS) {
2002 2001 *err_ret = SBD_RET_META_CREATION_FAILED;
2003 2002 ret = EIO;
2004 2003 goto scm_err_out;
2005 2004 }
2006 2005 }
2007 2006
2008 2007 ret = sbd_populate_and_register_lu(sl, err_ret);
2009 2008 if (ret) {
2010 2009 goto scm_err_out;
2011 2010 }
2012 2011
2013 2012 sl->sl_trans_op = SL_OP_NONE;
2014 2013 atomic_inc_32(&sbd_lu_count);
2015 2014 return (0);
2016 2015
2017 2016 scm_err_out:
2018 2017 return (sbd_close_delete_lu(sl, ret));
2019 2018 }
2020 2019
2021 2020 stmf_status_t
2022 2021 sbd_proxy_msg(uint8_t *luid, void *proxy_arg, uint32_t proxy_arg_len,
2023 2022 uint32_t type)
2024 2023 {
2025 2024 switch (type) {
2026 2025 case STMF_MSG_LU_ACTIVE:
2027 2026 return (sbd_proxy_reg_lu(luid, proxy_arg,
2028 2027 proxy_arg_len));
2029 2028 case STMF_MSG_LU_REGISTER:
2030 2029 return (sbd_proxy_reg_lu(luid, proxy_arg,
2031 2030 proxy_arg_len));
2032 2031 case STMF_MSG_LU_DEREGISTER:
2033 2032 return (sbd_proxy_dereg_lu(luid, proxy_arg,
2034 2033 proxy_arg_len));
2035 2034 default:
2036 2035 return (STMF_INVALID_ARG);
2037 2036 }
2038 2037 }
2039 2038
2040 2039
2041 2040 /*
2042 2041 * register a standby logical unit
2043 2042 * proxy_reg_arg contains the meta filename
2044 2043 */
2045 2044 stmf_status_t
2046 2045 sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg, uint32_t proxy_reg_arg_len)
2047 2046 {
2048 2047 sbd_lu_t *sl;
2049 2048 sbd_status_t sret;
2050 2049 sbd_create_standby_lu_t *stlu;
2051 2050 int alloc_sz;
2052 2051 uint32_t err_ret = 0;
2053 2052 stmf_status_t stret = STMF_SUCCESS;
2054 2053
2055 2054 if (luid == NULL) {
2056 2055 return (STMF_INVALID_ARG);
2057 2056 }
2058 2057
2059 2058 do {
2060 2059 sret = sbd_find_and_lock_lu(luid, NULL, SL_OP_MODIFY_LU, &sl);
2061 2060 } while (sret == SBD_BUSY);
2062 2061
2063 2062 if (sret == SBD_NOT_FOUND) {
2064 2063 alloc_sz = sizeof (*stlu) + proxy_reg_arg_len - 8;
2065 2064 stlu = (sbd_create_standby_lu_t *)kmem_zalloc(alloc_sz,
2066 2065 KM_SLEEP);
2067 2066 bcopy(luid, stlu->stlu_guid, 16);
2068 2067 if (proxy_reg_arg_len) {
2069 2068 bcopy(proxy_reg_arg, stlu->stlu_meta_fname,
2070 2069 proxy_reg_arg_len);
2071 2070 stlu->stlu_meta_fname_size = proxy_reg_arg_len;
2072 2071 }
2073 2072 if (sbd_create_standby_lu(stlu, &err_ret) != 0) {
2074 2073 cmn_err(CE_WARN,
2075 2074 "Unable to create standby logical unit for %s",
2076 2075 stlu->stlu_meta_fname);
2077 2076 stret = STMF_FAILURE;
2078 2077 }
2079 2078 kmem_free(stlu, alloc_sz);
2080 2079 return (stret);
2081 2080 } else if (sret == SBD_SUCCESS) {
2082 2081 /*
2083 2082 * if the lu is already registered, then the lu should now
2084 2083 * be in standby mode
2085 2084 */
2086 2085 sbd_it_data_t *it;
2087 2086 if (sl->sl_access_state != SBD_LU_STANDBY) {
2088 2087 mutex_enter(&sl->sl_lock);
2089 2088 sl->sl_access_state = SBD_LU_STANDBY;
2090 2089 for (it = sl->sl_it_list; it != NULL;
2091 2090 it = it->sbd_it_next) {
2092 2091 it->sbd_it_ua_conditions |=
2093 2092 SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2094 2093 it->sbd_it_flags &=
2095 2094 ~SBD_IT_HAS_SCSI2_RESERVATION;
2096 2095 sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
2097 2096 }
2098 2097 mutex_exit(&sl->sl_lock);
2099 2098 sbd_pgr_reset(sl);
2100 2099 }
2101 2100 sl->sl_trans_op = SL_OP_NONE;
2102 2101 } else {
2103 2102 cmn_err(CE_WARN, "could not find and lock logical unit");
2104 2103 stret = STMF_FAILURE;
2105 2104 }
2106 2105 out:
2107 2106 return (stret);
2108 2107 }
2109 2108
2110 2109 /* ARGSUSED */
2111 2110 stmf_status_t
2112 2111 sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
2113 2112 uint32_t proxy_reg_arg_len)
2114 2113 {
2115 2114 sbd_delete_lu_t dlu = {0};
2116 2115 uint32_t err_ret;
2117 2116
2118 2117 if (luid == NULL) {
2119 2118 cmn_err(CE_WARN, "de-register lu request had null luid");
2120 2119 return (STMF_INVALID_ARG);
2121 2120 }
2122 2121
2123 2122 bcopy(luid, &dlu.dlu_guid, 16);
2124 2123
2125 2124 if (sbd_delete_lu(&dlu, (int)sizeof (dlu), &err_ret) != 0) {
2126 2125 cmn_err(CE_WARN, "failed to delete de-register lu request");
2127 2126 return (STMF_FAILURE);
2128 2127 }
2129 2128
2130 2129 return (STMF_SUCCESS);
2131 2130 }
2132 2131
2133 2132 int
2134 2133 sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret)
2135 2134 {
2136 2135 sbd_lu_t *sl;
2137 2136 stmf_lu_t *lu;
2138 2137 int ret = EIO;
2139 2138 int alloc_sz;
2140 2139
2141 2140 alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) +
2142 2141 slu->stlu_meta_fname_size;
2143 2142 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
2144 2143 if (lu == NULL) {
2145 2144 return (ENOMEM);
2146 2145 }
2147 2146 sl = (sbd_lu_t *)lu->lu_provider_private;
2148 2147 bzero(sl, alloc_sz);
2149 2148 sl->sl_lu = lu;
2150 2149 sl->sl_alloc_size = alloc_sz;
2151 2150
2152 2151 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2153 2152 sl->sl_meta_filename = ((char *)sl) + sizeof (sbd_lu_t) +
2154 2153 sizeof (sbd_pgr_t);
2155 2154
2156 2155 if (slu->stlu_meta_fname_size > 0) {
2157 2156 (void) strcpy(sl->sl_meta_filename, slu->stlu_meta_fname);
2158 2157 }
2159 2158 sl->sl_name = sl->sl_meta_filename;
2160 2159
2161 2160 sl->sl_device_id[3] = 16;
2162 2161 sl->sl_device_id[0] = 0xf1;
2163 2162 sl->sl_device_id[1] = 3;
2164 2163 sl->sl_device_id[2] = 0;
2165 2164 bcopy(slu->stlu_guid, sl->sl_device_id + 4, 16);
2166 2165 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
2167 2166 sl->sl_access_state = SBD_LU_STANDBY;
2168 2167
2169 2168 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2170 2169 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2171 2170 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2172 2171 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2173 2172
2174 2173 sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
2175 2174
2176 2175 if (sbd_link_lu(sl) != SBD_SUCCESS) {
2177 2176 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2178 2177 ret = EALREADY;
2179 2178 goto scs_err_out;
2180 2179 }
2181 2180
2182 2181 ret = sbd_populate_and_register_lu(sl, err_ret);
2183 2182 if (ret) {
2184 2183 goto scs_err_out;
2185 2184 }
2186 2185
2187 2186 sl->sl_trans_op = SL_OP_NONE;
2188 2187 atomic_inc_32(&sbd_lu_count);
2189 2188 return (0);
2190 2189
2191 2190 scs_err_out:
2192 2191 return (sbd_close_delete_lu(sl, ret));
2193 2192 }
2194 2193
2195 2194 int
2196 2195 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
2197 2196 {
2198 2197 sbd_lu_info_1_0_t *sli = NULL;
2199 2198 sbd_status_t sret;
2200 2199
2201 2200 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2202 2201 SMS_ID_LU_INFO_1_0);
2203 2202
2204 2203 if (sret != SBD_SUCCESS) {
2205 2204 *err_ret = SBD_RET_NO_META;
2206 2205 return (EIO);
2207 2206 }
2208 2207 if (sli->sli_data_order != SMS_DATA_ORDER) {
2209 2208 sbd_swap_lu_info_1_0(sli);
2210 2209 if (sli->sli_data_order != SMS_DATA_ORDER) {
2211 2210 kmem_free(sli, sli->sli_sms_header.sms_size);
2212 2211 *err_ret = SBD_RET_NO_META;
2213 2212 return (EIO);
2214 2213 }
2215 2214 }
2216 2215
2217 2216 sl->sl_flags |= SL_SHARED_META;
2218 2217 sl->sl_data_blocksize_shift = 9;
2219 2218 sl->sl_data_offset = SHARED_META_DATA_SIZE;
2220 2219 sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
2221 2220 sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
2222 2221 bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
2223 2222
2224 2223 kmem_free(sli, sli->sli_sms_header.sms_size);
2225 2224 return (0);
2226 2225 }
2227 2226
2228 2227 int
2229 2228 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
2230 2229 int no_register, sbd_lu_t **slr)
2231 2230 {
2232 2231 stmf_lu_t *lu;
2233 2232 sbd_lu_t *sl;
2234 2233 sbd_lu_info_1_1_t *sli = NULL;
2235 2234 int asz;
2236 2235 int ret = 0;
2237 2236 stmf_status_t stret;
2238 2237 int flag;
2239 2238 int wcd = 0;
2240 2239 int data_opened;
2241 2240 uint16_t sli_buf_sz;
2242 2241 uint8_t *sli_buf_copy = NULL;
2243 2242 enum vtype vt;
2244 2243 int standby = 0;
2245 2244 sbd_status_t sret;
2246 2245
2247 2246 if (no_register && slr == NULL) {
2248 2247 return (EINVAL);
2249 2248 }
2250 2249 ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
2251 2250 /*
2252 2251 * check whether logical unit is already registered ALUA
2253 2252 * For a standby logical unit, the meta filename is set. Use
2254 2253 * that to search for an existing logical unit.
2255 2254 */
2256 2255 sret = sbd_find_and_lock_lu(NULL, (uint8_t *)&(ilu->ilu_meta_fname),
2257 2256 SL_OP_IMPORT_LU, &sl);
2258 2257
2259 2258 if (sret == SBD_SUCCESS) {
2260 2259 if (sl->sl_access_state != SBD_LU_ACTIVE) {
2261 2260 no_register = 1;
2262 2261 standby = 1;
2263 2262 lu = sl->sl_lu;
2264 2263 if (sl->sl_alias_alloc_size) {
2265 2264 kmem_free(sl->sl_alias,
2266 2265 sl->sl_alias_alloc_size);
2267 2266 sl->sl_alias_alloc_size = 0;
2268 2267 sl->sl_alias = NULL;
2269 2268 lu->lu_alias = NULL;
2270 2269 }
2271 2270 if (sl->sl_meta_filename == NULL) {
2272 2271 sl->sl_meta_filename = sl->sl_data_filename;
2273 2272 } else if (sl->sl_data_fname_alloc_size) {
2274 2273 kmem_free(sl->sl_data_filename,
2275 2274 sl->sl_data_fname_alloc_size);
2276 2275 sl->sl_data_fname_alloc_size = 0;
2277 2276 }
2278 2277 if (sl->sl_serial_no_alloc_size) {
2279 2278 kmem_free(sl->sl_serial_no,
2280 2279 sl->sl_serial_no_alloc_size);
2281 2280 sl->sl_serial_no_alloc_size = 0;
2282 2281 }
2283 2282 if (sl->sl_mgmt_url_alloc_size) {
2284 2283 kmem_free(sl->sl_mgmt_url,
2285 2284 sl->sl_mgmt_url_alloc_size);
2286 2285 sl->sl_mgmt_url_alloc_size = 0;
2287 2286 }
2288 2287 } else {
2289 2288 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2290 2289 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2291 2290 sl->sl_trans_op = SL_OP_NONE;
2292 2291 return (EALREADY);
2293 2292 }
2294 2293 } else if (sret == SBD_NOT_FOUND) {
2295 2294 asz = strlen(ilu->ilu_meta_fname) + 1;
2296 2295
2297 2296 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
2298 2297 sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
2299 2298 if (lu == NULL) {
2300 2299 return (ENOMEM);
2301 2300 }
2302 2301 sl = (sbd_lu_t *)lu->lu_provider_private;
2303 2302 bzero(sl, sizeof (*sl));
2304 2303 sl->sl_lu = lu;
2305 2304 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2306 2305 sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) +
2307 2306 sizeof (sbd_pgr_t);
2308 2307 (void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
2309 2308 sl->sl_name = sl->sl_meta_filename;
2310 2309 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2311 2310 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2312 2311 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2313 2312 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2314 2313 sl->sl_trans_op = SL_OP_IMPORT_LU;
2315 2314 } else {
2316 2315 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2317 2316 return (EIO);
2318 2317 }
2319 2318
2320 2319 /* we're only loading the metadata */
2321 2320 if (!no_register) {
2322 2321 if (sbd_link_lu(sl) != SBD_SUCCESS) {
2323 2322 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2324 2323 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2325 2324 ret = EALREADY;
2326 2325 goto sim_err_out;
2327 2326 }
2328 2327 }
2329 2328 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
2330 2329 NULLVPP, &sl->sl_meta_vp)) != 0) {
2331 2330 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2332 2331 goto sim_err_out;
2333 2332 }
2334 2333 if (sbd_is_zvol(sl->sl_meta_filename)) {
2335 2334 sl->sl_flags |= SL_ZFS_META;
2336 2335 sl->sl_data_filename = sl->sl_meta_filename;
2337 2336 }
2338 2337 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
2339 2338 VN_RELE(sl->sl_meta_vp);
2340 2339 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
2341 2340 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
2342 2341 ret = EINVAL;
2343 2342 goto sim_err_out;
2344 2343 }
2345 2344 if (sl->sl_flags & SL_ZFS_META) {
2346 2345 if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
2347 2346 /* let see if metadata is in the 64k block */
2348 2347 sl->sl_flags &= ~SL_ZFS_META;
2349 2348 }
2350 2349 }
2351 2350 if (!(sl->sl_flags & SL_ZFS_META)) {
2352 2351 /* metadata is always writable */
2353 2352 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2354 2353 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
2355 2354 &sl->sl_meta_vp, 0, 0)) != 0) {
2356 2355 *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
2357 2356 goto sim_err_out;
2358 2357 }
2359 2358 }
2360 2359 if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
2361 2360 sl->sl_meta_blocksize_shift = 0;
2362 2361 } else {
2363 2362 sl->sl_meta_blocksize_shift = 9;
2364 2363 }
2365 2364 sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET;
2366 2365 sl->sl_flags |= SL_META_OPENED;
2367 2366
2368 2367 mutex_enter(&sl->sl_metadata_lock);
2369 2368 sret = sbd_load_meta_start(sl);
2370 2369 mutex_exit(&sl->sl_metadata_lock);
2371 2370 if (sret != SBD_SUCCESS) {
2372 2371 if (sret == SBD_META_CORRUPTED) {
2373 2372 *err_ret = SBD_RET_NO_META;
2374 2373 } else if (sret == SBD_NOT_SUPPORTED) {
2375 2374 *err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
2376 2375 } else {
2377 2376 *err_ret = SBD_RET_NO_META;
2378 2377 }
2379 2378 ret = EINVAL;
2380 2379 goto sim_err_out;
2381 2380 }
2382 2381
2383 2382 /* Now lets see if we can read the most recent LU info */
2384 2383 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2385 2384 SMS_ID_LU_INFO_1_1);
2386 2385 if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
2387 2386 ret = sbd_load_sli_1_0(sl, err_ret);
2388 2387 if (ret) {
2389 2388 goto sim_err_out;
2390 2389 }
2391 2390 goto sim_sli_loaded;
2392 2391 }
2393 2392 if (sret != SBD_SUCCESS) {
2394 2393 *err_ret = SBD_RET_NO_META;
2395 2394 ret = EIO;
2396 2395 goto sim_err_out;
2397 2396 }
2398 2397 /* load sli 1.1 */
2399 2398 if (sli->sli_data_order != SMS_DATA_ORDER) {
2400 2399 sbd_swap_lu_info_1_1(sli);
2401 2400 if (sli->sli_data_order != SMS_DATA_ORDER) {
2402 2401 *err_ret = SBD_RET_NO_META;
2403 2402 ret = EIO;
2404 2403 goto sim_err_out;
2405 2404 }
2406 2405 }
2407 2406
2408 2407 sli_buf_sz = sli->sli_sms_header.sms_size -
2409 2408 sizeof (sbd_lu_info_1_1_t) + 8;
2410 2409 sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
2411 2410 bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
2412 2411 sli_buf_copy[sli_buf_sz] = 0;
2413 2412
2414 2413 /* Make sure all the offsets are within limits */
2415 2414 if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
2416 2415 (sli->sli_meta_fname_offset > sli_buf_sz)) ||
2417 2416 ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
2418 2417 (sli->sli_data_fname_offset > sli_buf_sz)) ||
2419 2418 ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
2420 2419 (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
2421 2420 ((sli->sli_flags & SLI_SERIAL_VALID) &&
2422 2421 ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
2423 2422 ((sli->sli_flags & SLI_ALIAS_VALID) &&
2424 2423 (sli->sli_alias_offset > sli_buf_sz))) {
2425 2424 *err_ret = SBD_RET_NO_META;
2426 2425 ret = EIO;
2427 2426 goto sim_err_out;
2428 2427 }
2429 2428
2430 2429 sl->sl_lu_size = sli->sli_lu_size;
2431 2430 sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
2432 2431 bcopy(sli->sli_device_id, sl->sl_device_id, 20);
2433 2432 if (sli->sli_flags & SLI_SERIAL_VALID) {
2434 2433 sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
2435 2434 sli->sli_serial_size;
2436 2435 sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
2437 2436 bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
2438 2437 sl->sl_serial_no_size);
2439 2438 }
2440 2439 if (sli->sli_flags & SLI_SEPARATE_META) {
2441 2440 sl->sl_total_data_size = sl->sl_lu_size;
2442 2441 if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
2443 2442 sl->sl_data_fname_alloc_size = strlen((char *)
2444 2443 sli_buf_copy + sli->sli_data_fname_offset) + 1;
2445 2444 sl->sl_data_filename = kmem_zalloc(
2446 2445 sl->sl_data_fname_alloc_size, KM_SLEEP);
2447 2446 (void) strcpy(sl->sl_data_filename,
2448 2447 (char *)sli_buf_copy + sli->sli_data_fname_offset);
2449 2448 }
2450 2449 } else {
2451 2450 if (sl->sl_flags & SL_ZFS_META) {
2452 2451 sl->sl_total_data_size = sl->sl_lu_size;
2453 2452 sl->sl_data_offset = 0;
2454 2453 } else {
2455 2454 sl->sl_total_data_size =
2456 2455 sl->sl_lu_size + SHARED_META_DATA_SIZE;
2457 2456 sl->sl_data_offset = SHARED_META_DATA_SIZE;
2458 2457 sl->sl_flags |= SL_SHARED_META;
2459 2458 }
2460 2459 }
2461 2460 if (sli->sli_flags & SLI_ALIAS_VALID) {
2462 2461 sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
2463 2462 sli->sli_alias_offset) + 1;
2464 2463 sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
2465 2464 (void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
2466 2465 sli->sli_alias_offset);
2467 2466 }
2468 2467 if (sli->sli_flags & SLI_MGMT_URL_VALID) {
2469 2468 sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
2470 2469 sli->sli_mgmt_url_offset) + 1;
2471 2470 sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
2472 2471 KM_SLEEP);
2473 2472 (void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
2474 2473 sli->sli_mgmt_url_offset);
2475 2474 }
2476 2475 if (sli->sli_flags & SLI_WRITE_PROTECTED) {
2477 2476 sl->sl_flags |= SL_WRITE_PROTECTED;
2478 2477 }
2479 2478 if (sli->sli_flags & SLI_VID_VALID) {
2480 2479 sl->sl_flags |= SL_VID_VALID;
2481 2480 bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
2482 2481 }
2483 2482 if (sli->sli_flags & SLI_PID_VALID) {
2484 2483 sl->sl_flags |= SL_PID_VALID;
2485 2484 bcopy(sli->sli_pid, sl->sl_product_id, 16);
2486 2485 }
2487 2486 if (sli->sli_flags & SLI_REV_VALID) {
2488 2487 sl->sl_flags |= SL_REV_VALID;
2489 2488 bcopy(sli->sli_rev, sl->sl_revision, 4);
2490 2489 }
2491 2490 if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
2492 2491 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2493 2492 }
2494 2493 sim_sli_loaded:
2495 2494 if ((sl->sl_flags & SL_SHARED_META) == 0) {
2496 2495 data_opened = 0;
2497 2496 } else {
2498 2497 data_opened = 1;
2499 2498 sl->sl_data_filename = sl->sl_meta_filename;
2500 2499 sl->sl_data_vp = sl->sl_meta_vp;
2501 2500 sl->sl_data_vtype = sl->sl_meta_vtype;
2502 2501 }
2503 2502
2504 2503 sret = sbd_pgr_meta_load(sl);
2505 2504 if (sret != SBD_SUCCESS) {
2506 2505 *err_ret = SBD_RET_NO_META;
2507 2506 ret = EIO;
2508 2507 goto sim_err_out;
2509 2508 }
2510 2509
2511 2510 ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
2512 2511 if (ret) {
2513 2512 goto sim_err_out;
2514 2513 }
2515 2514
2516 2515 /*
2517 2516 * set write cache disable on the device
2518 2517 * Note: this shouldn't fail on import unless the cache capabilities
2519 2518 * of the device changed. If that happened, modify will need to
2520 2519 * be used to set the cache flag appropriately after import is done.
2521 2520 */
2522 2521 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2523 2522 (void) sbd_wcd_set(1, sl);
2524 2523 wcd = 1;
2525 2524 /*
2526 2525 * if not explicitly set, attempt to set it to enable, if that fails
2527 2526 * get the current setting and use that
2528 2527 */
2529 2528 } else {
2530 2529 sret = sbd_wcd_set(0, sl);
2531 2530 if (sret != SBD_SUCCESS) {
2532 2531 sbd_wcd_get(&wcd, sl);
2533 2532 }
2534 2533 }
2535 2534
2536 2535 if (wcd) {
2537 2536 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
2538 2537 SL_SAVED_WRITE_CACHE_DISABLE;
2539 2538 }
2540 2539
2541 2540 /* we're only loading the metadata */
2542 2541 if (!no_register) {
2543 2542 ret = sbd_populate_and_register_lu(sl, err_ret);
2544 2543 if (ret) {
2545 2544 goto sim_err_out;
2546 2545 }
2547 2546 atomic_inc_32(&sbd_lu_count);
2548 2547 }
2549 2548
2550 2549 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2551 2550 sl->sl_trans_op = SL_OP_NONE;
2552 2551
2553 2552 if (sli) {
2554 2553 kmem_free(sli, sli->sli_sms_header.sms_size);
2555 2554 sli = NULL;
2556 2555 }
2557 2556 if (sli_buf_copy) {
2558 2557 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2559 2558 sli_buf_copy = NULL;
2560 2559 }
2561 2560 if (no_register && !standby) {
2562 2561 *slr = sl;
2563 2562 }
2564 2563
2565 2564 /*
2566 2565 * if this was imported from standby, set the access state
2567 2566 * to active.
2568 2567 */
2569 2568 if (standby) {
2570 2569 sbd_it_data_t *it;
2571 2570 mutex_enter(&sl->sl_lock);
2572 2571 sl->sl_access_state = SBD_LU_ACTIVE;
2573 2572 for (it = sl->sl_it_list; it != NULL;
2574 2573 it = it->sbd_it_next) {
2575 2574 it->sbd_it_ua_conditions |=
2576 2575 SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2577 2576 it->sbd_it_ua_conditions |= SBD_UA_POR;
2578 2577 it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
2579 2578 }
2580 2579 mutex_exit(&sl->sl_lock);
2581 2580 /* call set access state */
2582 2581 stret = stmf_set_lu_access(lu, STMF_LU_ACTIVE);
2583 2582 if (stret != STMF_SUCCESS) {
2584 2583 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2585 2584 sl->sl_access_state = SBD_LU_STANDBY;
2586 2585 goto sim_err_out;
2587 2586 }
2588 2587 if (sl->sl_alias) {
2589 2588 lu->lu_alias = sl->sl_alias;
2590 2589 } else {
2591 2590 lu->lu_alias = sl->sl_name;
2592 2591 }
2593 2592 }
2594 2593 sl->sl_access_state = SBD_LU_ACTIVE;
2595 2594 return (0);
2596 2595
2597 2596 sim_err_out:
2598 2597 if (sli) {
2599 2598 kmem_free(sli, sli->sli_sms_header.sms_size);
2600 2599 sli = NULL;
2601 2600 }
2602 2601 if (sli_buf_copy) {
2603 2602 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2604 2603 sli_buf_copy = NULL;
2605 2604 }
2606 2605
2607 2606 if (standby) {
2608 2607 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2609 2608 sl->sl_trans_op = SL_OP_NONE;
2610 2609 return (EIO);
2611 2610 } else {
2612 2611 return (sbd_close_delete_lu(sl, ret));
2613 2612 }
2614 2613 }
2615 2614
2616 2615 int
2617 2616 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
2618 2617 {
2619 2618 sbd_lu_t *sl = NULL;
2620 2619 uint16_t alias_sz;
2621 2620 int ret = 0;
2622 2621 sbd_it_data_t *it;
2623 2622 sbd_status_t sret;
2624 2623 uint64_t old_size;
2625 2624 int modify_unregistered = 0;
2626 2625 int ua = 0;
2627 2626 sbd_import_lu_t *ilu;
2628 2627 stmf_lu_t *lu;
2629 2628 uint32_t ilu_sz;
2630 2629 uint32_t sz;
2631 2630
2632 2631 sz = struct_sz - sizeof (*mlu) + 8 + 1;
2633 2632
2634 2633 /* if there is data in the buf, null terminate it */
2635 2634 if (struct_sz > sizeof (*mlu)) {
2636 2635 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2637 2636 }
2638 2637
2639 2638 *err_ret = 0;
2640 2639
2641 2640 /* Lets validate offsets */
2642 2641 if (((mlu->mlu_alias_valid) &&
2643 2642 (mlu->mlu_alias_off >= sz)) ||
2644 2643 ((mlu->mlu_mgmt_url_valid) &&
2645 2644 (mlu->mlu_mgmt_url_off >= sz)) ||
2646 2645 (mlu->mlu_by_fname) &&
2647 2646 (mlu->mlu_fname_off >= sz)) {
2648 2647 return (EINVAL);
2649 2648 }
2650 2649
2651 2650 /*
2652 2651 * We'll look for the device but if we don't find it registered,
2653 2652 * we'll still try to modify the unregistered device.
2654 2653 */
2655 2654 if (mlu->mlu_by_guid) {
2656 2655 sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
2657 2656 SL_OP_MODIFY_LU, &sl);
2658 2657 } else if (mlu->mlu_by_fname) {
2659 2658 sret = sbd_find_and_lock_lu(NULL,
2660 2659 (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
2661 2660 SL_OP_MODIFY_LU, &sl);
2662 2661 } else {
2663 2662 return (EINVAL);
2664 2663 }
2665 2664
2666 2665
2667 2666 if (sret != SBD_SUCCESS) {
2668 2667 if (sret == SBD_BUSY) {
2669 2668 *err_ret = SBD_RET_LU_BUSY;
2670 2669 return (EBUSY);
2671 2670 } else if (sret != SBD_NOT_FOUND) {
2672 2671 return (EIO);
2673 2672 } else if (!mlu->mlu_by_fname) {
2674 2673 return (EINVAL);
2675 2674 }
2676 2675 /* Okay, try to import the device */
2677 2676 struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
2678 2677 + 1);
2679 2678 struct_sz += sizeof (sbd_import_lu_t) - 8;
2680 2679 ilu_sz = struct_sz;
2681 2680 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
2682 2681 ilu->ilu_struct_size = struct_sz;
2683 2682 (void) strcpy(ilu->ilu_meta_fname,
2684 2683 &(mlu->mlu_buf[mlu->mlu_fname_off]));
2685 2684 ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
2686 2685 kmem_free(ilu, ilu_sz);
2687 2686 if (ret != SBD_SUCCESS) {
2688 2687 return (ENOENT);
2689 2688 }
2690 2689 modify_unregistered = 1;
2691 2690 }
2692 2691
2693 2692 if (sl->sl_access_state != SBD_LU_ACTIVE) {
2694 2693 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2695 2694 ret = EINVAL;
2696 2695 goto smm_err_out;
2697 2696 }
2698 2697
2699 2698 /* check for write cache change */
2700 2699 if (mlu->mlu_writeback_cache_disable_valid) {
2701 2700 /* set wce on device */
2702 2701 sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
2703 2702 if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
2704 2703 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
2705 2704 ret = EFAULT;
2706 2705 goto smm_err_out;
2707 2706 }
2708 2707 mutex_enter(&sl->sl_lock);
2709 2708 if (!mlu->mlu_writeback_cache_disable) {
2710 2709 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2711 2710 ua = 1;
2712 2711 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2713 2712 sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2714 2713 }
2715 2714 } else {
2716 2715 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2717 2716 ua = 1;
2718 2717 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2719 2718 sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2720 2719 }
2721 2720 }
2722 2721 for (it = sl->sl_it_list; ua && it != NULL;
2723 2722 it = it->sbd_it_next) {
2724 2723 it->sbd_it_ua_conditions |=
2725 2724 SBD_UA_MODE_PARAMETERS_CHANGED;
2726 2725 }
2727 2726 mutex_exit(&sl->sl_lock);
2728 2727 }
2729 2728 ua = 0;
2730 2729
2731 2730 if (mlu->mlu_alias_valid) {
2732 2731 alias_sz = strlen((char *)mlu->mlu_buf +
2733 2732 mlu->mlu_alias_off) + 1;
2734 2733 /*
2735 2734 * Use the allocated buffer or alloc a new one.
2736 2735 * Don't copy into sl_alias if sl_alias_alloc_size is 0
2737 2736 * otherwise or you'll be writing over the data/metadata
2738 2737 * filename.
2739 2738 */
2740 2739 mutex_enter(&sl->sl_lock);
2741 2740 if (sl->sl_alias_alloc_size > 0 &&
2742 2741 sl->sl_alias_alloc_size < alias_sz) {
2743 2742 kmem_free(sl->sl_alias,
2744 2743 sl->sl_alias_alloc_size);
2745 2744 sl->sl_alias_alloc_size = 0;
2746 2745 }
2747 2746 if (sl->sl_alias_alloc_size == 0) {
2748 2747 sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
2749 2748 sl->sl_alias_alloc_size = alias_sz;
2750 2749 }
2751 2750 (void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
2752 2751 mlu->mlu_alias_off);
2753 2752 lu = sl->sl_lu;
2754 2753 lu->lu_alias = sl->sl_alias;
2755 2754 mutex_exit(&sl->sl_lock);
2756 2755 }
2757 2756
2758 2757 if (mlu->mlu_mgmt_url_valid) {
2759 2758 uint16_t url_sz;
2760 2759
2761 2760 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2762 2761 if (url_sz > 0)
2763 2762 url_sz++;
2764 2763
2765 2764 mutex_enter(&sl->sl_lock);
2766 2765 if (sl->sl_mgmt_url_alloc_size > 0 &&
2767 2766 (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
2768 2767 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
2769 2768 sl->sl_mgmt_url = NULL;
2770 2769 sl->sl_mgmt_url_alloc_size = 0;
2771 2770 }
2772 2771 if (url_sz > 0) {
2773 2772 if (sl->sl_mgmt_url_alloc_size == 0) {
2774 2773 sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2775 2774 sl->sl_mgmt_url_alloc_size = url_sz;
2776 2775 }
2777 2776 (void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
2778 2777 mlu->mlu_mgmt_url_off);
2779 2778 }
2780 2779 for (it = sl->sl_it_list; it != NULL;
2781 2780 it = it->sbd_it_next) {
2782 2781 it->sbd_it_ua_conditions |=
2783 2782 SBD_UA_MODE_PARAMETERS_CHANGED;
2784 2783 }
2785 2784 mutex_exit(&sl->sl_lock);
2786 2785 }
2787 2786
2788 2787 if (mlu->mlu_write_protected_valid) {
2789 2788 mutex_enter(&sl->sl_lock);
2790 2789 if (mlu->mlu_write_protected) {
2791 2790 if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
2792 2791 ua = 1;
2793 2792 sl->sl_flags |= SL_WRITE_PROTECTED;
2794 2793 }
2795 2794 } else {
2796 2795 if (sl->sl_flags & SL_WRITE_PROTECTED) {
2797 2796 ua = 1;
2798 2797 sl->sl_flags &= ~SL_WRITE_PROTECTED;
2799 2798 }
2800 2799 }
2801 2800 for (it = sl->sl_it_list; ua && it != NULL;
2802 2801 it = it->sbd_it_next) {
2803 2802 it->sbd_it_ua_conditions |=
2804 2803 SBD_UA_MODE_PARAMETERS_CHANGED;
2805 2804 }
2806 2805 mutex_exit(&sl->sl_lock);
2807 2806 }
2808 2807
2809 2808 if (mlu->mlu_lu_size_valid) {
2810 2809 /*
2811 2810 * validate lu size and set
2812 2811 * For open file only (registered lu)
2813 2812 */
2814 2813 mutex_enter(&sl->sl_lock);
2815 2814 old_size = sl->sl_lu_size;
2816 2815 sl->sl_lu_size = mlu->mlu_lu_size;
2817 2816 mutex_exit(&sl->sl_lock);
2818 2817 ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
2819 2818 if (ret) {
2820 2819 mutex_enter(&sl->sl_lock);
2821 2820 sl->sl_lu_size = old_size;
2822 2821 mutex_exit(&sl->sl_lock);
2823 2822 goto smm_err_out;
2824 2823 }
2825 2824 if (old_size != mlu->mlu_lu_size) {
2826 2825 mutex_enter(&sl->sl_lock);
2827 2826 for (it = sl->sl_it_list; it != NULL;
2828 2827 it = it->sbd_it_next) {
2829 2828 it->sbd_it_ua_conditions |=
2830 2829 SBD_UA_CAPACITY_CHANGED;
2831 2830 }
2832 2831 mutex_exit(&sl->sl_lock);
2833 2832 }
2834 2833 }
2835 2834
2836 2835 if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2837 2836 *err_ret = SBD_RET_META_CREATION_FAILED;
2838 2837 ret = EIO;
2839 2838 }
2840 2839
2841 2840 smm_err_out:
2842 2841 if (modify_unregistered) {
2843 2842 (void) sbd_close_delete_lu(sl, 0);
2844 2843 } else {
2845 2844 sl->sl_trans_op = SL_OP_NONE;
2846 2845 }
2847 2846 return (ret);
2848 2847 }
2849 2848
2850 2849 int
2851 2850 sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
2852 2851 uint32_t *err_ret)
2853 2852 {
2854 2853 sbd_lu_t *sl = NULL;
2855 2854 int ret = 0;
2856 2855 sbd_it_data_t *it;
2857 2856 uint32_t sz;
2858 2857
2859 2858 sz = struct_sz - sizeof (*mlu) + 8 + 1;
2860 2859
2861 2860 /* if there is data in the buf, null terminate it */
2862 2861 if (struct_sz > sizeof (*mlu)) {
2863 2862 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2864 2863 }
2865 2864
2866 2865 *err_ret = 0;
2867 2866
2868 2867 /* Lets validate offsets */
2869 2868 if (((mlu->mlu_mgmt_url_valid) &&
2870 2869 (mlu->mlu_mgmt_url_off >= sz))) {
2871 2870 return (EINVAL);
2872 2871 }
2873 2872
2874 2873 if (mlu->mlu_mgmt_url_valid) {
2875 2874 uint16_t url_sz;
2876 2875
2877 2876 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2878 2877 if (url_sz > 0)
2879 2878 url_sz++;
2880 2879
2881 2880 rw_enter(&sbd_global_prop_lock, RW_WRITER);
2882 2881 if (sbd_mgmt_url_alloc_size > 0 &&
2883 2882 (url_sz == 0 || sbd_mgmt_url_alloc_size < url_sz)) {
2884 2883 kmem_free(sbd_mgmt_url, sbd_mgmt_url_alloc_size);
2885 2884 sbd_mgmt_url = NULL;
2886 2885 sbd_mgmt_url_alloc_size = 0;
2887 2886 }
2888 2887 if (url_sz > 0) {
2889 2888 if (sbd_mgmt_url_alloc_size == 0) {
2890 2889 sbd_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2891 2890 sbd_mgmt_url_alloc_size = url_sz;
2892 2891 }
2893 2892 (void) strcpy(sbd_mgmt_url, (char *)mlu->mlu_buf +
2894 2893 mlu->mlu_mgmt_url_off);
2895 2894 }
2896 2895 /*
2897 2896 * check each lu to determine whether a UA is needed.
2898 2897 */
2899 2898 mutex_enter(&sbd_lock);
2900 2899 for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
2901 2900 if (sl->sl_mgmt_url) {
2902 2901 continue;
2903 2902 }
2904 2903 mutex_enter(&sl->sl_lock);
2905 2904 for (it = sl->sl_it_list; it != NULL;
2906 2905 it = it->sbd_it_next) {
2907 2906 it->sbd_it_ua_conditions |=
2908 2907 SBD_UA_MODE_PARAMETERS_CHANGED;
2909 2908 }
2910 2909 mutex_exit(&sl->sl_lock);
2911 2910 }
2912 2911 mutex_exit(&sbd_lock);
2913 2912 rw_exit(&sbd_global_prop_lock);
2914 2913 }
2915 2914 return (ret);
2916 2915 }
2917 2916
2918 2917 /* ARGSUSED */
2919 2918 int
2920 2919 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
2921 2920 stmf_state_change_info_t *ssi)
2922 2921 {
2923 2922 int i;
2924 2923 stmf_status_t ret;
2925 2924
2926 2925 if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2927 2926 !sl->sl_state_not_acked) {
2928 2927 goto sdl_do_dereg;
2929 2928 }
2930 2929
2931 2930 if ((sl->sl_state != STMF_STATE_ONLINE) ||
2932 2931 sl->sl_state_not_acked) {
2933 2932 return (EBUSY);
2934 2933 }
2935 2934
2936 2935 ret = stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi);
2937 2936 if ((ret != STMF_SUCCESS) && (ret != STMF_ALREADY)) {
2938 2937 return (EBUSY);
2939 2938 }
2940 2939
2941 2940 for (i = 0; i < 500; i++) {
2942 2941 if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2943 2942 !sl->sl_state_not_acked) {
2944 2943 goto sdl_do_dereg;
2945 2944 }
2946 2945 delay(drv_usectohz(10000));
2947 2946 }
2948 2947 return (EBUSY);
2949 2948
2950 2949 sdl_do_dereg:;
2951 2950 if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
2952 2951 return (EBUSY);
2953 2952 atomic_dec_32(&sbd_lu_count);
2954 2953
2955 2954 return (sbd_close_delete_lu(sl, 0));
2956 2955 }
2957 2956
2958 2957 int
2959 2958 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
2960 2959 {
2961 2960 sbd_lu_t *sl;
2962 2961 sbd_status_t sret;
2963 2962 stmf_state_change_info_t ssi;
2964 2963 int ret;
2965 2964
2966 2965 if (dlu->dlu_by_meta_name) {
2967 2966 ((char *)dlu)[struct_sz - 1] = 0;
2968 2967 sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
2969 2968 SL_OP_DELETE_LU, &sl);
2970 2969 } else {
2971 2970 sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
2972 2971 SL_OP_DELETE_LU, &sl);
2973 2972 }
2974 2973 if (sret != SBD_SUCCESS) {
2975 2974 if (sret == SBD_BUSY) {
2976 2975 *err_ret = SBD_RET_LU_BUSY;
2977 2976 return (EBUSY);
2978 2977 } else if (sret == SBD_NOT_FOUND) {
2979 2978 *err_ret = SBD_RET_NOT_FOUND;
2980 2979 return (ENOENT);
2981 2980 }
2982 2981 return (EIO);
2983 2982 }
2984 2983
2985 2984 ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
2986 2985 ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
2987 2986 ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
2988 2987
2989 2988 if (ret) {
2990 2989 /* Once its locked, no need to grab mutex again */
2991 2990 sl->sl_trans_op = SL_OP_NONE;
2992 2991 }
2993 2992 return (ret);
2994 2993 }
2995 2994
2996 2995 sbd_status_t
2997 2996 sbd_data_read(sbd_lu_t *sl, struct scsi_task *task,
2998 2997 uint64_t offset, uint64_t size, uint8_t *buf)
2999 2998 {
3000 2999 int ret;
3001 3000 long resid;
3002 3001
3003 3002 if ((offset + size) > sl->sl_lu_size) {
3004 3003 return (SBD_IO_PAST_EOF);
3005 3004 }
3006 3005
3007 3006 offset += sl->sl_data_offset;
3008 3007
3009 3008 if ((offset + size) > sl->sl_data_readable_size) {
3010 3009 uint64_t store_end;
3011 3010 if (offset > sl->sl_data_readable_size) {
3012 3011 bzero(buf, size);
3013 3012 return (SBD_SUCCESS);
3014 3013 }
3015 3014 store_end = sl->sl_data_readable_size - offset;
3016 3015 bzero(buf + store_end, size - store_end);
3017 3016 size = store_end;
3018 3017 }
3019 3018
3020 3019 DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
3021 3020 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3022 3021 scsi_task_t *, task);
3023 3022
3024 3023 /*
3025 3024 * Don't proceed if the device has been closed
3026 3025 * This can occur on an access state change to standby or
3027 3026 * a delete. The writer lock is acquired before closing the
3028 3027 * lu.
3029 3028 */
3030 3029 rw_enter(&sl->sl_access_state_lock, RW_READER);
3031 3030 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3032 3031 rw_exit(&sl->sl_access_state_lock);
3033 3032 return (SBD_FAILURE);
3034 3033 }
3035 3034 ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3036 3035 (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
3037 3036 &resid);
3038 3037 rw_exit(&sl->sl_access_state_lock);
3039 3038
3040 3039 DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
3041 3040 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3042 3041 int, ret, scsi_task_t *, task);
3043 3042
3044 3043 over_sl_data_read:
3045 3044 if (ret || resid) {
3046 3045 stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
3047 3046 resid);
3048 3047 return (SBD_FAILURE);
3049 3048 }
3050 3049
3051 3050 return (SBD_SUCCESS);
3052 3051 }
3053 3052
3054 3053 sbd_status_t
3055 3054 sbd_data_write(sbd_lu_t *sl, struct scsi_task *task,
3056 3055 uint64_t offset, uint64_t size, uint8_t *buf)
3057 3056 {
3058 3057 int ret;
3059 3058 long resid;
3060 3059 sbd_status_t sret = SBD_SUCCESS;
3061 3060 int ioflag;
3062 3061
3063 3062 if ((offset + size) > sl->sl_lu_size) {
3064 3063 return (SBD_IO_PAST_EOF);
3065 3064 }
3066 3065
3067 3066 offset += sl->sl_data_offset;
3068 3067
3069 3068 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3070 3069 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3071 3070 ioflag = FSYNC;
3072 3071 } else {
3073 3072 ioflag = 0;
3074 3073 }
3075 3074
3076 3075 DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3077 3076 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3078 3077 scsi_task_t *, task);
3079 3078
3080 3079 /*
3081 3080 * Don't proceed if the device has been closed
3082 3081 * This can occur on an access state change to standby or
3083 3082 * a delete. The writer lock is acquired before closing the
3084 3083 * lu.
3085 3084 */
3086 3085 rw_enter(&sl->sl_access_state_lock, RW_READER);
3087 3086 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3088 3087 rw_exit(&sl->sl_access_state_lock);
3089 3088 return (SBD_FAILURE);
3090 3089 }
3091 3090 ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3092 3091 (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
3093 3092 &resid);
3094 3093 rw_exit(&sl->sl_access_state_lock);
3095 3094
3096 3095 DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3097 3096 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3098 3097 int, ret, scsi_task_t *, task);
3099 3098
3100 3099 if ((ret == 0) && (resid == 0) &&
3101 3100 (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3102 3101 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3103 3102 sret = sbd_flush_data_cache(sl, 1);
3104 3103 }
3105 3104 over_sl_data_write:
3106 3105
3107 3106 if ((ret || resid) || (sret != SBD_SUCCESS)) {
3108 3107 return (SBD_FAILURE);
3109 3108 } else if ((offset + size) > sl->sl_data_readable_size) {
3110 3109 uint64_t old_size, new_size;
3111 3110
3112 3111 do {
3113 3112 old_size = sl->sl_data_readable_size;
3114 3113 if ((offset + size) <= old_size)
3115 3114 break;
3116 3115 new_size = offset + size;
3117 3116 } while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
3118 3117 new_size) != old_size);
3119 3118 }
3120 3119
3121 3120 return (SBD_SUCCESS);
3122 3121 }
3123 3122
3124 3123 int
3125 3124 sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
3126 3125 uint32_t *err_ret)
3127 3126 {
3128 3127 uint32_t sz = 0;
3129 3128 uint16_t off;
3130 3129
3131 3130 rw_enter(&sbd_global_prop_lock, RW_READER);
3132 3131 if (sbd_mgmt_url) {
3133 3132 sz += strlen(sbd_mgmt_url) + 1;
3134 3133 }
3135 3134 bzero(oslp, sizeof (*oslp) - 8);
3136 3135 oslp->mlu_buf_size_needed = sz;
3137 3136
3138 3137 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3139 3138 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3140 3139 rw_exit(&sbd_global_prop_lock);
3141 3140 return (ENOMEM);
3142 3141 }
3143 3142
3144 3143 off = 0;
3145 3144 if (sbd_mgmt_url) {
3146 3145 oslp->mlu_mgmt_url_valid = 1;
3147 3146 oslp->mlu_mgmt_url_off = off;
3148 3147 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3149 3148 off += strlen(sbd_mgmt_url) + 1;
3150 3149 }
3151 3150
3152 3151 rw_exit(&sbd_global_prop_lock);
3153 3152 return (0);
3154 3153 }
3155 3154
3156 3155 static int
3157 3156 sbd_get_unmap_props(sbd_unmap_props_t *sup,
3158 3157 sbd_unmap_props_t *osup, uint32_t *err_ret)
3159 3158 {
3160 3159 sbd_status_t sret;
3161 3160 sbd_lu_t *sl = NULL;
3162 3161
3163 3162 if (sup->sup_guid_valid) {
3164 3163 sret = sbd_find_and_lock_lu(sup->sup_guid,
3165 3164 NULL, SL_OP_LU_PROPS, &sl);
3166 3165 } else {
3167 3166 sret = sbd_find_and_lock_lu(NULL,
3168 3167 (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS,
3169 3168 &sl);
3170 3169 }
3171 3170 if (sret != SBD_SUCCESS) {
3172 3171 if (sret == SBD_BUSY) {
3173 3172 *err_ret = SBD_RET_LU_BUSY;
3174 3173 return (EBUSY);
3175 3174 } else if (sret == SBD_NOT_FOUND) {
3176 3175 *err_ret = SBD_RET_NOT_FOUND;
3177 3176 return (ENOENT);
3178 3177 }
3179 3178 return (EIO);
3180 3179 }
3181 3180
3182 3181 sup->sup_found_lu = 1;
3183 3182 sup->sup_guid_valid = 1;
3184 3183 bcopy(sl->sl_device_id + 4, sup->sup_guid, 16);
3185 3184 if (sl->sl_flags & SL_UNMAP_ENABLED)
3186 3185 sup->sup_unmap_enabled = 1;
3187 3186 else
3188 3187 sup->sup_unmap_enabled = 0;
3189 3188
3190 3189 *osup = *sup;
3191 3190 sl->sl_trans_op = SL_OP_NONE;
3192 3191
3193 3192 return (0);
3194 3193 }
3195 3194
3196 3195 int
3197 3196 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3198 3197 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3199 3198 {
3200 3199 sbd_status_t sret;
3201 3200 sbd_lu_t *sl = NULL;
3202 3201 uint32_t sz;
3203 3202 uint16_t off;
3204 3203
3205 3204 if (islp->slp_input_guid) {
3206 3205 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3207 3206 SL_OP_LU_PROPS, &sl);
3208 3207 } else {
3209 3208 ((char *)islp)[islp_sz - 1] = 0;
3210 3209 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3211 3210 SL_OP_LU_PROPS, &sl);
3212 3211 }
3213 3212 if (sret != SBD_SUCCESS) {
3214 3213 if (sret == SBD_BUSY) {
3215 3214 *err_ret = SBD_RET_LU_BUSY;
3216 3215 return (EBUSY);
3217 3216 } else if (sret == SBD_NOT_FOUND) {
3218 3217 *err_ret = SBD_RET_NOT_FOUND;
3219 3218 return (ENOENT);
3220 3219 }
3221 3220 return (EIO);
3222 3221 }
3223 3222
3224 3223 sz = strlen(sl->sl_name) + 1;
3225 3224 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3226 3225 if (sl->sl_data_filename) {
3227 3226 sz += strlen(sl->sl_data_filename) + 1;
3228 3227 }
3229 3228 }
3230 3229 sz += sl->sl_serial_no_size;
3231 3230 if (sl->sl_alias) {
3232 3231 sz += strlen(sl->sl_alias) + 1;
3233 3232 }
3234 3233
3235 3234 rw_enter(&sbd_global_prop_lock, RW_READER);
3236 3235 if (sl->sl_mgmt_url) {
3237 3236 sz += strlen(sl->sl_mgmt_url) + 1;
3238 3237 } else if (sbd_mgmt_url) {
3239 3238 sz += strlen(sbd_mgmt_url) + 1;
3240 3239 }
3241 3240 bzero(oslp, sizeof (*oslp) - 8);
3242 3241 oslp->slp_buf_size_needed = sz;
3243 3242
3244 3243 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3245 3244 sl->sl_trans_op = SL_OP_NONE;
3246 3245 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3247 3246 rw_exit(&sbd_global_prop_lock);
3248 3247 return (ENOMEM);
3249 3248 }
3250 3249
3251 3250 off = 0;
3252 3251 (void) strcpy((char *)oslp->slp_buf, sl->sl_name);
3253 3252 oslp->slp_meta_fname_off = off;
3254 3253 off += strlen(sl->sl_name) + 1;
3255 3254 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3256 3255 oslp->slp_meta_fname_valid = 1;
3257 3256 oslp->slp_separate_meta = 1;
3258 3257 if (sl->sl_data_filename) {
3259 3258 oslp->slp_data_fname_valid = 1;
3260 3259 oslp->slp_data_fname_off = off;
3261 3260 (void) strcpy((char *)&oslp->slp_buf[off],
3262 3261 sl->sl_data_filename);
3263 3262 off += strlen(sl->sl_data_filename) + 1;
3264 3263 }
3265 3264 } else {
3266 3265 oslp->slp_data_fname_valid = 1;
3267 3266 oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
3268 3267 if (sl->sl_flags & SL_ZFS_META) {
3269 3268 oslp->slp_zfs_meta = 1;
3270 3269 }
3271 3270 }
3272 3271 if (sl->sl_alias) {
3273 3272 oslp->slp_alias_valid = 1;
3274 3273 oslp->slp_alias_off = off;
3275 3274 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
3276 3275 off += strlen(sl->sl_alias) + 1;
3277 3276 }
3278 3277 if (sl->sl_mgmt_url) {
3279 3278 oslp->slp_mgmt_url_valid = 1;
3280 3279 oslp->slp_mgmt_url_off = off;
3281 3280 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
3282 3281 off += strlen(sl->sl_mgmt_url) + 1;
3283 3282 } else if (sbd_mgmt_url) {
3284 3283 oslp->slp_mgmt_url_valid = 1;
3285 3284 oslp->slp_mgmt_url_off = off;
3286 3285 (void) strcpy((char *)&oslp->slp_buf[off], sbd_mgmt_url);
3287 3286 off += strlen(sbd_mgmt_url) + 1;
3288 3287 }
3289 3288 if (sl->sl_serial_no_size) {
3290 3289 oslp->slp_serial_off = off;
3291 3290 bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
3292 3291 sl->sl_serial_no_size);
3293 3292 oslp->slp_serial_size = sl->sl_serial_no_size;
3294 3293 oslp->slp_serial_valid = 1;
3295 3294 off += sl->sl_serial_no_size;
3296 3295 }
3297 3296
3298 3297 oslp->slp_lu_size = sl->sl_lu_size;
3299 3298 oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
3300 3299
3301 3300 oslp->slp_access_state = sl->sl_access_state;
3302 3301
3303 3302 if (sl->sl_flags & SL_VID_VALID) {
3304 3303 oslp->slp_lu_vid = 1;
3305 3304 bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
3306 3305 } else {
3307 3306 bcopy(sbd_vendor_id, oslp->slp_vid, 8);
3308 3307 }
3309 3308 if (sl->sl_flags & SL_PID_VALID) {
3310 3309 oslp->slp_lu_pid = 1;
3311 3310 bcopy(sl->sl_product_id, oslp->slp_pid, 16);
3312 3311 } else {
3313 3312 bcopy(sbd_product_id, oslp->slp_pid, 16);
3314 3313 }
3315 3314 if (sl->sl_flags & SL_REV_VALID) {
3316 3315 oslp->slp_lu_rev = 1;
3317 3316 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3318 3317 } else {
3319 3318 bcopy(sbd_revision, oslp->slp_rev, 4);
3320 3319 }
3321 3320 bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3322 3321
3323 3322 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3324 3323 oslp->slp_writeback_cache_disable_cur = 1;
3325 3324 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3326 3325 oslp->slp_writeback_cache_disable_saved = 1;
3327 3326 if (sl->sl_flags & SL_WRITE_PROTECTED)
3328 3327 oslp->slp_write_protected = 1;
3329 3328
3330 3329 sl->sl_trans_op = SL_OP_NONE;
3331 3330
3332 3331 rw_exit(&sbd_global_prop_lock);
3333 3332 return (0);
3334 3333 }
3335 3334
3336 3335 /*
3337 3336 * Returns an allocated string with the "<pool>/..." form of the zvol name.
3338 3337 */
3339 3338 static char *
3340 3339 sbd_get_zvol_name(sbd_lu_t *sl)
3341 3340 {
3342 3341 char *src;
3343 3342 char *p;
3344 3343
3345 3344 if (sl->sl_data_filename)
3346 3345 src = sl->sl_data_filename;
3347 3346 else
3348 3347 src = sl->sl_meta_filename;
3349 3348 /* There has to be a better way */
3350 3349 if (SBD_IS_ZVOL(src) != 0) {
3351 3350 ASSERT(0);
3352 3351 }
3353 3352 src += 14; /* Past /dev/zvol/dsk/ */
3354 3353 if (*src == '/')
3355 3354 src++; /* or /dev/zvol/rdsk/ */
3356 3355 p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3357 3356 (void) strcpy(p, src);
3358 3357 return (p);
3359 3358 }
3360 3359
3361 3360 /*
3362 3361 * this function creates a local metadata zvol property
3363 3362 */
3364 3363 sbd_status_t
3365 3364 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3366 3365 {
3367 3366 /*
3368 3367 * -allocate 1/2 the property size, the zfs property
3369 3368 * is 8k in size and stored as ascii hex string, all
3370 3369 * we needed is 4k buffer to store the binary data.
3371 3370 * -initialize reader/write lock
3372 3371 */
3373 3372 if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3374 3373 == NULL)
3375 3374 return (SBD_FAILURE);
3376 3375 rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL);
3377 3376 return (SBD_SUCCESS);
3378 3377 }
3379 3378
3380 3379 char
3381 3380 sbd_ctoi(char c)
3382 3381 {
3383 3382 if ((c >= '0') && (c <= '9'))
3384 3383 c -= '0';
3385 3384 else if ((c >= 'A') && (c <= 'F'))
3386 3385 c = c - 'A' + 10;
3387 3386 else if ((c >= 'a') && (c <= 'f'))
3388 3387 c = c - 'a' + 10;
3389 3388 else
3390 3389 c = -1;
3391 3390 return (c);
3392 3391 }
3393 3392
3394 3393 /*
3395 3394 * read zvol property and convert to binary
3396 3395 */
3397 3396 sbd_status_t
3398 3397 sbd_open_zfs_meta(sbd_lu_t *sl)
3399 3398 {
3400 3399 char *meta = NULL, cl, ch;
3401 3400 int i;
3402 3401 char *tmp, *ptr;
3403 3402 uint64_t rc = SBD_SUCCESS;
3404 3403 int len;
3405 3404 char *file;
3406 3405
3407 3406 if (sl->sl_zfs_meta == NULL) {
3408 3407 if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE)
3409 3408 return (SBD_FAILURE);
3410 3409 } else {
3411 3410 bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2));
3412 3411 }
3413 3412
3414 3413 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3415 3414 file = sbd_get_zvol_name(sl);
3416 3415 if (sbd_zvolget(file, &meta)) {
3417 3416 rc = SBD_FAILURE;
3418 3417 goto done;
3419 3418 }
3420 3419 tmp = meta;
3421 3420 /* convert ascii hex to binary meta */
3422 3421 len = strlen(meta);
3423 3422 ptr = sl->sl_zfs_meta;
3424 3423 for (i = 0; i < len; i += 2) {
3425 3424 ch = sbd_ctoi(*tmp++);
3426 3425 cl = sbd_ctoi(*tmp++);
3427 3426 if (ch == -1 || cl == -1) {
3428 3427 rc = SBD_FAILURE;
3429 3428 break;
3430 3429 }
3431 3430 *ptr++ = (ch << 4) + cl;
3432 3431 }
3433 3432 done:
3434 3433 rw_exit(&sl->sl_zfs_meta_lock);
3435 3434 if (meta)
3436 3435 kmem_free(meta, len + 1);
3437 3436 kmem_free(file, strlen(file) + 1);
3438 3437 return (rc);
3439 3438 }
3440 3439
3441 3440 sbd_status_t
3442 3441 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3443 3442 {
3444 3443 ASSERT(sl->sl_zfs_meta);
3445 3444 rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3446 3445 bcopy(&sl->sl_zfs_meta[off], buf, sz);
3447 3446 rw_exit(&sl->sl_zfs_meta_lock);
3448 3447 return (SBD_SUCCESS);
3449 3448 }
3450 3449
3451 3450 sbd_status_t
3452 3451 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3453 3452 {
3454 3453 ASSERT(sl->sl_zfs_meta);
3455 3454 if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) {
3456 3455 return (SBD_META_CORRUPTED);
3457 3456 }
3458 3457 if ((off + sz) > sl->sl_meta_size_used) {
3459 3458 sl->sl_meta_size_used = off + sz;
3460 3459 if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
3461 3460 uint64_t meta_align =
3462 3461 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
3463 3462 sl->sl_total_meta_size = (sl->sl_meta_size_used +
3464 3463 meta_align) & (~meta_align);
3465 3464 }
3466 3465 }
3467 3466 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3468 3467 bcopy(buf, &sl->sl_zfs_meta[off], sz);
3469 3468 rw_exit(&sl->sl_zfs_meta_lock);
3470 3469 /*
3471 3470 * During creation of a logical unit, sbd_update_zfs_prop will be
3472 3471 * called separately to avoid multiple calls as each meta section
3473 3472 * create/update will result in a call to sbd_write_zfs_meta().
3474 3473 * We only need to update the zvol once during create.
3475 3474 */
3476 3475 mutex_enter(&sl->sl_lock);
3477 3476 if (sl->sl_trans_op != SL_OP_CREATE_REGISTER_LU) {
3478 3477 mutex_exit(&sl->sl_lock);
3479 3478 return (sbd_update_zfs_prop(sl));
3480 3479 }
3481 3480 mutex_exit(&sl->sl_lock);
3482 3481 return (SBD_SUCCESS);
3483 3482 }
3484 3483
3485 3484 sbd_status_t
3486 3485 sbd_update_zfs_prop(sbd_lu_t *sl)
3487 3486 {
3488 3487 char *ptr, *ah_meta;
3489 3488 char *dp = NULL;
3490 3489 int i, num;
3491 3490 char *file;
3492 3491 sbd_status_t ret = SBD_SUCCESS;
3493 3492
3494 3493 ASSERT(sl->sl_zfs_meta);
3495 3494 ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP);
3496 3495 rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3497 3496 /* convert local copy to ascii hex */
3498 3497 dp = sl->sl_zfs_meta;
3499 3498 for (i = 0; i < sl->sl_total_meta_size; i++, dp++) {
3500 3499 num = ((*dp) >> 4) & 0xF;
3501 3500 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3502 3501 num = (*dp) & 0xF;
3503 3502 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3504 3503 }
3505 3504 *ah_meta = NULL;
3506 3505 file = sbd_get_zvol_name(sl);
3507 3506 if (sbd_zvolset(file, (char *)ptr)) {
3508 3507 ret = SBD_META_CORRUPTED;
3509 3508 }
3510 3509 rw_exit(&sl->sl_zfs_meta_lock);
3511 3510 kmem_free(ptr, ZAP_MAXVALUELEN);
3512 3511 kmem_free(file, strlen(file) + 1);
3513 3512 return (ret);
3514 3513 }
3515 3514
3516 3515 int
3517 3516 sbd_is_zvol(char *path)
3518 3517 {
3519 3518 int is_zfs = 0;
3520 3519
3521 3520 if (SBD_IS_ZVOL(path) == 0)
3522 3521 is_zfs = 1;
3523 3522
3524 3523 return (is_zfs);
3525 3524 }
3526 3525
3527 3526 /*
3528 3527 * set write cache disable
3529 3528 * wcd - 1 = disable, 0 = enable
3530 3529 */
3531 3530 sbd_status_t
3532 3531 sbd_wcd_set(int wcd, sbd_lu_t *sl)
3533 3532 {
3534 3533 /* translate to wce bit */
3535 3534 int wce = wcd ? 0 : 1;
3536 3535 int ret;
3537 3536 sbd_status_t sret = SBD_SUCCESS;
3538 3537
3539 3538 mutex_enter(&sl->sl_lock);
3540 3539 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3541 3540
3542 3541 if (sl->sl_data_vp->v_type == VREG) {
3543 3542 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3544 3543 goto done;
3545 3544 }
3546 3545
3547 3546 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
3548 3547 kcred, NULL, NULL);
3549 3548 if (ret == 0) {
3550 3549 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3551 3550 sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
3552 3551 } else {
3553 3552 sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3554 3553 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3555 3554 sret = SBD_FAILURE;
3556 3555 goto done;
3557 3556 }
3558 3557
3559 3558 done:
3560 3559 mutex_exit(&sl->sl_lock);
3561 3560 return (sret);
3562 3561 }
3563 3562
3564 3563 /*
3565 3564 * get write cache disable
3566 3565 * wcd - 1 = disable, 0 = enable
3567 3566 */
3568 3567 void
3569 3568 sbd_wcd_get(int *wcd, sbd_lu_t *sl)
3570 3569 {
3571 3570 int wce;
3572 3571 int ret;
3573 3572
3574 3573 if (sl->sl_data_vp->v_type == VREG) {
3575 3574 *wcd = 0;
3576 3575 return;
3577 3576 }
3578 3577
3579 3578 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
3580 3579 kcred, NULL, NULL);
3581 3580 /* if write cache get failed, assume disabled */
3582 3581 if (ret) {
3583 3582 *wcd = 1;
3584 3583 } else {
3585 3584 /* translate to wcd bit */
3586 3585 *wcd = wce ? 0 : 1;
3587 3586 }
3588 3587 }
3589 3588
3590 3589 int
3591 3590 sbd_zvolget(char *zvol_name, char **comstarprop)
3592 3591 {
3593 3592 ldi_handle_t zfs_lh;
3594 3593 nvlist_t *nv = NULL, *nv2;
3595 3594 zfs_cmd_t *zc;
3596 3595 char *ptr;
3597 3596 int size = 1024;
3598 3597 int unused;
3599 3598 int rc;
3600 3599
3601 3600 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3602 3601 &zfs_lh, sbd_zfs_ident)) != 0) {
3603 3602 cmn_err(CE_WARN, "ldi_open %d", rc);
3604 3603 return (ENXIO);
3605 3604 }
3606 3605
3607 3606 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3608 3607 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3609 3608 again:
3610 3609 zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3611 3610 KM_SLEEP);
3612 3611 zc->zc_nvlist_dst_size = size;
3613 3612 rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3614 3613 FKIOCTL, kcred, &unused);
3615 3614 /*
3616 3615 * ENOMEM means the list is larger than what we've allocated
3617 3616 * ldi_ioctl will fail with ENOMEM only once
3618 3617 */
3619 3618 if (rc == ENOMEM) {
3620 3619 int newsize;
3621 3620 newsize = zc->zc_nvlist_dst_size;
3622 3621 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3623 3622 size = newsize;
3624 3623 goto again;
3625 3624 } else if (rc != 0) {
3626 3625 goto out;
3627 3626 }
3628 3627 rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3629 3628 zc->zc_nvlist_dst_size, &nv, 0);
3630 3629 ASSERT(rc == 0); /* nvlist_unpack should not fail */
3631 3630 if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) {
3632 3631 rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr);
3633 3632 if (rc != 0) {
3634 3633 cmn_err(CE_WARN, "couldn't get value");
3635 3634 } else {
3636 3635 *comstarprop = kmem_alloc(strlen(ptr) + 1,
3637 3636 KM_SLEEP);
3638 3637 (void) strcpy(*comstarprop, ptr);
3639 3638 }
3640 3639 }
3641 3640 out:
3642 3641 nvlist_free(nv);
3643 3642 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3644 3643 kmem_free(zc, sizeof (zfs_cmd_t));
3645 3644 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3646 3645
3647 3646 return (rc);
3648 3647 }
3649 3648
3650 3649 int
3651 3650 sbd_zvolset(char *zvol_name, char *comstarprop)
3652 3651 {
3653 3652 ldi_handle_t zfs_lh;
3654 3653 nvlist_t *nv;
3655 3654 char *packed = NULL;
3656 3655 size_t len;
3657 3656 zfs_cmd_t *zc;
3658 3657 int unused;
3659 3658 int rc;
3660 3659
3661 3660 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3662 3661 &zfs_lh, sbd_zfs_ident)) != 0) {
3663 3662 cmn_err(CE_WARN, "ldi_open %d", rc);
3664 3663 return (ENXIO);
3665 3664 }
3666 3665 (void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP);
3667 3666 (void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop);
3668 3667 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3669 3668 goto out;
3670 3669 }
3671 3670
3672 3671 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3673 3672 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3674 3673 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3675 3674 zc->zc_nvlist_src_size = len;
3676 3675 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3677 3676 FKIOCTL, kcred, &unused);
3678 3677 if (rc != 0) {
3679 3678 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3680 3679 }
3681 3680 kmem_free(zc, sizeof (zfs_cmd_t));
3682 3681 if (packed)
3683 3682 kmem_free(packed, len);
3684 3683 out:
3685 3684 nvlist_free(nv);
3686 3685 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3687 3686 return (rc);
3688 3687 }
3689 3688
3690 3689 /*
3691 3690 * Unmap a region in a volume. Currently only supported for zvols.
3692 3691 */
3693 3692 int
3694 3693 sbd_unmap(sbd_lu_t *sl, uint64_t offset, uint64_t length)
3695 3694 {
3696 3695 vnode_t *vp;
3697 3696 int unused;
3698 3697 dkioc_free_t df;
3699 3698
3700 3699 /* Right now, we only support UNMAP on zvols. */
3701 3700 if (!(sl->sl_flags & SL_ZFS_META))
3702 3701 return (EIO);
3703 3702
3704 3703 df.df_flags = (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) ?
3705 3704 DF_WAIT_SYNC : 0;
3706 3705 df.df_start = offset;
3707 3706 df.df_length = length;
3708 3707
3709 3708 /* Use the data vnode we have to send a fop_ioctl(). */
3710 3709 vp = sl->sl_data_vp;
3711 3710 if (vp == NULL) {
3712 3711 cmn_err(CE_WARN, "Cannot unmap - no vnode pointer.");
3713 3712 return (EIO);
3714 3713 }
3715 3714
3716 3715 return (VOP_IOCTL(vp, DKIOCFREE, (intptr_t)(&df), FKIOCTL, kcred,
3717 3716 &unused, NULL));
3718 3717 }
↓ open down ↓ |
3539 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX