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