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