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