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