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
107 /* Global property settings for the logical unit */
108 char sbd_vendor_id[] = "SUN ";
109 char sbd_product_id[] = "COMSTAR ";
110 char sbd_revision[] = "1.0 ";
111 char *sbd_mgmt_url = NULL;
112 uint16_t sbd_mgmt_url_alloc_size = 0;
113 krwlock_t sbd_global_prop_lock;
114
115 static char sbd_name[] = "sbd";
116
117 static struct cb_ops sbd_cb_ops = {
118 sbd_open, /* open */
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;
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 int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup,
89 uint32_t *err_ret);
90 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
91 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
92 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
93 uint64_t off);
94 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
95 uint64_t off);
96 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
97 int sbd_is_zvol(char *path);
98 int sbd_zvolget(char *zvol_name, char **comstarprop);
99 int sbd_zvolset(char *zvol_name, char *comstarprop);
100 char sbd_ctoi(char c);
101 void sbd_close_lu(sbd_lu_t *sl);
102 static nvlist_t *sbd_zvol_get_props(char *zvol_name);
103 static int sbd_zvol_set_props(char *zvol_name, nvlist_t *nv);
104
105 static ldi_ident_t sbd_zfs_ident;
106 static stmf_lu_provider_t *sbd_lp;
107 static sbd_lu_t *sbd_lu_list = NULL;
108 static kmutex_t sbd_lock;
109 static dev_info_t *sbd_dip;
110 static uint32_t sbd_lu_count = 0;
111
112 /* Global property settings for the logical unit */
113 char sbd_vendor_id[] = "SUN ";
114 char sbd_product_id[] = "COMSTAR ";
115 char sbd_revision[] = "1.0 ";
116 char *sbd_mgmt_url = NULL;
117 uint16_t sbd_mgmt_url_alloc_size = 0;
118 krwlock_t sbd_global_prop_lock;
119
120 static char sbd_name[] = "sbd";
121
122 static struct cb_ops sbd_cb_ops = {
123 sbd_open, /* open */
436 break;
437 }
438 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
439 iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
440 iocd->stmf_obuf_size, &iocd->stmf_error);
441 break;
442 case SBD_IOCTL_GET_LU_LIST:
443 mutex_enter(&sbd_lock);
444 iocd->stmf_obuf_max_nentries = sbd_lu_count;
445 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
446 sbd_lu_count);
447 for (nsl = sbd_lu_list, i = 0; nsl &&
448 (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
449 bcopy(nsl->sl_device_id + 4,
450 &(((uint8_t *)obuf)[i << 4]), 16);
451 }
452 mutex_exit(&sbd_lock);
453 ret = 0;
454 iocd->stmf_error = 0;
455 break;
456 case SBD_IOCTL_GET_UNMAP_PROPS:
457 if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) {
458 ret = EFAULT;
459 break;
460 }
461 if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) {
462 ret = EINVAL;
463 break;
464 }
465 ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf,
466 (sbd_unmap_props_t *)obuf, &iocd->stmf_error);
467 break;
468 default:
469 ret = ENOTTY;
470 }
471
472 if (ret == 0) {
473 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
474 } else if (iocd->stmf_error) {
475 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
476 }
477 if (obuf) {
478 kmem_free(obuf, iocd->stmf_obuf_size);
479 obuf = NULL;
480 }
481 if (ibuf) {
482 kmem_free(ibuf, iocd->stmf_ibuf_size);
483 ibuf = NULL;
484 }
485 kmem_free(iocd, sizeof (stmf_iocdata_t));
486 return (ret);
487 }
1372 sli->sli_serial_offset =
1373 (uintptr_t)p - (uintptr_t)sli->sli_buf;
1374 sli->sli_flags |= SLI_SERIAL_VALID;
1375 p += sli->sli_serial_size;
1376 }
1377 sli->sli_lu_size = sl->sl_lu_size;
1378 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1379 sli->sli_data_order = SMS_DATA_ORDER;
1380 bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1381
1382 sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1383 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1384 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1385
1386 mutex_exit(&sl->sl_lock);
1387 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1388 kmem_free(sli, sizeof (*sli) + s);
1389 return (ret);
1390 }
1391
1392 /*
1393 * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
1394 */
1395 static void
1396 do_unmap_setup(sbd_lu_t *sl)
1397 {
1398 char *file = NULL;
1399 nvlist_t *nv = NULL, *nv2 = NULL;
1400 boolean_t already_compressing = B_FALSE;
1401 uint64_t val;
1402
1403 ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
1404
1405 if ((sl->sl_flags & SL_ZFS_META) == 0)
1406 return; /* No UNMAP for you. */
1407
1408 file = sbd_get_zvol_name(sl);
1409 if (file == NULL) {
1410 cmn_err(CE_WARN, "sbd has zfs meta but no zvol name");
1411 return; /* No UNMAP for you. */
1412 }
1413 nv = sbd_zvol_get_props(file);
1414 if (nv == NULL) {
1415 cmn_err(CE_WARN, "unable to get zvol props");
1416 kmem_free(file, strlen(file) + 1);
1417 return; /* No UNMAP for you. */
1418 }
1419
1420 /* See if compression is supported, but turned off on this dataset. */
1421 if (nvlist_lookup_nvlist(nv, "compression", &nv2) == 0 &&
1422 nvlist_lookup_uint64(nv2, ZPROP_VALUE, &val) == 0) {
1423 already_compressing = (val != ZIO_COMPRESS_OFF);
1424 } else {
1425 cmn_err(CE_WARN, "prop lookup for compression failed");
1426 }
1427
1428 /*
1429 * Check refreservation because no refreservation means this is a
1430 * sparse zvol and we can enable SCSI unmap.
1431 */
1432 if (nvlist_lookup_nvlist(nv, "refreservation", &nv2) != 0) {
1433 cmn_err(CE_WARN, "lookup for refreservation nvlist failed");
1434 } else if (nvlist_lookup_uint64(nv2, ZPROP_VALUE, &val) != 0) {
1435 cmn_err(CE_WARN, "prop lookup for refreservation failed");
1436 } else if (val == 0) {
1437 sl->sl_flags |= SL_UNMAP_ENABLED;
1438 if (!already_compressing) {
1439 nvlist_free(nv);
1440 nv = NULL;
1441 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0 ||
1442 nvlist_add_uint64(nv, "compression",
1443 ZIO_COMPRESS_ZLE) != 0 ||
1444 sbd_zvol_set_props(file, nv)) {
1445 cmn_err(CE_WARN, "Setting zle compression "
1446 "failed for zvol %s", file);
1447 }
1448 }
1449 }
1450
1451 nvlist_free(nv);
1452 kmem_free(file, strlen(file) + 1);
1453 }
1454
1455 int
1456 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1457 {
1458 stmf_lu_t *lu = sl->sl_lu;
1459 stmf_status_t ret;
1460
1461 do_unmap_setup(sl);
1462
1463 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1464 if (sl->sl_alias) {
1465 lu->lu_alias = sl->sl_alias;
1466 } else {
1467 lu->lu_alias = sl->sl_name;
1468 }
1469 if (sl->sl_access_state == SBD_LU_STANDBY) {
1470 /* call set access state */
1471 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1472 if (ret != STMF_SUCCESS) {
1473 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1474 return (EIO);
1475 }
1476 }
1477 /* set proxy_reg_cb_arg to meta filename */
1478 if (sl->sl_meta_filename) {
1479 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1480 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1481 } else {
1482 lu->lu_proxy_reg_arg = sl->sl_data_filename;
3197 oslp->mlu_buf_size_needed = sz;
3198
3199 if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3200 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3201 rw_exit(&sbd_global_prop_lock);
3202 return (ENOMEM);
3203 }
3204
3205 off = 0;
3206 if (sbd_mgmt_url) {
3207 oslp->mlu_mgmt_url_valid = 1;
3208 oslp->mlu_mgmt_url_off = off;
3209 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3210 off += strlen(sbd_mgmt_url) + 1;
3211 }
3212
3213 rw_exit(&sbd_global_prop_lock);
3214 return (0);
3215 }
3216
3217 static int
3218 sbd_get_unmap_props(sbd_unmap_props_t *sup,
3219 sbd_unmap_props_t *osup, uint32_t *err_ret)
3220 {
3221 sbd_status_t sret;
3222 sbd_lu_t *sl = NULL;
3223
3224 if (sup->sup_guid_valid) {
3225 sret = sbd_find_and_lock_lu(sup->sup_guid,
3226 NULL, SL_OP_LU_PROPS, &sl);
3227 } else {
3228 sret = sbd_find_and_lock_lu(NULL,
3229 (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS,
3230 &sl);
3231 }
3232 if (sret != SBD_SUCCESS) {
3233 if (sret == SBD_BUSY) {
3234 *err_ret = SBD_RET_LU_BUSY;
3235 return (EBUSY);
3236 } else if (sret == SBD_NOT_FOUND) {
3237 *err_ret = SBD_RET_NOT_FOUND;
3238 return (ENOENT);
3239 }
3240 return (EIO);
3241 }
3242
3243 sup->sup_found_lu = 1;
3244 sup->sup_guid_valid = 1;
3245 bcopy(sl->sl_device_id + 4, sup->sup_guid, 16);
3246 if (sl->sl_flags & SL_UNMAP_ENABLED)
3247 sup->sup_unmap_enabled = 1;
3248 else
3249 sup->sup_unmap_enabled = 0;
3250
3251 *osup = *sup;
3252 sl->sl_trans_op = SL_OP_NONE;
3253
3254 return (0);
3255 }
3256
3257 int
3258 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3259 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3260 {
3261 sbd_status_t sret;
3262 sbd_lu_t *sl = NULL;
3263 uint32_t sz;
3264 uint16_t off;
3265
3266 if (islp->slp_input_guid) {
3267 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3268 SL_OP_LU_PROPS, &sl);
3269 } else {
3270 ((char *)islp)[islp_sz - 1] = 0;
3271 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3272 SL_OP_LU_PROPS, &sl);
3273 }
3274 if (sret != SBD_SUCCESS) {
3275 if (sret == SBD_BUSY) {
3276 *err_ret = SBD_RET_LU_BUSY;
3727 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3728 goto out;
3729 }
3730
3731 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3732 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3733 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3734 zc->zc_nvlist_src_size = len;
3735 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3736 FKIOCTL, kcred, &unused);
3737 if (rc != 0) {
3738 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3739 }
3740 kmem_free(zc, sizeof (zfs_cmd_t));
3741 if (packed)
3742 kmem_free(packed, len);
3743 out:
3744 nvlist_free(nv);
3745 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3746 return (rc);
3747 }
3748
3749 static nvlist_t *
3750 sbd_zvol_get_props(char *zvol_name)
3751 {
3752 ldi_handle_t zfs_lh;
3753 nvlist_t *nv = NULL;
3754 zfs_cmd_t *zc;
3755 int size = 4096;
3756 int unused;
3757 int rc;
3758
3759 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3760 &zfs_lh, sbd_zfs_ident)) != 0) {
3761 cmn_err(CE_WARN, "ldi_open %d", rc);
3762 return (NULL);
3763 }
3764
3765 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3766 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3767 szg_again:
3768 zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3769 KM_SLEEP);
3770 zc->zc_nvlist_dst_size = size;
3771 rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3772 FKIOCTL, kcred, &unused);
3773 /*
3774 * ENOMEM means the list is larger than what we've allocated
3775 * ldi_ioctl will fail with ENOMEM only once
3776 */
3777 if (rc == ENOMEM) {
3778 int newsize;
3779 newsize = zc->zc_nvlist_dst_size;
3780 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3781 size = newsize;
3782 goto szg_again;
3783 } else if (rc != 0) {
3784 goto szg_out;
3785 }
3786 rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3787 zc->zc_nvlist_dst_size, &nv, 0);
3788 ASSERT(rc == 0); /* nvlist_unpack should not fail */
3789 szg_out:
3790 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3791 kmem_free(zc, sizeof (zfs_cmd_t));
3792 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3793
3794 return (nv);
3795 }
3796
3797 static int
3798 sbd_zvol_set_props(char *zvol_name, nvlist_t *nv)
3799 {
3800 ldi_handle_t zfs_lh;
3801 char *packed = NULL;
3802 size_t len;
3803 zfs_cmd_t *zc;
3804 int unused;
3805 int rc;
3806
3807 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3808 &zfs_lh, sbd_zfs_ident)) != 0) {
3809 cmn_err(CE_WARN, "ldi_open %d", rc);
3810 return (ENXIO);
3811 }
3812 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3813 goto szs_out;
3814 }
3815
3816 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3817 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3818 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3819 zc->zc_nvlist_src_size = len;
3820 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3821 FKIOCTL, kcred, &unused);
3822 if (rc != 0) {
3823 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3824 }
3825 kmem_free(zc, sizeof (zfs_cmd_t));
3826 if (packed)
3827 kmem_free(packed, len);
3828 szs_out:
3829 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3830 return (rc);
3831 }
|