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