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