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