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