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_VID_VALID) {
1357 bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
1358 sli->sli_flags |= SLI_VID_VALID;
1359 }
1360 if (sl->sl_flags & SL_PID_VALID) {
1361 bcopy(sl->sl_product_id, sli->sli_pid, 16);
1362 sli->sli_flags |= SLI_PID_VALID;
1363 }
1364 if (sl->sl_flags & SL_REV_VALID) {
1365 bcopy(sl->sl_revision, sli->sli_rev, 4);
1366 sli->sli_flags |= SLI_REV_VALID;
1367 }
1368 if (sl->sl_serial_no_size) {
1369 bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
1370 sli->sli_serial_size = sl->sl_serial_no_size;
1371 sli->sli_serial_offset =
1372 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1373 sli->sli_flags |= SLI_SERIAL_VALID;
1374 p += sli->sli_serial_size;
1375 }
1376 sli->sli_lu_size = sl->sl_lu_size;
1377 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1378 sli->sli_data_order = SMS_DATA_ORDER;
1379 bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1380
1381 sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1382 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1383 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1384
1385 mutex_exit(&sl->sl_lock);
1386 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1387 kmem_free(sli, sizeof (*sli) + s);
1388 return (ret);
1389 }
1390
1391 /*
1392 * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
1393 */
1394 static void
1395 do_unmap_setup(sbd_lu_t *sl)
1396 {
1397 ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
1398
1399 if ((sl->sl_flags & SL_ZFS_META) == 0)
1400 return; /* No UNMAP for you. */
1401
1402 sl->sl_flags |= SL_UNMAP_ENABLED;
1403 }
1404
1405 int
1406 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1407 {
1408 stmf_lu_t *lu = sl->sl_lu;
1409 stmf_status_t ret;
1410
1411 do_unmap_setup(sl);
1412
1413 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1414 if (sl->sl_alias) {
1415 lu->lu_alias = sl->sl_alias;
1416 } else {
1417 lu->lu_alias = sl->sl_name;
1418 }
1419 if (sl->sl_access_state == SBD_LU_STANDBY) {
1420 /* call set access state */
1421 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1422 if (ret != STMF_SUCCESS) {
1423 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1424 return (EIO);
1425 }
1426 }
1427 /* set proxy_reg_cb_arg to meta filename */
1428 if (sl->sl_meta_filename) {
1429 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1430 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1431 } else {
1432 lu->lu_proxy_reg_arg = sl->sl_data_filename;
1433 lu->lu_proxy_reg_arg_len = strlen(sl->sl_data_filename) + 1;
1434 }
1435 lu->lu_lp = sbd_lp;
1436 lu->lu_task_alloc = sbd_task_alloc;
1437 lu->lu_new_task = sbd_new_task;
1438 lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1439 lu->lu_send_status_done = sbd_send_status_done;
1440 lu->lu_task_free = sbd_task_free;
1441 lu->lu_abort = sbd_abort;
1442 lu->lu_dbuf_free = sbd_dbuf_free;
1443 lu->lu_ctl = sbd_ctl;
1444 lu->lu_info = sbd_info;
1445 sl->sl_state = STMF_STATE_OFFLINE;
1446
1447 if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1448 stmf_trace(0, "Failed to register with framework, ret=%llx",
1449 ret);
1450 if (ret == STMF_ALREADY) {
1451 *err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
1452 }
1453 return (EIO);
1454 }
1455
1456 *err_ret = 0;
1457 return (0);
1458 }
1459
1460 int
1461 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
1462 int vp_valid, int keep_open)
1463 {
1464 int ret;
1465 int flag;
1466 ulong_t nbits;
1467 uint64_t supported_size;
1468 vattr_t vattr;
1469 enum vtype vt;
1470 struct dk_cinfo dki;
1471 int unused;
1472
1473 mutex_enter(&sl->sl_lock);
1474 if (vp_valid) {
1475 goto odf_over_open;
1476 }
1477 if (sl->sl_data_filename[0] != '/') {
1478 *err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
1479 mutex_exit(&sl->sl_lock);
1480 return (EINVAL);
1481 }
1482 if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
1483 NULLVPP, &sl->sl_data_vp)) != 0) {
1484 *err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
1485 mutex_exit(&sl->sl_lock);
1486 return (ret);
1487 }
1488 sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
1489 VN_RELE(sl->sl_data_vp);
1490 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1491 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1492 mutex_exit(&sl->sl_lock);
1493 return (EINVAL);
1494 }
1495 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1496 flag = FREAD | FOFFMAX;
1497 } else {
1498 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1499 }
1500 if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
1501 &sl->sl_data_vp, 0, 0)) != 0) {
1502 *err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
1503 mutex_exit(&sl->sl_lock);
1504 return (ret);
1505 }
1506 odf_over_open:
1507 vattr.va_mask = AT_SIZE;
1508 if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
1509 *err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
1510 goto odf_close_data_and_exit;
1511 }
1512 if ((vt != VREG) && (vattr.va_size == 0)) {
1513 /*
1514 * Its a zero byte block or char device. This cannot be
1515 * a raw disk.
1516 */
1517 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1518 ret = EINVAL;
1519 goto odf_close_data_and_exit;
1520 }
1521 /* sl_data_readable size includes any metadata. */
1522 sl->sl_data_readable_size = vattr.va_size;
1523
1524 if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
1525 CRED(), NULL) != 0) {
1526 nbits = 0;
1527 }
1528 /* nbits cannot be greater than 64 */
1529 sl->sl_data_fs_nbits = (uint8_t)nbits;
1530 if (lu_size_valid) {
1531 sl->sl_total_data_size = sl->sl_lu_size;
1532 if (sl->sl_flags & SL_SHARED_META) {
1533 sl->sl_total_data_size += SHARED_META_DATA_SIZE;
1534 }
1535 if ((nbits > 0) && (nbits < 64)) {
1536 /*
1537 * The expression below is correct only if nbits is
1538 * positive and less than 64.
1539 */
1540 supported_size = (((uint64_t)1) << nbits) - 1;
1541 if (sl->sl_total_data_size > supported_size) {
1542 *err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
1543 ret = EINVAL;
1544 goto odf_close_data_and_exit;
1545 }
1546 }
1547 } else {
1548 sl->sl_total_data_size = vattr.va_size;
1549 if (sl->sl_flags & SL_SHARED_META) {
1550 if (vattr.va_size > SHARED_META_DATA_SIZE) {
1551 sl->sl_lu_size = vattr.va_size -
1552 SHARED_META_DATA_SIZE;
1553 } else {
1554 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1555 ret = EINVAL;
1556 goto odf_close_data_and_exit;
1557 }
1558 } else {
1559 sl->sl_lu_size = vattr.va_size;
1560 }
1561 }
1562 if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
1563 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1564 ret = EINVAL;
1565 goto odf_close_data_and_exit;
1566 }
1567 if (sl->sl_lu_size &
1568 ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
1569 *err_ret = SBD_RET_FILE_ALIGN_ERROR;
1570 ret = EINVAL;
1571 goto odf_close_data_and_exit;
1572 }
1573 /*
1574 * Get the minor device for direct zvol access
1575 */
1576 if (sl->sl_flags & SL_ZFS_META) {
1577 if ((ret = VOP_IOCTL(sl->sl_data_vp, DKIOCINFO, (intptr_t)&dki,
1578 FKIOCTL, kcred, &unused, NULL)) != 0) {
1579 cmn_err(CE_WARN, "ioctl(DKIOCINFO) failed %d", ret);
1580 /* zvol reserves 0, so this would fail later */
1581 sl->sl_zvol_minor = 0;
1582 } else {
1583 sl->sl_zvol_minor = dki.dki_unit;
1584 if (sbd_zvol_get_volume_params(sl) == 0)
1585 sl->sl_flags |= SL_CALL_ZVOL;
1586 }
1587 }
1588 sl->sl_flags |= SL_MEDIA_LOADED;
1589 mutex_exit(&sl->sl_lock);
1590 return (0);
1591
1592 odf_close_data_and_exit:
1593 if (!keep_open) {
1594 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1595 VN_RELE(sl->sl_data_vp);
1596 }
1597 mutex_exit(&sl->sl_lock);
1598 return (ret);
1599 }
1600
1601 void
1602 sbd_close_lu(sbd_lu_t *sl)
1603 {
1604 int flag;
1605
1606 if (((sl->sl_flags & SL_SHARED_META) == 0) &&
1607 (sl->sl_flags & SL_META_OPENED)) {
1608 if (sl->sl_flags & SL_ZFS_META) {
1609 rw_destroy(&sl->sl_zfs_meta_lock);
1610 if (sl->sl_zfs_meta) {
1611 kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2);
1612 sl->sl_zfs_meta = NULL;
1613 }
1614 } else {
1615 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1616 (void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
1617 CRED(), NULL);
1618 VN_RELE(sl->sl_meta_vp);
1619 }
1620 sl->sl_flags &= ~SL_META_OPENED;
1621 }
1622 if (sl->sl_flags & SL_MEDIA_LOADED) {
1623 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1624 flag = FREAD | FOFFMAX;
1625 } else {
1626 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1627 }
1628 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1629 VN_RELE(sl->sl_data_vp);
1630 sl->sl_flags &= ~SL_MEDIA_LOADED;
1631 if (sl->sl_flags & SL_SHARED_META) {
1632 sl->sl_flags &= ~SL_META_OPENED;
1633 }
1634 }
1635 }
1636
1637 int
1638 sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret)
1639 {
1640 sbd_lu_t *sl;
1641 sbd_status_t sret;
1642 stmf_status_t stret;
1643 uint8_t old_access_state;
1644
1645 sret = sbd_find_and_lock_lu(stlu->stlu_guid, NULL,
1646 SL_OP_MODIFY_LU, &sl);
1647 if (sret != SBD_SUCCESS) {
1648 if (sret == SBD_BUSY) {
1649 *err_ret = SBD_RET_LU_BUSY;
1650 return (EBUSY);
1651 } else if (sret == SBD_NOT_FOUND) {
1652 *err_ret = SBD_RET_NOT_FOUND;
1653 return (ENOENT);
1654 }
1655 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1656 return (EIO);
1657 }
1658
1659 old_access_state = sl->sl_access_state;
1660 sl->sl_access_state = SBD_LU_TRANSITION_TO_STANDBY;
1661 stret = stmf_set_lu_access((stmf_lu_t *)sl->sl_lu, STMF_LU_STANDBY);
1662 if (stret != STMF_SUCCESS) {
1663 sl->sl_trans_op = SL_OP_NONE;
1664 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1665 sl->sl_access_state = old_access_state;
1666 return (EIO);
1667 }
1668
1669 /*
1670 * acquire the writer lock here to ensure we're not pulling
1671 * the rug from the vn_rdwr to the backing store
1672 */
1673 rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1674 sbd_close_lu(sl);
1675 rw_exit(&sl->sl_access_state_lock);
1676
1677 sl->sl_trans_op = SL_OP_NONE;
1678 return (0);
1679 }
1680
1681 int
1682 sbd_close_delete_lu(sbd_lu_t *sl, int ret)
1683 {
1684
1685 /*
1686 * acquire the writer lock here to ensure we're not pulling
1687 * the rug from the vn_rdwr to the backing store
1688 */
1689 rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1690 sbd_close_lu(sl);
1691 rw_exit(&sl->sl_access_state_lock);
1692
1693 if (sl->sl_flags & SL_LINKED)
1694 sbd_unlink_lu(sl);
1695 mutex_destroy(&sl->sl_metadata_lock);
1696 mutex_destroy(&sl->sl_lock);
1697 rw_destroy(&sl->sl_pgr->pgr_lock);
1698 rw_destroy(&sl->sl_access_state_lock);
1699 if (sl->sl_serial_no_alloc_size) {
1700 kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
1701 }
1702 if (sl->sl_data_fname_alloc_size) {
1703 kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
1704 }
1705 if (sl->sl_alias_alloc_size) {
1706 kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
1707 }
1708 if (sl->sl_mgmt_url_alloc_size) {
1709 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
1710 }
1711 stmf_free(sl->sl_lu);
1712 return (ret);
1713 }
1714
1715 int
1716 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
1717 uint32_t *err_ret)
1718 {
1719 char *namebuf;
1720 sbd_lu_t *sl;
1721 stmf_lu_t *lu;
1722 sbd_status_t sret;
1723 char *p;
1724 int sz;
1725 int alloc_sz;
1726 int ret = EIO;
1727 int flag;
1728 int wcd = 0;
1729 uint32_t hid = 0;
1730 enum vtype vt;
1731
1732 sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
1733
1734 *err_ret = 0;
1735
1736 /* Lets validate various offsets */
1737 if (((slu->slu_meta_fname_valid) &&
1738 (slu->slu_meta_fname_off >= sz)) ||
1739 (slu->slu_data_fname_off >= sz) ||
1740 ((slu->slu_alias_valid) &&
1741 (slu->slu_alias_off >= sz)) ||
1742 ((slu->slu_mgmt_url_valid) &&
1743 (slu->slu_mgmt_url_off >= sz)) ||
1744 ((slu->slu_serial_valid) &&
1745 ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
1746 return (EINVAL);
1747 }
1748
1749 namebuf = kmem_zalloc(sz, KM_SLEEP);
1750 bcopy(slu->slu_buf, namebuf, sz - 1);
1751 namebuf[sz - 1] = 0;
1752
1753 alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1754 if (slu->slu_meta_fname_valid) {
1755 alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
1756 }
1757 alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
1758 if (slu->slu_alias_valid) {
1759 alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
1760 }
1761 if (slu->slu_mgmt_url_valid) {
1762 alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
1763 }
1764 if (slu->slu_serial_valid) {
1765 alloc_sz += slu->slu_serial_size;
1766 }
1767
1768 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
1769 if (lu == NULL) {
1770 kmem_free(namebuf, sz);
1771 return (ENOMEM);
1772 }
1773 sl = (sbd_lu_t *)lu->lu_provider_private;
1774 bzero(sl, alloc_sz);
1775 sl->sl_lu = lu;
1776 sl->sl_alloc_size = alloc_sz;
1777 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1778 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1779 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1780 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
1781 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
1782 p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1783 sl->sl_data_filename = p;
1784 (void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
1785 p += strlen(sl->sl_data_filename) + 1;
1786 sl->sl_meta_offset = SBD_META_OFFSET;
1787 sl->sl_access_state = SBD_LU_ACTIVE;
1788 if (slu->slu_meta_fname_valid) {
1789 sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
1790 (void) strcpy(sl->sl_meta_filename, namebuf +
1791 slu->slu_meta_fname_off);
1792 p += strlen(sl->sl_meta_filename) + 1;
1793 } else {
1794 sl->sl_alias = sl->sl_name = sl->sl_data_filename;
1795 if (sbd_is_zvol(sl->sl_data_filename)) {
1796 sl->sl_flags |= SL_ZFS_META;
1797 sl->sl_meta_offset = 0;
1798 } else {
1799 sl->sl_flags |= SL_SHARED_META;
1800 sl->sl_data_offset = SHARED_META_DATA_SIZE;
1801 sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
1802 sl->sl_meta_size_used = 0;
1803 }
1804 }
1805 if (slu->slu_alias_valid) {
1806 sl->sl_alias = p;
1807 (void) strcpy(p, namebuf + slu->slu_alias_off);
1808 p += strlen(sl->sl_alias) + 1;
1809 }
1810 if (slu->slu_mgmt_url_valid) {
1811 sl->sl_mgmt_url = p;
1812 (void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
1813 p += strlen(sl->sl_mgmt_url) + 1;
1814 }
1815 if (slu->slu_serial_valid) {
1816 sl->sl_serial_no = (uint8_t *)p;
1817 bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
1818 slu->slu_serial_size);
1819 sl->sl_serial_no_size = slu->slu_serial_size;
1820 p += slu->slu_serial_size;
1821 }
1822 kmem_free(namebuf, sz);
1823 if (slu->slu_vid_valid) {
1824 bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
1825 sl->sl_flags |= SL_VID_VALID;
1826 }
1827 if (slu->slu_pid_valid) {
1828 bcopy(slu->slu_pid, sl->sl_product_id, 16);
1829 sl->sl_flags |= SL_PID_VALID;
1830 }
1831 if (slu->slu_rev_valid) {
1832 bcopy(slu->slu_rev, sl->sl_revision, 4);
1833 sl->sl_flags |= SL_REV_VALID;
1834 }
1835 if (slu->slu_write_protected) {
1836 sl->sl_flags |= SL_WRITE_PROTECTED;
1837 }
1838 if (slu->slu_writeback_cache_disable) {
1839 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1840 SL_SAVED_WRITE_CACHE_DISABLE;
1841 }
1842
1843 if (slu->slu_blksize_valid) {
1844 if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
1845 (slu->slu_blksize > (32 * 1024)) ||
1846 (slu->slu_blksize == 0)) {
1847 *err_ret = SBD_RET_INVALID_BLKSIZE;
1848 ret = EINVAL;
1849 goto scm_err_out;
1850 }
1851 while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
1852 sl->sl_data_blocksize_shift++;
1853 }
1854 } else {
1855 sl->sl_data_blocksize_shift = 9; /* 512 by default */
1856 slu->slu_blksize = 512;
1857 }
1858
1859 /* Now lets start creating meta */
1860 sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
1861 if (sbd_link_lu(sl) != SBD_SUCCESS) {
1862 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1863 ret = EALREADY;
1864 goto scm_err_out;
1865 }
1866
1867 /* 1st focus on the data store */
1868 if (slu->slu_lu_size_valid) {
1869 sl->sl_lu_size = slu->slu_lu_size;
1870 }
1871 ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
1872 slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
1873 slu->slu_lu_size = sl->sl_lu_size;
1874 if (ret) {
1875 goto scm_err_out;
1876 }
1877
1878 /*
1879 * set write cache disable on the device
1880 * if it fails, we'll support it using sync/flush
1881 */
1882 if (slu->slu_writeback_cache_disable) {
1883 (void) sbd_wcd_set(1, sl);
1884 wcd = 1;
1885 /*
1886 * Attempt to set it to enable, if that fails and it was explicitly set
1887 * return an error, otherwise get the current setting and use that
1888 */
1889 } else {
1890 sret = sbd_wcd_set(0, sl);
1891 if (slu->slu_writeback_cache_disable_valid &&
1892 sret != SBD_SUCCESS) {
1893 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
1894 ret = EFAULT;
1895 goto scm_err_out;
1896 }
1897 if (sret != SBD_SUCCESS) {
1898 sbd_wcd_get(&wcd, sl);
1899 }
1900 }
1901
1902 if (wcd) {
1903 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1904 SL_SAVED_WRITE_CACHE_DISABLE;
1905 }
1906
1907 if (sl->sl_flags & SL_SHARED_META) {
1908 goto over_meta_open;
1909 }
1910 if (sl->sl_flags & SL_ZFS_META) {
1911 if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
1912 *err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
1913 ret = ENOMEM;
1914 goto scm_err_out;
1915 }
1916 sl->sl_meta_blocksize_shift = 0;
1917 goto over_meta_create;
1918 }
1919 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1920 NULLVPP, &sl->sl_meta_vp)) != 0) {
1921 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1922 goto scm_err_out;
1923 }
1924 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1925 VN_RELE(sl->sl_meta_vp);
1926 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1927 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1928 ret = EINVAL;
1929 goto scm_err_out;
1930 }
1931 if (vt == VREG) {
1932 sl->sl_meta_blocksize_shift = 0;
1933 } else {
1934 sl->sl_meta_blocksize_shift = 9;
1935 }
1936 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1937 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1938 &sl->sl_meta_vp, 0, 0)) != 0) {
1939 *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1940 goto scm_err_out;
1941 }
1942 over_meta_create:
1943 sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1944 sl->sl_total_meta_size +=
1945 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1946 sl->sl_total_meta_size &=
1947 ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
1948 sl->sl_meta_size_used = 0;
1949 over_meta_open:
1950 sl->sl_flags |= SL_META_OPENED;
1951
1952 sl->sl_device_id[3] = 16;
1953 if (slu->slu_guid_valid) {
1954 sl->sl_device_id[0] = 0xf1;
1955 sl->sl_device_id[1] = 3;
1956 sl->sl_device_id[2] = 0;
1957 bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
1958 } else {
1959 if (slu->slu_host_id_valid)
1960 hid = slu->slu_host_id;
1961 if (!slu->slu_company_id_valid)
1962 slu->slu_company_id = COMPANY_ID_SUN;
1963 if (stmf_scsilib_uniq_lu_id2(slu->slu_company_id, hid,
1964 (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
1965 STMF_SUCCESS) {
1966 *err_ret = SBD_RET_META_CREATION_FAILED;
1967 ret = EIO;
1968 goto scm_err_out;
1969 }
1970 bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
1971 }
1972
1973 /* Lets create the meta now */
1974 mutex_enter(&sl->sl_metadata_lock);
1975 if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
1976 sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
1977 mutex_exit(&sl->sl_metadata_lock);
1978 *err_ret = SBD_RET_META_CREATION_FAILED;
1979 ret = EIO;
1980 goto scm_err_out;
1981 }
1982 mutex_exit(&sl->sl_metadata_lock);
1983 sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1984
1985 if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
1986 *err_ret = SBD_RET_META_CREATION_FAILED;
1987 ret = EIO;
1988 goto scm_err_out;
1989 }
1990
1991 if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) {
1992 *err_ret = SBD_RET_META_CREATION_FAILED;
1993 ret = EIO;
1994 goto scm_err_out;
1995 }
1996
1997 /*
1998 * Update the zvol separately as this need only be called upon
1999 * completion of the metadata initialization.
2000 */
2001 if (sl->sl_flags & SL_ZFS_META) {
2002 if (sbd_update_zfs_prop(sl) != SBD_SUCCESS) {
2003 *err_ret = SBD_RET_META_CREATION_FAILED;
2004 ret = EIO;
2005 goto scm_err_out;
2006 }
2007 }
2008
2009 ret = sbd_populate_and_register_lu(sl, err_ret);
2010 if (ret) {
2011 goto scm_err_out;
2012 }
2013
2014 sl->sl_trans_op = SL_OP_NONE;
2015 atomic_add_32(&sbd_lu_count, 1);
2016 return (0);
2017
2018 scm_err_out:
2019 return (sbd_close_delete_lu(sl, ret));
2020 }
2021
2022 stmf_status_t
2023 sbd_proxy_msg(uint8_t *luid, void *proxy_arg, uint32_t proxy_arg_len,
2024 uint32_t type)
2025 {
2026 switch (type) {
2027 case STMF_MSG_LU_ACTIVE:
2028 return (sbd_proxy_reg_lu(luid, proxy_arg,
2029 proxy_arg_len));
2030 case STMF_MSG_LU_REGISTER:
2031 return (sbd_proxy_reg_lu(luid, proxy_arg,
2032 proxy_arg_len));
2033 case STMF_MSG_LU_DEREGISTER:
2034 return (sbd_proxy_dereg_lu(luid, proxy_arg,
2035 proxy_arg_len));
2036 default:
2037 return (STMF_INVALID_ARG);
2038 }
2039 }
2040
2041
2042 /*
2043 * register a standby logical unit
2044 * proxy_reg_arg contains the meta filename
2045 */
2046 stmf_status_t
2047 sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg, uint32_t proxy_reg_arg_len)
2048 {
2049 sbd_lu_t *sl;
2050 sbd_status_t sret;
2051 sbd_create_standby_lu_t *stlu;
2052 int alloc_sz;
2053 uint32_t err_ret = 0;
2054 stmf_status_t stret = STMF_SUCCESS;
2055
2056 if (luid == NULL) {
2057 return (STMF_INVALID_ARG);
2058 }
2059
2060 do {
2061 sret = sbd_find_and_lock_lu(luid, NULL, SL_OP_MODIFY_LU, &sl);
2062 } while (sret == SBD_BUSY);
2063
2064 if (sret == SBD_NOT_FOUND) {
2065 alloc_sz = sizeof (*stlu) + proxy_reg_arg_len - 8;
2066 stlu = (sbd_create_standby_lu_t *)kmem_zalloc(alloc_sz,
2067 KM_SLEEP);
2068 bcopy(luid, stlu->stlu_guid, 16);
2069 if (proxy_reg_arg_len) {
2070 bcopy(proxy_reg_arg, stlu->stlu_meta_fname,
2071 proxy_reg_arg_len);
2072 stlu->stlu_meta_fname_size = proxy_reg_arg_len;
2073 }
2074 if (sbd_create_standby_lu(stlu, &err_ret) != 0) {
2075 cmn_err(CE_WARN,
2076 "Unable to create standby logical unit for %s",
2077 stlu->stlu_meta_fname);
2078 stret = STMF_FAILURE;
2079 }
2080 kmem_free(stlu, alloc_sz);
2081 return (stret);
2082 } else if (sret == SBD_SUCCESS) {
2083 /*
2084 * if the lu is already registered, then the lu should now
2085 * be in standby mode
2086 */
2087 sbd_it_data_t *it;
2088 if (sl->sl_access_state != SBD_LU_STANDBY) {
2089 mutex_enter(&sl->sl_lock);
2090 sl->sl_access_state = SBD_LU_STANDBY;
2091 for (it = sl->sl_it_list; it != NULL;
2092 it = it->sbd_it_next) {
2093 it->sbd_it_ua_conditions |=
2094 SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2095 it->sbd_it_flags &=
2096 ~SBD_IT_HAS_SCSI2_RESERVATION;
2097 sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
2098 }
2099 mutex_exit(&sl->sl_lock);
2100 sbd_pgr_reset(sl);
2101 }
2102 sl->sl_trans_op = SL_OP_NONE;
2103 } else {
2104 cmn_err(CE_WARN, "could not find and lock logical unit");
2105 stret = STMF_FAILURE;
2106 }
2107 out:
2108 return (stret);
2109 }
2110
2111 /* ARGSUSED */
2112 stmf_status_t
2113 sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
2114 uint32_t proxy_reg_arg_len)
2115 {
2116 sbd_delete_lu_t dlu = {0};
2117 uint32_t err_ret;
2118
2119 if (luid == NULL) {
2120 cmn_err(CE_WARN, "de-register lu request had null luid");
2121 return (STMF_INVALID_ARG);
2122 }
2123
2124 bcopy(luid, &dlu.dlu_guid, 16);
2125
2126 if (sbd_delete_lu(&dlu, (int)sizeof (dlu), &err_ret) != 0) {
2127 cmn_err(CE_WARN, "failed to delete de-register lu request");
2128 return (STMF_FAILURE);
2129 }
2130
2131 return (STMF_SUCCESS);
2132 }
2133
2134 int
2135 sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret)
2136 {
2137 sbd_lu_t *sl;
2138 stmf_lu_t *lu;
2139 int ret = EIO;
2140 int alloc_sz;
2141
2142 alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) +
2143 slu->stlu_meta_fname_size;
2144 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
2145 if (lu == NULL) {
2146 return (ENOMEM);
2147 }
2148 sl = (sbd_lu_t *)lu->lu_provider_private;
2149 bzero(sl, alloc_sz);
2150 sl->sl_lu = lu;
2151 sl->sl_alloc_size = alloc_sz;
2152
2153 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2154 sl->sl_meta_filename = ((char *)sl) + sizeof (sbd_lu_t) +
2155 sizeof (sbd_pgr_t);
2156
2157 if (slu->stlu_meta_fname_size > 0) {
2158 (void) strcpy(sl->sl_meta_filename, slu->stlu_meta_fname);
2159 }
2160 sl->sl_name = sl->sl_meta_filename;
2161
2162 sl->sl_device_id[3] = 16;
2163 sl->sl_device_id[0] = 0xf1;
2164 sl->sl_device_id[1] = 3;
2165 sl->sl_device_id[2] = 0;
2166 bcopy(slu->stlu_guid, sl->sl_device_id + 4, 16);
2167 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
2168 sl->sl_access_state = SBD_LU_STANDBY;
2169
2170 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2171 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2172 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2173 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2174
2175 sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
2176
2177 if (sbd_link_lu(sl) != SBD_SUCCESS) {
2178 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2179 ret = EALREADY;
2180 goto scs_err_out;
2181 }
2182
2183 ret = sbd_populate_and_register_lu(sl, err_ret);
2184 if (ret) {
2185 goto scs_err_out;
2186 }
2187
2188 sl->sl_trans_op = SL_OP_NONE;
2189 atomic_add_32(&sbd_lu_count, 1);
2190 return (0);
2191
2192 scs_err_out:
2193 return (sbd_close_delete_lu(sl, ret));
2194 }
2195
2196 int
2197 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
2198 {
2199 sbd_lu_info_1_0_t *sli = NULL;
2200 sbd_status_t sret;
2201
2202 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2203 SMS_ID_LU_INFO_1_0);
2204
2205 if (sret != SBD_SUCCESS) {
2206 *err_ret = SBD_RET_NO_META;
2207 return (EIO);
2208 }
2209 if (sli->sli_data_order != SMS_DATA_ORDER) {
2210 sbd_swap_lu_info_1_0(sli);
2211 if (sli->sli_data_order != SMS_DATA_ORDER) {
2212 kmem_free(sli, sli->sli_sms_header.sms_size);
2213 *err_ret = SBD_RET_NO_META;
2214 return (EIO);
2215 }
2216 }
2217
2218 sl->sl_flags |= SL_SHARED_META;
2219 sl->sl_data_blocksize_shift = 9;
2220 sl->sl_data_offset = SHARED_META_DATA_SIZE;
2221 sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
2222 sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
2223 bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
2224
2225 kmem_free(sli, sli->sli_sms_header.sms_size);
2226 return (0);
2227 }
2228
2229 int
2230 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
2231 int no_register, sbd_lu_t **slr)
2232 {
2233 stmf_lu_t *lu;
2234 sbd_lu_t *sl;
2235 sbd_lu_info_1_1_t *sli = NULL;
2236 int asz;
2237 int ret = 0;
2238 stmf_status_t stret;
2239 int flag;
2240 int wcd = 0;
2241 int data_opened;
2242 uint16_t sli_buf_sz;
2243 uint8_t *sli_buf_copy = NULL;
2244 enum vtype vt;
2245 int standby = 0;
2246 sbd_status_t sret;
2247
2248 if (no_register && slr == NULL) {
2249 return (EINVAL);
2250 }
2251 ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
2252 /*
2253 * check whether logical unit is already registered ALUA
2254 * For a standby logical unit, the meta filename is set. Use
2255 * that to search for an existing logical unit.
2256 */
2257 sret = sbd_find_and_lock_lu(NULL, (uint8_t *)&(ilu->ilu_meta_fname),
2258 SL_OP_IMPORT_LU, &sl);
2259
2260 if (sret == SBD_SUCCESS) {
2261 if (sl->sl_access_state != SBD_LU_ACTIVE) {
2262 no_register = 1;
2263 standby = 1;
2264 lu = sl->sl_lu;
2265 if (sl->sl_alias_alloc_size) {
2266 kmem_free(sl->sl_alias,
2267 sl->sl_alias_alloc_size);
2268 sl->sl_alias_alloc_size = 0;
2269 sl->sl_alias = NULL;
2270 lu->lu_alias = NULL;
2271 }
2272 if (sl->sl_meta_filename == NULL) {
2273 sl->sl_meta_filename = sl->sl_data_filename;
2274 } else if (sl->sl_data_fname_alloc_size) {
2275 kmem_free(sl->sl_data_filename,
2276 sl->sl_data_fname_alloc_size);
2277 sl->sl_data_fname_alloc_size = 0;
2278 }
2279 if (sl->sl_serial_no_alloc_size) {
2280 kmem_free(sl->sl_serial_no,
2281 sl->sl_serial_no_alloc_size);
2282 sl->sl_serial_no_alloc_size = 0;
2283 }
2284 if (sl->sl_mgmt_url_alloc_size) {
2285 kmem_free(sl->sl_mgmt_url,
2286 sl->sl_mgmt_url_alloc_size);
2287 sl->sl_mgmt_url_alloc_size = 0;
2288 }
2289 } else {
2290 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2291 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2292 sl->sl_trans_op = SL_OP_NONE;
2293 return (EALREADY);
2294 }
2295 } else if (sret == SBD_NOT_FOUND) {
2296 asz = strlen(ilu->ilu_meta_fname) + 1;
2297
2298 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
2299 sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
2300 if (lu == NULL) {
2301 return (ENOMEM);
2302 }
2303 sl = (sbd_lu_t *)lu->lu_provider_private;
2304 bzero(sl, sizeof (*sl));
2305 sl->sl_lu = lu;
2306 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2307 sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) +
2308 sizeof (sbd_pgr_t);
2309 (void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
2310 sl->sl_name = sl->sl_meta_filename;
2311 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2312 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2313 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2314 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2315 sl->sl_trans_op = SL_OP_IMPORT_LU;
2316 } else {
2317 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2318 return (EIO);
2319 }
2320
2321 /* we're only loading the metadata */
2322 if (!no_register) {
2323 if (sbd_link_lu(sl) != SBD_SUCCESS) {
2324 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2325 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2326 ret = EALREADY;
2327 goto sim_err_out;
2328 }
2329 }
2330 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
2331 NULLVPP, &sl->sl_meta_vp)) != 0) {
2332 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2333 goto sim_err_out;
2334 }
2335 if (sbd_is_zvol(sl->sl_meta_filename)) {
2336 sl->sl_flags |= SL_ZFS_META;
2337 sl->sl_data_filename = sl->sl_meta_filename;
2338 }
2339 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
2340 VN_RELE(sl->sl_meta_vp);
2341 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
2342 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
2343 ret = EINVAL;
2344 goto sim_err_out;
2345 }
2346 if (sl->sl_flags & SL_ZFS_META) {
2347 if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
2348 /* let see if metadata is in the 64k block */
2349 sl->sl_flags &= ~SL_ZFS_META;
2350 }
2351 }
2352 if (!(sl->sl_flags & SL_ZFS_META)) {
2353 /* metadata is always writable */
2354 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2355 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
2356 &sl->sl_meta_vp, 0, 0)) != 0) {
2357 *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
2358 goto sim_err_out;
2359 }
2360 }
2361 if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
2362 sl->sl_meta_blocksize_shift = 0;
2363 } else {
2364 sl->sl_meta_blocksize_shift = 9;
2365 }
2366 sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET;
2367 sl->sl_flags |= SL_META_OPENED;
2368
2369 mutex_enter(&sl->sl_metadata_lock);
2370 sret = sbd_load_meta_start(sl);
2371 mutex_exit(&sl->sl_metadata_lock);
2372 if (sret != SBD_SUCCESS) {
2373 if (sret == SBD_META_CORRUPTED) {
2374 *err_ret = SBD_RET_NO_META;
2375 } else if (sret == SBD_NOT_SUPPORTED) {
2376 *err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
2377 } else {
2378 *err_ret = SBD_RET_NO_META;
2379 }
2380 ret = EINVAL;
2381 goto sim_err_out;
2382 }
2383
2384 /* Now lets see if we can read the most recent LU info */
2385 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2386 SMS_ID_LU_INFO_1_1);
2387 if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
2388 ret = sbd_load_sli_1_0(sl, err_ret);
2389 if (ret) {
2390 goto sim_err_out;
2391 }
2392 goto sim_sli_loaded;
2393 }
2394 if (sret != SBD_SUCCESS) {
2395 *err_ret = SBD_RET_NO_META;
2396 ret = EIO;
2397 goto sim_err_out;
2398 }
2399 /* load sli 1.1 */
2400 if (sli->sli_data_order != SMS_DATA_ORDER) {
2401 sbd_swap_lu_info_1_1(sli);
2402 if (sli->sli_data_order != SMS_DATA_ORDER) {
2403 *err_ret = SBD_RET_NO_META;
2404 ret = EIO;
2405 goto sim_err_out;
2406 }
2407 }
2408
2409 sli_buf_sz = sli->sli_sms_header.sms_size -
2410 sizeof (sbd_lu_info_1_1_t) + 8;
2411 sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
2412 bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
2413 sli_buf_copy[sli_buf_sz] = 0;
2414
2415 /* Make sure all the offsets are within limits */
2416 if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
2417 (sli->sli_meta_fname_offset > sli_buf_sz)) ||
2418 ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
2419 (sli->sli_data_fname_offset > sli_buf_sz)) ||
2420 ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
2421 (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
2422 ((sli->sli_flags & SLI_SERIAL_VALID) &&
2423 ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
2424 ((sli->sli_flags & SLI_ALIAS_VALID) &&
2425 (sli->sli_alias_offset > sli_buf_sz))) {
2426 *err_ret = SBD_RET_NO_META;
2427 ret = EIO;
2428 goto sim_err_out;
2429 }
2430
2431 sl->sl_lu_size = sli->sli_lu_size;
2432 sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
2433 bcopy(sli->sli_device_id, sl->sl_device_id, 20);
2434 if (sli->sli_flags & SLI_SERIAL_VALID) {
2435 sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
2436 sli->sli_serial_size;
2437 sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
2438 bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
2439 sl->sl_serial_no_size);
2440 }
2441 if (sli->sli_flags & SLI_SEPARATE_META) {
2442 sl->sl_total_data_size = sl->sl_lu_size;
2443 if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
2444 sl->sl_data_fname_alloc_size = strlen((char *)
2445 sli_buf_copy + sli->sli_data_fname_offset) + 1;
2446 sl->sl_data_filename = kmem_zalloc(
2447 sl->sl_data_fname_alloc_size, KM_SLEEP);
2448 (void) strcpy(sl->sl_data_filename,
2449 (char *)sli_buf_copy + sli->sli_data_fname_offset);
2450 }
2451 } else {
2452 if (sl->sl_flags & SL_ZFS_META) {
2453 sl->sl_total_data_size = sl->sl_lu_size;
2454 sl->sl_data_offset = 0;
2455 } else {
2456 sl->sl_total_data_size =
2457 sl->sl_lu_size + SHARED_META_DATA_SIZE;
2458 sl->sl_data_offset = SHARED_META_DATA_SIZE;
2459 sl->sl_flags |= SL_SHARED_META;
2460 }
2461 }
2462 if (sli->sli_flags & SLI_ALIAS_VALID) {
2463 sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
2464 sli->sli_alias_offset) + 1;
2465 sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
2466 (void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
2467 sli->sli_alias_offset);
2468 }
2469 if (sli->sli_flags & SLI_MGMT_URL_VALID) {
2470 sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
2471 sli->sli_mgmt_url_offset) + 1;
2472 sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
2473 KM_SLEEP);
2474 (void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
2475 sli->sli_mgmt_url_offset);
2476 }
2477 if (sli->sli_flags & SLI_WRITE_PROTECTED) {
2478 sl->sl_flags |= SL_WRITE_PROTECTED;
2479 }
2480 if (sli->sli_flags & SLI_VID_VALID) {
2481 sl->sl_flags |= SL_VID_VALID;
2482 bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
2483 }
2484 if (sli->sli_flags & SLI_PID_VALID) {
2485 sl->sl_flags |= SL_PID_VALID;
2486 bcopy(sli->sli_pid, sl->sl_product_id, 16);
2487 }
2488 if (sli->sli_flags & SLI_REV_VALID) {
2489 sl->sl_flags |= SL_REV_VALID;
2490 bcopy(sli->sli_rev, sl->sl_revision, 4);
2491 }
2492 if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
2493 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2494 }
2495 sim_sli_loaded:
2496 if ((sl->sl_flags & SL_SHARED_META) == 0) {
2497 data_opened = 0;
2498 } else {
2499 data_opened = 1;
2500 sl->sl_data_filename = sl->sl_meta_filename;
2501 sl->sl_data_vp = sl->sl_meta_vp;
2502 sl->sl_data_vtype = sl->sl_meta_vtype;
2503 }
2504
2505 sret = sbd_pgr_meta_load(sl);
2506 if (sret != SBD_SUCCESS) {
2507 *err_ret = SBD_RET_NO_META;
2508 ret = EIO;
2509 goto sim_err_out;
2510 }
2511
2512 ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
2513 if (ret) {
2514 goto sim_err_out;
2515 }
2516
2517 /*
2518 * set write cache disable on the device
2519 * Note: this shouldn't fail on import unless the cache capabilities
2520 * of the device changed. If that happened, modify will need to
2521 * be used to set the cache flag appropriately after import is done.
2522 */
2523 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2524 (void) sbd_wcd_set(1, sl);
2525 wcd = 1;
2526 /*
2527 * if not explicitly set, attempt to set it to enable, if that fails
2528 * get the current setting and use that
2529 */
2530 } else {
2531 sret = sbd_wcd_set(0, sl);
2532 if (sret != SBD_SUCCESS) {
2533 sbd_wcd_get(&wcd, sl);
2534 }
2535 }
2536
2537 if (wcd) {
2538 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
2539 SL_SAVED_WRITE_CACHE_DISABLE;
2540 }
2541
2542 /* we're only loading the metadata */
2543 if (!no_register) {
2544 ret = sbd_populate_and_register_lu(sl, err_ret);
2545 if (ret) {
2546 goto sim_err_out;
2547 }
2548 atomic_add_32(&sbd_lu_count, 1);
2549 }
2550
2551 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2552 sl->sl_trans_op = SL_OP_NONE;
2553
2554 if (sli) {
2555 kmem_free(sli, sli->sli_sms_header.sms_size);
2556 sli = NULL;
2557 }
2558 if (sli_buf_copy) {
2559 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2560 sli_buf_copy = NULL;
2561 }
2562 if (no_register && !standby) {
2563 *slr = sl;
2564 }
2565
2566 /*
2567 * if this was imported from standby, set the access state
2568 * to active.
2569 */
2570 if (standby) {
2571 sbd_it_data_t *it;
2572 mutex_enter(&sl->sl_lock);
2573 sl->sl_access_state = SBD_LU_ACTIVE;
2574 for (it = sl->sl_it_list; it != NULL;
2575 it = it->sbd_it_next) {
2576 it->sbd_it_ua_conditions |=
2577 SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2578 it->sbd_it_ua_conditions |= SBD_UA_POR;
2579 it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
2580 }
2581 mutex_exit(&sl->sl_lock);
2582 /* call set access state */
2583 stret = stmf_set_lu_access(lu, STMF_LU_ACTIVE);
2584 if (stret != STMF_SUCCESS) {
2585 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2586 sl->sl_access_state = SBD_LU_STANDBY;
2587 goto sim_err_out;
2588 }
2589 if (sl->sl_alias) {
2590 lu->lu_alias = sl->sl_alias;
2591 } else {
2592 lu->lu_alias = sl->sl_name;
2593 }
2594 }
2595 sl->sl_access_state = SBD_LU_ACTIVE;
2596 return (0);
2597
2598 sim_err_out:
2599 if (sli) {
2600 kmem_free(sli, sli->sli_sms_header.sms_size);
2601 sli = NULL;
2602 }
2603 if (sli_buf_copy) {
2604 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2605 sli_buf_copy = NULL;
2606 }
2607
2608 if (standby) {
2609 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2610 sl->sl_trans_op = SL_OP_NONE;
2611 return (EIO);
2612 } else {
2613 return (sbd_close_delete_lu(sl, ret));
2614 }
2615 }
2616
2617 int
2618 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
2619 {
2620 sbd_lu_t *sl = NULL;
2621 uint16_t alias_sz;
2622 int ret = 0;
2623 sbd_it_data_t *it;
2624 sbd_status_t sret;
2625 uint64_t old_size;
2626 int modify_unregistered = 0;
2627 int ua = 0;
2628 sbd_import_lu_t *ilu;
2629 stmf_lu_t *lu;
2630 uint32_t ilu_sz;
2631 uint32_t sz;
2632
2633 sz = struct_sz - sizeof (*mlu) + 8 + 1;
2634
2635 /* if there is data in the buf, null terminate it */
2636 if (struct_sz > sizeof (*mlu)) {
2637 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2638 }
2639
2640 *err_ret = 0;
2641
2642 /* Lets validate offsets */
2643 if (((mlu->mlu_alias_valid) &&
2644 (mlu->mlu_alias_off >= sz)) ||
2645 ((mlu->mlu_mgmt_url_valid) &&
2646 (mlu->mlu_mgmt_url_off >= sz)) ||
2647 (mlu->mlu_by_fname) &&
2648 (mlu->mlu_fname_off >= sz)) {
2649 return (EINVAL);
2650 }
2651
2652 /*
2653 * We'll look for the device but if we don't find it registered,
2654 * we'll still try to modify the unregistered device.
2655 */
2656 if (mlu->mlu_by_guid) {
2657 sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
2658 SL_OP_MODIFY_LU, &sl);
2659 } else if (mlu->mlu_by_fname) {
2660 sret = sbd_find_and_lock_lu(NULL,
2661 (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
2662 SL_OP_MODIFY_LU, &sl);
2663 } else {
2664 return (EINVAL);
2665 }
2666
2667
2668 if (sret != SBD_SUCCESS) {
2669 if (sret == SBD_BUSY) {
2670 *err_ret = SBD_RET_LU_BUSY;
2671 return (EBUSY);
2672 } else if (sret != SBD_NOT_FOUND) {
2673 return (EIO);
2674 } else if (!mlu->mlu_by_fname) {
2675 return (EINVAL);
2676 }
2677 /* Okay, try to import the device */
2678 struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
2679 + 1);
2680 struct_sz += sizeof (sbd_import_lu_t) - 8;
2681 ilu_sz = struct_sz;
2682 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
2683 ilu->ilu_struct_size = struct_sz;
2684 (void) strcpy(ilu->ilu_meta_fname,
2685 &(mlu->mlu_buf[mlu->mlu_fname_off]));
2686 ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
2687 kmem_free(ilu, ilu_sz);
2688 if (ret != SBD_SUCCESS) {
2689 return (ENOENT);
2690 }
2691 modify_unregistered = 1;
2692 }
2693
2694 if (sl->sl_access_state != SBD_LU_ACTIVE) {
2695 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2696 ret = EINVAL;
2697 goto smm_err_out;
2698 }
2699
2700 /* check for write cache change */
2701 if (mlu->mlu_writeback_cache_disable_valid) {
2702 /* set wce on device */
2703 sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
2704 if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
2705 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
2706 ret = EFAULT;
2707 goto smm_err_out;
2708 }
2709 mutex_enter(&sl->sl_lock);
2710 if (!mlu->mlu_writeback_cache_disable) {
2711 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2712 ua = 1;
2713 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2714 sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2715 }
2716 } else {
2717 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2718 ua = 1;
2719 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2720 sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2721 }
2722 }
2723 for (it = sl->sl_it_list; ua && it != NULL;
2724 it = it->sbd_it_next) {
2725 it->sbd_it_ua_conditions |=
2726 SBD_UA_MODE_PARAMETERS_CHANGED;
2727 }
2728 mutex_exit(&sl->sl_lock);
2729 }
2730 ua = 0;
2731
2732 if (mlu->mlu_alias_valid) {
2733 alias_sz = strlen((char *)mlu->mlu_buf +
2734 mlu->mlu_alias_off) + 1;
2735 /*
2736 * Use the allocated buffer or alloc a new one.
2737 * Don't copy into sl_alias if sl_alias_alloc_size is 0
2738 * otherwise or you'll be writing over the data/metadata
2739 * filename.
2740 */
2741 mutex_enter(&sl->sl_lock);
2742 if (sl->sl_alias_alloc_size > 0 &&
2743 sl->sl_alias_alloc_size < alias_sz) {
2744 kmem_free(sl->sl_alias,
2745 sl->sl_alias_alloc_size);
2746 sl->sl_alias_alloc_size = 0;
2747 }
2748 if (sl->sl_alias_alloc_size == 0) {
2749 sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
2750 sl->sl_alias_alloc_size = alias_sz;
2751 }
2752 (void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
2753 mlu->mlu_alias_off);
2754 lu = sl->sl_lu;
2755 lu->lu_alias = sl->sl_alias;
2756 mutex_exit(&sl->sl_lock);
2757 }
2758
2759 if (mlu->mlu_mgmt_url_valid) {
2760 uint16_t url_sz;
2761
2762 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2763 if (url_sz > 0)
2764 url_sz++;
2765
2766 mutex_enter(&sl->sl_lock);
2767 if (sl->sl_mgmt_url_alloc_size > 0 &&
2768 (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
2769 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
2770 sl->sl_mgmt_url = NULL;
2771 sl->sl_mgmt_url_alloc_size = 0;
2772 }
2773 if (url_sz > 0) {
2774 if (sl->sl_mgmt_url_alloc_size == 0) {
2775 sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2776 sl->sl_mgmt_url_alloc_size = url_sz;
2777 }
2778 (void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
2779 mlu->mlu_mgmt_url_off);
2780 }
2781 for (it = sl->sl_it_list; it != NULL;
2782 it = it->sbd_it_next) {
2783 it->sbd_it_ua_conditions |=
2784 SBD_UA_MODE_PARAMETERS_CHANGED;
2785 }
2786 mutex_exit(&sl->sl_lock);
2787 }
2788
2789 if (mlu->mlu_write_protected_valid) {
2790 mutex_enter(&sl->sl_lock);
2791 if (mlu->mlu_write_protected) {
2792 if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
2793 ua = 1;
2794 sl->sl_flags |= SL_WRITE_PROTECTED;
2795 }
2796 } else {
2797 if (sl->sl_flags & SL_WRITE_PROTECTED) {
2798 ua = 1;
2799 sl->sl_flags &= ~SL_WRITE_PROTECTED;
2800 }
2801 }
2802 for (it = sl->sl_it_list; ua && it != NULL;
2803 it = it->sbd_it_next) {
2804 it->sbd_it_ua_conditions |=
2805 SBD_UA_MODE_PARAMETERS_CHANGED;
2806 }
2807 mutex_exit(&sl->sl_lock);
2808 }
2809
2810 if (mlu->mlu_lu_size_valid) {
2811 /*
2812 * validate lu size and set
2813 * For open file only (registered lu)
2814 */
2815 mutex_enter(&sl->sl_lock);
2816 old_size = sl->sl_lu_size;
2817 sl->sl_lu_size = mlu->mlu_lu_size;
2818 mutex_exit(&sl->sl_lock);
2819 ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
2820 if (ret) {
2821 mutex_enter(&sl->sl_lock);
2822 sl->sl_lu_size = old_size;
2823 mutex_exit(&sl->sl_lock);
2824 goto smm_err_out;
2825 }
2826 if (old_size != mlu->mlu_lu_size) {
2827 mutex_enter(&sl->sl_lock);
2828 for (it = sl->sl_it_list; it != NULL;
2829 it = it->sbd_it_next) {
2830 it->sbd_it_ua_conditions |=
2831 SBD_UA_CAPACITY_CHANGED;
2832 }
2833 mutex_exit(&sl->sl_lock);
2834 }
2835 }
2836
2837 if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2838 *err_ret = SBD_RET_META_CREATION_FAILED;
2839 ret = EIO;
2840 }
2841
2842 smm_err_out:
2843 if (modify_unregistered) {
2844 (void) sbd_close_delete_lu(sl, 0);
2845 } else {
2846 sl->sl_trans_op = SL_OP_NONE;
2847 }
2848 return (ret);
2849 }
2850
2851 int
2852 sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
2853 uint32_t *err_ret)
2854 {
2855 sbd_lu_t *sl = NULL;
2856 int ret = 0;
2857 sbd_it_data_t *it;
2858 uint32_t sz;
2859
2860 sz = struct_sz - sizeof (*mlu) + 8 + 1;
2861
2862 /* if there is data in the buf, null terminate it */
2863 if (struct_sz > sizeof (*mlu)) {
2864 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2865 }
2866
2867 *err_ret = 0;
2868
2869 /* Lets validate offsets */
2870 if (((mlu->mlu_mgmt_url_valid) &&
2871 (mlu->mlu_mgmt_url_off >= sz))) {
2872 return (EINVAL);
2873 }
2874
2875 if (mlu->mlu_mgmt_url_valid) {
2876 uint16_t url_sz;
2877
2878 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2879 if (url_sz > 0)
2880 url_sz++;
2881
2882 rw_enter(&sbd_global_prop_lock, RW_WRITER);
2883 if (sbd_mgmt_url_alloc_size > 0 &&
2884 (url_sz == 0 || sbd_mgmt_url_alloc_size < url_sz)) {
2885 kmem_free(sbd_mgmt_url, sbd_mgmt_url_alloc_size);
2886 sbd_mgmt_url = NULL;
2887 sbd_mgmt_url_alloc_size = 0;
2888 }
2889 if (url_sz > 0) {
2890 if (sbd_mgmt_url_alloc_size == 0) {
2891 sbd_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2892 sbd_mgmt_url_alloc_size = url_sz;
2893 }
2894 (void) strcpy(sbd_mgmt_url, (char *)mlu->mlu_buf +
2895 mlu->mlu_mgmt_url_off);
2896 }
2897 /*
2898 * check each lu to determine whether a UA is needed.
2899 */
2900 mutex_enter(&sbd_lock);
2901 for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
2902 if (sl->sl_mgmt_url) {
2903 continue;
2904 }
2905 mutex_enter(&sl->sl_lock);
2906 for (it = sl->sl_it_list; it != NULL;
2907 it = it->sbd_it_next) {
2908 it->sbd_it_ua_conditions |=
2909 SBD_UA_MODE_PARAMETERS_CHANGED;
2910 }
2911 mutex_exit(&sl->sl_lock);
2912 }
2913 mutex_exit(&sbd_lock);
2914 rw_exit(&sbd_global_prop_lock);
2915 }
2916 return (ret);
2917 }
2918
2919 /* ARGSUSED */
2920 int
2921 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
2922 stmf_state_change_info_t *ssi)
2923 {
2924 int i;
2925 stmf_status_t ret;
2926
2927 if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2928 !sl->sl_state_not_acked) {
2929 goto sdl_do_dereg;
2930 }
2931
2932 if ((sl->sl_state != STMF_STATE_ONLINE) ||
2933 sl->sl_state_not_acked) {
2934 return (EBUSY);
2935 }
2936
2937 ret = stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi);
2938 if ((ret != STMF_SUCCESS) && (ret != STMF_ALREADY)) {
2939 return (EBUSY);
2940 }
2941
2942 for (i = 0; i < 500; i++) {
2943 if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2944 !sl->sl_state_not_acked) {
2945 goto sdl_do_dereg;
2946 }
2947 delay(drv_usectohz(10000));
2948 }
2949 return (EBUSY);
2950
2951 sdl_do_dereg:;
2952 if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
2953 return (EBUSY);
2954 atomic_add_32(&sbd_lu_count, -1);
2955
2956 return (sbd_close_delete_lu(sl, 0));
2957 }
2958
2959 int
2960 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
2961 {
2962 sbd_lu_t *sl;
2963 sbd_status_t sret;
2964 stmf_state_change_info_t ssi;
2965 int ret;
2966
2967 if (dlu->dlu_by_meta_name) {
2968 ((char *)dlu)[struct_sz - 1] = 0;
2969 sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
2970 SL_OP_DELETE_LU, &sl);
2971 } else {
2972 sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
2973 SL_OP_DELETE_LU, &sl);
2974 }
2975 if (sret != SBD_SUCCESS) {
2976 if (sret == SBD_BUSY) {
2977 *err_ret = SBD_RET_LU_BUSY;
2978 return (EBUSY);
2979 } else if (sret == SBD_NOT_FOUND) {
2980 *err_ret = SBD_RET_NOT_FOUND;
2981 return (ENOENT);
2982 }
2983 return (EIO);
2984 }
2985
2986 ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
2987 ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
2988 ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
2989
2990 if (ret) {
2991 /* Once its locked, no need to grab mutex again */
2992 sl->sl_trans_op = SL_OP_NONE;
2993 }
2994 return (ret);
2995 }
2996
2997 sbd_status_t
2998 sbd_data_read(sbd_lu_t *sl, struct scsi_task *task,
2999 uint64_t offset, uint64_t size, uint8_t *buf)
3000 {
3001 int ret;
3002 long resid;
3003 hrtime_t xfer_start, xfer_done;
3004
3005 if ((offset + size) > sl->sl_lu_size) {
3006 return (SBD_IO_PAST_EOF);
3007 }
3008
3009 offset += sl->sl_data_offset;
3010
3011 if ((offset + size) > sl->sl_data_readable_size) {
3012 uint64_t store_end;
3013 if (offset > sl->sl_data_readable_size) {
3014 bzero(buf, size);
3015 return (SBD_SUCCESS);
3016 }
3017 store_end = sl->sl_data_readable_size - offset;
3018 bzero(buf + store_end, size - store_end);
3019 size = store_end;
3020 }
3021
3022 xfer_start = gethrtime();
3023 stmf_lu_xfer_start(task);
3024 DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
3025 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3026 scsi_task_t *, task);
3027
3028 /*
3029 * Don't proceed if the device has been closed
3030 * This can occur on an access state change to standby or
3031 * a delete. The writer lock is acquired before closing the
3032 * lu.
3033 */
3034 rw_enter(&sl->sl_access_state_lock, RW_READER);
3035 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3036 rw_exit(&sl->sl_access_state_lock);
3037 return (SBD_FAILURE);
3038 }
3039 ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3040 (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
3041 &resid);
3042 rw_exit(&sl->sl_access_state_lock);
3043
3044 xfer_done = gethrtime() - xfer_start;
3045 stmf_lu_xfer_done(task, B_TRUE /* read */, size, xfer_done);
3046 DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
3047 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3048 int, ret, scsi_task_t *, task);
3049
3050 over_sl_data_read:
3051 if (ret || resid) {
3052 stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
3053 resid);
3054 return (SBD_FAILURE);
3055 }
3056
3057 return (SBD_SUCCESS);
3058 }
3059
3060 sbd_status_t
3061 sbd_data_write(sbd_lu_t *sl, struct scsi_task *task,
3062 uint64_t offset, uint64_t size, uint8_t *buf)
3063 {
3064 int ret;
3065 long resid;
3066 sbd_status_t sret = SBD_SUCCESS;
3067 int ioflag;
3068 hrtime_t xfer_start, xfer_done;
3069
3070 if ((offset + size) > sl->sl_lu_size) {
3071 return (SBD_IO_PAST_EOF);
3072 }
3073
3074 offset += sl->sl_data_offset;
3075
3076 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3077 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3078 ioflag = FSYNC;
3079 } else {
3080 ioflag = 0;
3081 }
3082
3083 xfer_start = gethrtime();
3084 stmf_lu_xfer_start(task);
3085 DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3086 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3087 scsi_task_t *, task);
3088
3089 /*
3090 * Don't proceed if the device has been closed
3091 * This can occur on an access state change to standby or
3092 * a delete. The writer lock is acquired before closing the
3093 * lu.
3094 */
3095 rw_enter(&sl->sl_access_state_lock, RW_READER);
3096 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3097 rw_exit(&sl->sl_access_state_lock);
3098 return (SBD_FAILURE);
3099 }
3100 ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3101 (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
3102 &resid);
3103 rw_exit(&sl->sl_access_state_lock);
3104
3105 xfer_done = gethrtime() - xfer_start;
3106 stmf_lu_xfer_done(task, B_FALSE /* write */, size, xfer_done);
3107 DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3108 uint8_t *, buf, uint64_t, size, uint64_t, offset,
3109 int, ret, scsi_task_t *, task);
3110
3111 if ((ret == 0) && (resid == 0) &&
3112 (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3113 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3114 sret = sbd_flush_data_cache(sl, 1);
3115 }
3116 over_sl_data_write:
3117
3118 if ((ret || resid) || (sret != SBD_SUCCESS)) {
3119 return (SBD_FAILURE);
3120 } else if ((offset + size) > sl->sl_data_readable_size) {
3121 uint64_t old_size, new_size;
3122
3123 do {
3124 old_size = sl->sl_data_readable_size;
3125 if ((offset + size) <= old_size)
3126 break;
3127 new_size = offset + size;
3128 } while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
3129 new_size) != old_size);
3130 }
3131
3132 return (SBD_SUCCESS);
3133 }
3134
3135 int
3136 sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
3137 uint32_t *err_ret)
3138 {
3139 uint32_t sz = 0;
3140 uint16_t off;
3141
3142 rw_enter(&sbd_global_prop_lock, RW_READER);
3143 if (sbd_mgmt_url) {
3144 sz += strlen(sbd_mgmt_url) + 1;
3145 }
3146 bzero(oslp, sizeof (*oslp) - 8);
3147 oslp->mlu_buf_size_needed = sz;
3148
3149 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3150 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3151 rw_exit(&sbd_global_prop_lock);
3152 return (ENOMEM);
3153 }
3154
3155 off = 0;
3156 if (sbd_mgmt_url) {
3157 oslp->mlu_mgmt_url_valid = 1;
3158 oslp->mlu_mgmt_url_off = off;
3159 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3160 off += strlen(sbd_mgmt_url) + 1;
3161 }
3162
3163 rw_exit(&sbd_global_prop_lock);
3164 return (0);
3165 }
3166
3167 static int
3168 sbd_get_unmap_props(sbd_unmap_props_t *sup,
3169 sbd_unmap_props_t *osup, uint32_t *err_ret)
3170 {
3171 sbd_status_t sret;
3172 sbd_lu_t *sl = NULL;
3173
3174 if (sup->sup_guid_valid) {
3175 sret = sbd_find_and_lock_lu(sup->sup_guid,
3176 NULL, SL_OP_LU_PROPS, &sl);
3177 } else {
3178 sret = sbd_find_and_lock_lu(NULL,
3179 (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS,
3180 &sl);
3181 }
3182 if (sret != SBD_SUCCESS) {
3183 if (sret == SBD_BUSY) {
3184 *err_ret = SBD_RET_LU_BUSY;
3185 return (EBUSY);
3186 } else if (sret == SBD_NOT_FOUND) {
3187 *err_ret = SBD_RET_NOT_FOUND;
3188 return (ENOENT);
3189 }
3190 return (EIO);
3191 }
3192
3193 sup->sup_found_lu = 1;
3194 sup->sup_guid_valid = 1;
3195 bcopy(sl->sl_device_id + 4, sup->sup_guid, 16);
3196 if (sl->sl_flags & SL_UNMAP_ENABLED)
3197 sup->sup_unmap_enabled = 1;
3198 else
3199 sup->sup_unmap_enabled = 0;
3200
3201 *osup = *sup;
3202 sl->sl_trans_op = SL_OP_NONE;
3203
3204 return (0);
3205 }
3206
3207 int
3208 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3209 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3210 {
3211 sbd_status_t sret;
3212 sbd_lu_t *sl = NULL;
3213 uint32_t sz;
3214 uint16_t off;
3215
3216 if (islp->slp_input_guid) {
3217 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3218 SL_OP_LU_PROPS, &sl);
3219 } else {
3220 ((char *)islp)[islp_sz - 1] = 0;
3221 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3222 SL_OP_LU_PROPS, &sl);
3223 }
3224 if (sret != SBD_SUCCESS) {
3225 if (sret == SBD_BUSY) {
3226 *err_ret = SBD_RET_LU_BUSY;
3227 return (EBUSY);
3228 } else if (sret == SBD_NOT_FOUND) {
3229 *err_ret = SBD_RET_NOT_FOUND;
3230 return (ENOENT);
3231 }
3232 return (EIO);
3233 }
3234
3235 sz = strlen(sl->sl_name) + 1;
3236 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3237 if (sl->sl_data_filename) {
3238 sz += strlen(sl->sl_data_filename) + 1;
3239 }
3240 }
3241 sz += sl->sl_serial_no_size;
3242 if (sl->sl_alias) {
3243 sz += strlen(sl->sl_alias) + 1;
3244 }
3245
3246 rw_enter(&sbd_global_prop_lock, RW_READER);
3247 if (sl->sl_mgmt_url) {
3248 sz += strlen(sl->sl_mgmt_url) + 1;
3249 } else if (sbd_mgmt_url) {
3250 sz += strlen(sbd_mgmt_url) + 1;
3251 }
3252 bzero(oslp, sizeof (*oslp) - 8);
3253 oslp->slp_buf_size_needed = sz;
3254
3255 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3256 sl->sl_trans_op = SL_OP_NONE;
3257 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3258 rw_exit(&sbd_global_prop_lock);
3259 return (ENOMEM);
3260 }
3261
3262 off = 0;
3263 (void) strcpy((char *)oslp->slp_buf, sl->sl_name);
3264 oslp->slp_meta_fname_off = off;
3265 off += strlen(sl->sl_name) + 1;
3266 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3267 oslp->slp_meta_fname_valid = 1;
3268 oslp->slp_separate_meta = 1;
3269 if (sl->sl_data_filename) {
3270 oslp->slp_data_fname_valid = 1;
3271 oslp->slp_data_fname_off = off;
3272 (void) strcpy((char *)&oslp->slp_buf[off],
3273 sl->sl_data_filename);
3274 off += strlen(sl->sl_data_filename) + 1;
3275 }
3276 } else {
3277 oslp->slp_data_fname_valid = 1;
3278 oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
3279 if (sl->sl_flags & SL_ZFS_META) {
3280 oslp->slp_zfs_meta = 1;
3281 }
3282 }
3283 if (sl->sl_alias) {
3284 oslp->slp_alias_valid = 1;
3285 oslp->slp_alias_off = off;
3286 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
3287 off += strlen(sl->sl_alias) + 1;
3288 }
3289 if (sl->sl_mgmt_url) {
3290 oslp->slp_mgmt_url_valid = 1;
3291 oslp->slp_mgmt_url_off = off;
3292 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
3293 off += strlen(sl->sl_mgmt_url) + 1;
3294 } else if (sbd_mgmt_url) {
3295 oslp->slp_mgmt_url_valid = 1;
3296 oslp->slp_mgmt_url_off = off;
3297 (void) strcpy((char *)&oslp->slp_buf[off], sbd_mgmt_url);
3298 off += strlen(sbd_mgmt_url) + 1;
3299 }
3300 if (sl->sl_serial_no_size) {
3301 oslp->slp_serial_off = off;
3302 bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
3303 sl->sl_serial_no_size);
3304 oslp->slp_serial_size = sl->sl_serial_no_size;
3305 oslp->slp_serial_valid = 1;
3306 off += sl->sl_serial_no_size;
3307 }
3308
3309 oslp->slp_lu_size = sl->sl_lu_size;
3310 oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
3311
3312 oslp->slp_access_state = sl->sl_access_state;
3313
3314 if (sl->sl_flags & SL_VID_VALID) {
3315 oslp->slp_lu_vid = 1;
3316 bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
3317 } else {
3318 bcopy(sbd_vendor_id, oslp->slp_vid, 8);
3319 }
3320 if (sl->sl_flags & SL_PID_VALID) {
3321 oslp->slp_lu_pid = 1;
3322 bcopy(sl->sl_product_id, oslp->slp_pid, 16);
3323 } else {
3324 bcopy(sbd_product_id, oslp->slp_pid, 16);
3325 }
3326 if (sl->sl_flags & SL_REV_VALID) {
3327 oslp->slp_lu_rev = 1;
3328 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3329 } else {
3330 bcopy(sbd_revision, oslp->slp_rev, 4);
3331 }
3332 bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3333
3334 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3335 oslp->slp_writeback_cache_disable_cur = 1;
3336 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3337 oslp->slp_writeback_cache_disable_saved = 1;
3338 if (sl->sl_flags & SL_WRITE_PROTECTED)
3339 oslp->slp_write_protected = 1;
3340
3341 sl->sl_trans_op = SL_OP_NONE;
3342
3343 rw_exit(&sbd_global_prop_lock);
3344 return (0);
3345 }
3346
3347 /*
3348 * Returns an allocated string with the "<pool>/..." form of the zvol name.
3349 */
3350 static char *
3351 sbd_get_zvol_name(sbd_lu_t *sl)
3352 {
3353 char *src;
3354 char *p;
3355
3356 if (sl->sl_data_filename)
3357 src = sl->sl_data_filename;
3358 else
3359 src = sl->sl_meta_filename;
3360 /* There has to be a better way */
3361 if (SBD_IS_ZVOL(src) != 0) {
3362 ASSERT(0);
3363 }
3364 src += 14; /* Past /dev/zvol/dsk/ */
3365 if (*src == '/')
3366 src++; /* or /dev/zvol/rdsk/ */
3367 p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3368 (void) strcpy(p, src);
3369 return (p);
3370 }
3371
3372 /*
3373 * this function creates a local metadata zvol property
3374 */
3375 sbd_status_t
3376 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3377 {
3378 /*
3379 * -allocate 1/2 the property size, the zfs property
3380 * is 8k in size and stored as ascii hex string, all
3381 * we needed is 4k buffer to store the binary data.
3382 * -initialize reader/write lock
3383 */
3384 if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3385 == NULL)
3386 return (SBD_FAILURE);
3387 rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL);
3388 return (SBD_SUCCESS);
3389 }
3390
3391 char
3392 sbd_ctoi(char c)
3393 {
3394 if ((c >= '0') && (c <= '9'))
3395 c -= '0';
3396 else if ((c >= 'A') && (c <= 'F'))
3397 c = c - 'A' + 10;
3398 else if ((c >= 'a') && (c <= 'f'))
3399 c = c - 'a' + 10;
3400 else
3401 c = -1;
3402 return (c);
3403 }
3404
3405 /*
3406 * read zvol property and convert to binary
3407 */
3408 sbd_status_t
3409 sbd_open_zfs_meta(sbd_lu_t *sl)
3410 {
3411 char *meta = NULL, cl, ch;
3412 int i;
3413 char *tmp, *ptr;
3414 uint64_t rc = SBD_SUCCESS;
3415 int len;
3416 char *file;
3417
3418 if (sl->sl_zfs_meta == NULL) {
3419 if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE)
3420 return (SBD_FAILURE);
3421 } else {
3422 bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2));
3423 }
3424
3425 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3426 file = sbd_get_zvol_name(sl);
3427 if (sbd_zvolget(file, &meta)) {
3428 rc = SBD_FAILURE;
3429 goto done;
3430 }
3431 tmp = meta;
3432 /* convert ascii hex to binary meta */
3433 len = strlen(meta);
3434 ptr = sl->sl_zfs_meta;
3435 for (i = 0; i < len; i += 2) {
3436 ch = sbd_ctoi(*tmp++);
3437 cl = sbd_ctoi(*tmp++);
3438 if (ch == -1 || cl == -1) {
3439 rc = SBD_FAILURE;
3440 break;
3441 }
3442 *ptr++ = (ch << 4) + cl;
3443 }
3444 done:
3445 rw_exit(&sl->sl_zfs_meta_lock);
3446 if (meta)
3447 kmem_free(meta, len + 1);
3448 kmem_free(file, strlen(file) + 1);
3449 return (rc);
3450 }
3451
3452 sbd_status_t
3453 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3454 {
3455 ASSERT(sl->sl_zfs_meta);
3456 rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3457 bcopy(&sl->sl_zfs_meta[off], buf, sz);
3458 rw_exit(&sl->sl_zfs_meta_lock);
3459 return (SBD_SUCCESS);
3460 }
3461
3462 sbd_status_t
3463 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3464 {
3465 ASSERT(sl->sl_zfs_meta);
3466 if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) {
3467 return (SBD_META_CORRUPTED);
3468 }
3469 if ((off + sz) > sl->sl_meta_size_used) {
3470 sl->sl_meta_size_used = off + sz;
3471 if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
3472 uint64_t meta_align =
3473 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
3474 sl->sl_total_meta_size = (sl->sl_meta_size_used +
3475 meta_align) & (~meta_align);
3476 }
3477 }
3478 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3479 bcopy(buf, &sl->sl_zfs_meta[off], sz);
3480 rw_exit(&sl->sl_zfs_meta_lock);
3481 /*
3482 * During creation of a logical unit, sbd_update_zfs_prop will be
3483 * called separately to avoid multiple calls as each meta section
3484 * create/update will result in a call to sbd_write_zfs_meta().
3485 * We only need to update the zvol once during create.
3486 */
3487 mutex_enter(&sl->sl_lock);
3488 if (sl->sl_trans_op != SL_OP_CREATE_REGISTER_LU) {
3489 mutex_exit(&sl->sl_lock);
3490 return (sbd_update_zfs_prop(sl));
3491 }
3492 mutex_exit(&sl->sl_lock);
3493 return (SBD_SUCCESS);
3494 }
3495
3496 sbd_status_t
3497 sbd_update_zfs_prop(sbd_lu_t *sl)
3498 {
3499 char *ptr, *ah_meta;
3500 char *dp = NULL;
3501 int i, num;
3502 char *file;
3503 sbd_status_t ret = SBD_SUCCESS;
3504
3505 ASSERT(sl->sl_zfs_meta);
3506 ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP);
3507 rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3508 /* convert local copy to ascii hex */
3509 dp = sl->sl_zfs_meta;
3510 for (i = 0; i < sl->sl_total_meta_size; i++, dp++) {
3511 num = ((*dp) >> 4) & 0xF;
3512 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3513 num = (*dp) & 0xF;
3514 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3515 }
3516 *ah_meta = NULL;
3517 file = sbd_get_zvol_name(sl);
3518 if (sbd_zvolset(file, (char *)ptr)) {
3519 ret = SBD_META_CORRUPTED;
3520 }
3521 rw_exit(&sl->sl_zfs_meta_lock);
3522 kmem_free(ptr, ZAP_MAXVALUELEN);
3523 kmem_free(file, strlen(file) + 1);
3524 return (ret);
3525 }
3526
3527 int
3528 sbd_is_zvol(char *path)
3529 {
3530 int is_zfs = 0;
3531
3532 if (SBD_IS_ZVOL(path) == 0)
3533 is_zfs = 1;
3534
3535 return (is_zfs);
3536 }
3537
3538 /*
3539 * set write cache disable
3540 * wcd - 1 = disable, 0 = enable
3541 */
3542 sbd_status_t
3543 sbd_wcd_set(int wcd, sbd_lu_t *sl)
3544 {
3545 /* translate to wce bit */
3546 int wce = wcd ? 0 : 1;
3547 int ret;
3548 sbd_status_t sret = SBD_SUCCESS;
3549
3550 mutex_enter(&sl->sl_lock);
3551 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3552
3553 if (sl->sl_data_vp->v_type == VREG) {
3554 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3555 goto done;
3556 }
3557
3558 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
3559 kcred, NULL, NULL);
3560 if (ret == 0) {
3561 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3562 sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
3563 } else {
3564 sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3565 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3566 sret = SBD_FAILURE;
3567 goto done;
3568 }
3569
3570 done:
3571 mutex_exit(&sl->sl_lock);
3572 return (sret);
3573 }
3574
3575 /*
3576 * get write cache disable
3577 * wcd - 1 = disable, 0 = enable
3578 */
3579 void
3580 sbd_wcd_get(int *wcd, sbd_lu_t *sl)
3581 {
3582 int wce;
3583 int ret;
3584
3585 if (sl->sl_data_vp->v_type == VREG) {
3586 *wcd = 0;
3587 return;
3588 }
3589
3590 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
3591 kcred, NULL, NULL);
3592 /* if write cache get failed, assume disabled */
3593 if (ret) {
3594 *wcd = 1;
3595 } else {
3596 /* translate to wcd bit */
3597 *wcd = wce ? 0 : 1;
3598 }
3599 }
3600
3601 int
3602 sbd_zvolget(char *zvol_name, char **comstarprop)
3603 {
3604 ldi_handle_t zfs_lh;
3605 nvlist_t *nv = NULL, *nv2;
3606 zfs_cmd_t *zc;
3607 char *ptr;
3608 int size = 1024;
3609 int unused;
3610 int rc;
3611
3612 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3613 &zfs_lh, sbd_zfs_ident)) != 0) {
3614 cmn_err(CE_WARN, "ldi_open %d", rc);
3615 return (ENXIO);
3616 }
3617
3618 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3619 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3620 again:
3621 zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3622 KM_SLEEP);
3623 zc->zc_nvlist_dst_size = size;
3624 rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3625 FKIOCTL, kcred, &unused);
3626 /*
3627 * ENOMEM means the list is larger than what we've allocated
3628 * ldi_ioctl will fail with ENOMEM only once
3629 */
3630 if (rc == ENOMEM) {
3631 int newsize;
3632 newsize = zc->zc_nvlist_dst_size;
3633 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3634 size = newsize;
3635 goto again;
3636 } else if (rc != 0) {
3637 goto out;
3638 }
3639 rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3640 zc->zc_nvlist_dst_size, &nv, 0);
3641 ASSERT(rc == 0); /* nvlist_unpack should not fail */
3642 if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) {
3643 rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr);
3644 if (rc != 0) {
3645 cmn_err(CE_WARN, "couldn't get value");
3646 } else {
3647 *comstarprop = kmem_alloc(strlen(ptr) + 1,
3648 KM_SLEEP);
3649 (void) strcpy(*comstarprop, ptr);
3650 }
3651 }
3652 out:
3653 if (nv != NULL)
3654 nvlist_free(nv);
3655 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3656 kmem_free(zc, sizeof (zfs_cmd_t));
3657 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3658
3659 return (rc);
3660 }
3661
3662 int
3663 sbd_zvolset(char *zvol_name, char *comstarprop)
3664 {
3665 ldi_handle_t zfs_lh;
3666 nvlist_t *nv;
3667 char *packed = NULL;
3668 size_t len;
3669 zfs_cmd_t *zc;
3670 int unused;
3671 int rc;
3672
3673 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3674 &zfs_lh, sbd_zfs_ident)) != 0) {
3675 cmn_err(CE_WARN, "ldi_open %d", rc);
3676 return (ENXIO);
3677 }
3678 (void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP);
3679 (void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop);
3680 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3681 goto out;
3682 }
3683
3684 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3685 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3686 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3687 zc->zc_nvlist_src_size = len;
3688 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3689 FKIOCTL, kcred, &unused);
3690 if (rc != 0) {
3691 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3692 }
3693 kmem_free(zc, sizeof (zfs_cmd_t));
3694 if (packed)
3695 kmem_free(packed, len);
3696 out:
3697 nvlist_free(nv);
3698 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3699 return (rc);
3700 }
3701
3702 /*
3703 * Unmap a region in a volume. Currently only supported for zvols.
3704 */
3705 int
3706 sbd_unmap(sbd_lu_t *sl, uint64_t offset, uint64_t length)
3707 {
3708 vnode_t *vp;
3709 int unused;
3710 dkioc_free_t df;
3711
3712 /* Right now, we only support UNMAP on zvols. */
3713 if (!(sl->sl_flags & SL_ZFS_META))
3714 return (EIO);
3715
3716 df.df_flags = (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) ?
3717 DF_WAIT_SYNC : 0;
3718 df.df_start = offset;
3719 df.df_length = length;
3720
3721 /* Use the data vnode we have to send a fop_ioctl(). */
3722 vp = sl->sl_data_vp;
3723 if (vp == NULL) {
3724 cmn_err(CE_WARN, "Cannot unmap - no vnode pointer.");
3725 return (EIO);
3726 }
3727
3728 return (VOP_IOCTL(vp, DKIOCFREE, (intptr_t)(&df), FKIOCTL, kcred,
3729 &unused, NULL));
3730 }