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