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