3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/conf.h>
26 #include <sys/file.h>
27 #include <sys/ddi.h>
28 #include <sys/sunddi.h>
29 #include <sys/modctl.h>
30 #include <sys/scsi/scsi.h>
31 #include <sys/scsi/impl/scsi_reset_notify.h>
32 #include <sys/disp.h>
33 #include <sys/byteorder.h>
34 #include <sys/pathname.h>
35 #include <sys/atomic.h>
36 #include <sys/nvpair.h>
37 #include <sys/fs/zfs.h>
38 #include <sys/sdt.h>
39 #include <sys/dkio.h>
40 #include <sys/zfs_ioctl.h>
41
42 #include <sys/stmf.h>
66 uint32_t proxy_reg_arg_len);
67 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
68 uint32_t proxy_reg_arg_len);
69 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
70 uint32_t proxy_arg_len, uint32_t type);
71 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
72 uint32_t *err_ret);
73 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
74 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
75 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
76 int no_register, sbd_lu_t **slr);
77 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
78 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
79 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
80 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
81 uint32_t *err_ret);
82 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
83 uint32_t *err_ret);
84 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
85 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
86 char *sbd_get_zvol_name(sbd_lu_t *sl);
87 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
88 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
89 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
90 uint64_t off);
91 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
92 uint64_t off);
93 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
94 int sbd_is_zvol(char *path);
95 int sbd_zvolget(char *zvol_name, char **comstarprop);
96 int sbd_zvolset(char *zvol_name, char *comstarprop);
97 char sbd_ctoi(char c);
98 void sbd_close_lu(sbd_lu_t *sl);
99
100 static ldi_ident_t sbd_zfs_ident;
101 static stmf_lu_provider_t *sbd_lp;
102 static sbd_lu_t *sbd_lu_list = NULL;
103 static kmutex_t sbd_lock;
104 static dev_info_t *sbd_dip;
105 static uint32_t sbd_lu_count = 0;
106
431 break;
432 }
433 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
434 iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
435 iocd->stmf_obuf_size, &iocd->stmf_error);
436 break;
437 case SBD_IOCTL_GET_LU_LIST:
438 mutex_enter(&sbd_lock);
439 iocd->stmf_obuf_max_nentries = sbd_lu_count;
440 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
441 sbd_lu_count);
442 for (nsl = sbd_lu_list, i = 0; nsl &&
443 (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
444 bcopy(nsl->sl_device_id + 4,
445 &(((uint8_t *)obuf)[i << 4]), 16);
446 }
447 mutex_exit(&sbd_lock);
448 ret = 0;
449 iocd->stmf_error = 0;
450 break;
451 default:
452 ret = ENOTTY;
453 }
454
455 if (ret == 0) {
456 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
457 } else if (iocd->stmf_error) {
458 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
459 }
460 if (obuf) {
461 kmem_free(obuf, iocd->stmf_obuf_size);
462 obuf = NULL;
463 }
464 if (ibuf) {
465 kmem_free(ibuf, iocd->stmf_ibuf_size);
466 ibuf = NULL;
467 }
468 kmem_free(iocd, sizeof (stmf_iocdata_t));
469 return (ret);
470 }
1355 sli->sli_serial_offset =
1356 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1357 sli->sli_flags |= SLI_SERIAL_VALID;
1358 p += sli->sli_serial_size;
1359 }
1360 sli->sli_lu_size = sl->sl_lu_size;
1361 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1362 sli->sli_data_order = SMS_DATA_ORDER;
1363 bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1364
1365 sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1366 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1367 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1368
1369 mutex_exit(&sl->sl_lock);
1370 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1371 kmem_free(sli, sizeof (*sli) + s);
1372 return (ret);
1373 }
1374
1375 int
1376 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1377 {
1378 stmf_lu_t *lu = sl->sl_lu;
1379 stmf_status_t ret;
1380
1381 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1382 if (sl->sl_alias) {
1383 lu->lu_alias = sl->sl_alias;
1384 } else {
1385 lu->lu_alias = sl->sl_name;
1386 }
1387 if (sl->sl_access_state == SBD_LU_STANDBY) {
1388 /* call set access state */
1389 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1390 if (ret != STMF_SUCCESS) {
1391 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1392 return (EIO);
1393 }
1394 }
1395 /* set proxy_reg_cb_arg to meta filename */
1396 if (sl->sl_meta_filename) {
1397 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1398 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1399 } else {
1400 lu->lu_proxy_reg_arg = sl->sl_data_filename;
3115 oslp->mlu_buf_size_needed = sz;
3116
3117 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3118 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3119 rw_exit(&sbd_global_prop_lock);
3120 return (ENOMEM);
3121 }
3122
3123 off = 0;
3124 if (sbd_mgmt_url) {
3125 oslp->mlu_mgmt_url_valid = 1;
3126 oslp->mlu_mgmt_url_off = off;
3127 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3128 off += strlen(sbd_mgmt_url) + 1;
3129 }
3130
3131 rw_exit(&sbd_global_prop_lock);
3132 return (0);
3133 }
3134
3135 int
3136 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3137 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3138 {
3139 sbd_status_t sret;
3140 sbd_lu_t *sl = NULL;
3141 uint32_t sz;
3142 uint16_t off;
3143
3144 if (islp->slp_input_guid) {
3145 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3146 SL_OP_LU_PROPS, &sl);
3147 } else {
3148 ((char *)islp)[islp_sz - 1] = 0;
3149 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3150 SL_OP_LU_PROPS, &sl);
3151 }
3152 if (sret != SBD_SUCCESS) {
3153 if (sret == SBD_BUSY) {
3154 *err_ret = SBD_RET_LU_BUSY;
3255 oslp->slp_lu_rev = 1;
3256 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3257 } else {
3258 bcopy(sbd_revision, oslp->slp_rev, 4);
3259 }
3260 bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3261
3262 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3263 oslp->slp_writeback_cache_disable_cur = 1;
3264 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3265 oslp->slp_writeback_cache_disable_saved = 1;
3266 if (sl->sl_flags & SL_WRITE_PROTECTED)
3267 oslp->slp_write_protected = 1;
3268
3269 sl->sl_trans_op = SL_OP_NONE;
3270
3271 rw_exit(&sbd_global_prop_lock);
3272 return (0);
3273 }
3274
3275 char *
3276 sbd_get_zvol_name(sbd_lu_t *sl)
3277 {
3278 char *src;
3279 char *p;
3280
3281 if (sl->sl_data_filename)
3282 src = sl->sl_data_filename;
3283 else
3284 src = sl->sl_meta_filename;
3285 /* There has to be a better way */
3286 if (SBD_IS_ZVOL(src) != 0) {
3287 ASSERT(0);
3288 }
3289 src += 14;
3290 if (*src == '/')
3291 src++;
3292 p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3293 (void) strcpy(p, src);
3294 return (p);
3295 }
3296
3297 /*
3298 * this function creates a local metadata zvol property
3299 */
3300 sbd_status_t
3301 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3302 {
3303 /*
3304 * -allocate 1/2 the property size, the zfs property
3305 * is 8k in size and stored as ascii hex string, all
3306 * we needed is 4k buffer to store the binary data.
3307 * -initialize reader/write lock
3308 */
3309 if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3310 == NULL)
3311 return (SBD_FAILURE);
3605 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3606 goto out;
3607 }
3608
3609 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3610 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3611 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3612 zc->zc_nvlist_src_size = len;
3613 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3614 FKIOCTL, kcred, &unused);
3615 if (rc != 0) {
3616 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3617 }
3618 kmem_free(zc, sizeof (zfs_cmd_t));
3619 if (packed)
3620 kmem_free(packed, len);
3621 out:
3622 nvlist_free(nv);
3623 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3624 return (rc);
3625 }
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 *
24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/conf.h>
28 #include <sys/file.h>
29 #include <sys/ddi.h>
30 #include <sys/sunddi.h>
31 #include <sys/modctl.h>
32 #include <sys/scsi/scsi.h>
33 #include <sys/scsi/impl/scsi_reset_notify.h>
34 #include <sys/disp.h>
35 #include <sys/byteorder.h>
36 #include <sys/pathname.h>
37 #include <sys/atomic.h>
38 #include <sys/nvpair.h>
39 #include <sys/fs/zfs.h>
40 #include <sys/sdt.h>
41 #include <sys/dkio.h>
42 #include <sys/zfs_ioctl.h>
43
44 #include <sys/stmf.h>
68 uint32_t proxy_reg_arg_len);
69 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
70 uint32_t proxy_reg_arg_len);
71 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
72 uint32_t proxy_arg_len, uint32_t type);
73 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
74 uint32_t *err_ret);
75 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
76 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
77 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
78 int no_register, sbd_lu_t **slr);
79 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
80 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
81 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
82 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
83 uint32_t *err_ret);
84 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
85 uint32_t *err_ret);
86 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
87 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
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);
91 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
92 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
93 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
94 uint64_t off);
95 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
96 uint64_t off);
97 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
98 int sbd_is_zvol(char *path);
99 int sbd_zvolget(char *zvol_name, char **comstarprop);
100 int sbd_zvolset(char *zvol_name, char *comstarprop);
101 char sbd_ctoi(char c);
102 void sbd_close_lu(sbd_lu_t *sl);
103
104 static ldi_ident_t sbd_zfs_ident;
105 static stmf_lu_provider_t *sbd_lp;
106 static sbd_lu_t *sbd_lu_list = NULL;
107 static kmutex_t sbd_lock;
108 static dev_info_t *sbd_dip;
109 static uint32_t sbd_lu_count = 0;
110
435 break;
436 }
437 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
438 iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
439 iocd->stmf_obuf_size, &iocd->stmf_error);
440 break;
441 case SBD_IOCTL_GET_LU_LIST:
442 mutex_enter(&sbd_lock);
443 iocd->stmf_obuf_max_nentries = sbd_lu_count;
444 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
445 sbd_lu_count);
446 for (nsl = sbd_lu_list, i = 0; nsl &&
447 (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
448 bcopy(nsl->sl_device_id + 4,
449 &(((uint8_t *)obuf)[i << 4]), 16);
450 }
451 mutex_exit(&sbd_lock);
452 ret = 0;
453 iocd->stmf_error = 0;
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;
467 default:
468 ret = ENOTTY;
469 }
470
471 if (ret == 0) {
472 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
473 } else if (iocd->stmf_error) {
474 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
475 }
476 if (obuf) {
477 kmem_free(obuf, iocd->stmf_obuf_size);
478 obuf = NULL;
479 }
480 if (ibuf) {
481 kmem_free(ibuf, iocd->stmf_ibuf_size);
482 ibuf = NULL;
483 }
484 kmem_free(iocd, sizeof (stmf_iocdata_t));
485 return (ret);
486 }
1371 sli->sli_serial_offset =
1372 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1373 sli->sli_flags |= SLI_SERIAL_VALID;
1374 p += sli->sli_serial_size;
1375 }
1376 sli->sli_lu_size = sl->sl_lu_size;
1377 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1378 sli->sli_data_order = SMS_DATA_ORDER;
1379 bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1380
1381 sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1382 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1383 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1384
1385 mutex_exit(&sl->sl_lock);
1386 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1387 kmem_free(sli, sizeof (*sli) + s);
1388 return (ret);
1389 }
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
1405 int
1406 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1407 {
1408 stmf_lu_t *lu = sl->sl_lu;
1409 stmf_status_t ret;
1410
1411 do_unmap_setup(sl);
1412
1413 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1414 if (sl->sl_alias) {
1415 lu->lu_alias = sl->sl_alias;
1416 } else {
1417 lu->lu_alias = sl->sl_name;
1418 }
1419 if (sl->sl_access_state == SBD_LU_STANDBY) {
1420 /* call set access state */
1421 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1422 if (ret != STMF_SUCCESS) {
1423 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1424 return (EIO);
1425 }
1426 }
1427 /* set proxy_reg_cb_arg to meta filename */
1428 if (sl->sl_meta_filename) {
1429 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1430 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1431 } else {
1432 lu->lu_proxy_reg_arg = sl->sl_data_filename;
3147 oslp->mlu_buf_size_needed = sz;
3148
3149 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3150 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3151 rw_exit(&sbd_global_prop_lock);
3152 return (ENOMEM);
3153 }
3154
3155 off = 0;
3156 if (sbd_mgmt_url) {
3157 oslp->mlu_mgmt_url_valid = 1;
3158 oslp->mlu_mgmt_url_off = off;
3159 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3160 off += strlen(sbd_mgmt_url) + 1;
3161 }
3162
3163 rw_exit(&sbd_global_prop_lock);
3164 return (0);
3165 }
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
3207 int
3208 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3209 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3210 {
3211 sbd_status_t sret;
3212 sbd_lu_t *sl = NULL;
3213 uint32_t sz;
3214 uint16_t off;
3215
3216 if (islp->slp_input_guid) {
3217 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3218 SL_OP_LU_PROPS, &sl);
3219 } else {
3220 ((char *)islp)[islp_sz - 1] = 0;
3221 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3222 SL_OP_LU_PROPS, &sl);
3223 }
3224 if (sret != SBD_SUCCESS) {
3225 if (sret == SBD_BUSY) {
3226 *err_ret = SBD_RET_LU_BUSY;
3327 oslp->slp_lu_rev = 1;
3328 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3329 } else {
3330 bcopy(sbd_revision, oslp->slp_rev, 4);
3331 }
3332 bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3333
3334 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3335 oslp->slp_writeback_cache_disable_cur = 1;
3336 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3337 oslp->slp_writeback_cache_disable_saved = 1;
3338 if (sl->sl_flags & SL_WRITE_PROTECTED)
3339 oslp->slp_write_protected = 1;
3340
3341 sl->sl_trans_op = SL_OP_NONE;
3342
3343 rw_exit(&sbd_global_prop_lock);
3344 return (0);
3345 }
3346
3347 /*
3348 * Returns an allocated string with the "<pool>/..." form of the zvol name.
3349 */
3350 static char *
3351 sbd_get_zvol_name(sbd_lu_t *sl)
3352 {
3353 char *src;
3354 char *p;
3355
3356 if (sl->sl_data_filename)
3357 src = sl->sl_data_filename;
3358 else
3359 src = sl->sl_meta_filename;
3360 /* There has to be a better way */
3361 if (SBD_IS_ZVOL(src) != 0) {
3362 ASSERT(0);
3363 }
3364 src += 14; /* Past /dev/zvol/dsk/ */
3365 if (*src == '/')
3366 src++; /* or /dev/zvol/rdsk/ */
3367 p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3368 (void) strcpy(p, src);
3369 return (p);
3370 }
3371
3372 /*
3373 * this function creates a local metadata zvol property
3374 */
3375 sbd_status_t
3376 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3377 {
3378 /*
3379 * -allocate 1/2 the property size, the zfs property
3380 * is 8k in size and stored as ascii hex string, all
3381 * we needed is 4k buffer to store the binary data.
3382 * -initialize reader/write lock
3383 */
3384 if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3385 == NULL)
3386 return (SBD_FAILURE);
3680 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3681 goto out;
3682 }
3683
3684 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3685 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3686 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3687 zc->zc_nvlist_src_size = len;
3688 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3689 FKIOCTL, kcred, &unused);
3690 if (rc != 0) {
3691 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3692 }
3693 kmem_free(zc, sizeof (zfs_cmd_t));
3694 if (packed)
3695 kmem_free(packed, len);
3696 out:
3697 nvlist_free(nv);
3698 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
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));
3730 }
|