1*b8aa3defSJoshua M. Clulow /*
2*b8aa3defSJoshua M. Clulow * This file and its contents are supplied under the terms of the
3*b8aa3defSJoshua M. Clulow * Common Development and Distribution License ("CDDL"), version 1.0.
4*b8aa3defSJoshua M. Clulow * You may only use this file in accordance with the terms of version
5*b8aa3defSJoshua M. Clulow * 1.0 of the CDDL.
6*b8aa3defSJoshua M. Clulow *
7*b8aa3defSJoshua M. Clulow * A full copy of the text of the CDDL should have accompanied this
8*b8aa3defSJoshua M. Clulow * source. A copy of the CDDL is also available via the Internet at
9*b8aa3defSJoshua M. Clulow * http://www.illumos.org/license/CDDL.
10*b8aa3defSJoshua M. Clulow */
11*b8aa3defSJoshua M. Clulow
12*b8aa3defSJoshua M. Clulow /*
13*b8aa3defSJoshua M. Clulow * Copyright (c) 2017, Joyent, Inc.
14*b8aa3defSJoshua M. Clulow */
15*b8aa3defSJoshua M. Clulow
16*b8aa3defSJoshua M. Clulow #include <sys/scsi/adapters/smrt/smrt.h>
17*b8aa3defSJoshua M. Clulow
18*b8aa3defSJoshua M. Clulow static void
smrt_logvol_free(smrt_volume_t * smlv)19*b8aa3defSJoshua M. Clulow smrt_logvol_free(smrt_volume_t *smlv)
20*b8aa3defSJoshua M. Clulow {
21*b8aa3defSJoshua M. Clulow /*
22*b8aa3defSJoshua M. Clulow * By this stage of teardown, all of the SCSI target drivers
23*b8aa3defSJoshua M. Clulow * must have been detached from this logical volume.
24*b8aa3defSJoshua M. Clulow */
25*b8aa3defSJoshua M. Clulow VERIFY(list_is_empty(&smlv->smlv_targets));
26*b8aa3defSJoshua M. Clulow list_destroy(&smlv->smlv_targets);
27*b8aa3defSJoshua M. Clulow
28*b8aa3defSJoshua M. Clulow kmem_free(smlv, sizeof (*smlv));
29*b8aa3defSJoshua M. Clulow }
30*b8aa3defSJoshua M. Clulow
31*b8aa3defSJoshua M. Clulow smrt_volume_t *
smrt_logvol_lookup_by_id(smrt_t * smrt,unsigned long id)32*b8aa3defSJoshua M. Clulow smrt_logvol_lookup_by_id(smrt_t *smrt, unsigned long id)
33*b8aa3defSJoshua M. Clulow {
34*b8aa3defSJoshua M. Clulow VERIFY(MUTEX_HELD(&smrt->smrt_mutex));
35*b8aa3defSJoshua M. Clulow
36*b8aa3defSJoshua M. Clulow for (smrt_volume_t *smlv = list_head(&smrt->smrt_volumes);
37*b8aa3defSJoshua M. Clulow smlv != NULL; smlv = list_next(&smrt->smrt_volumes, smlv)) {
38*b8aa3defSJoshua M. Clulow if (smlv->smlv_addr.LogDev.VolId == id) {
39*b8aa3defSJoshua M. Clulow return (smlv);
40*b8aa3defSJoshua M. Clulow }
41*b8aa3defSJoshua M. Clulow }
42*b8aa3defSJoshua M. Clulow
43*b8aa3defSJoshua M. Clulow return (NULL);
44*b8aa3defSJoshua M. Clulow }
45*b8aa3defSJoshua M. Clulow
46*b8aa3defSJoshua M. Clulow static int
smrt_read_logvols(smrt_t * smrt,smrt_report_logical_lun_t * smrll,uint64_t gen)47*b8aa3defSJoshua M. Clulow smrt_read_logvols(smrt_t *smrt, smrt_report_logical_lun_t *smrll, uint64_t gen)
48*b8aa3defSJoshua M. Clulow {
49*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_ent_t *ents = smrll->smrll_data.ents;
50*b8aa3defSJoshua M. Clulow uint32_t count = BE_32(smrll->smrll_datasize) /
51*b8aa3defSJoshua M. Clulow sizeof (smrt_report_logical_lun_ent_t);
52*b8aa3defSJoshua M. Clulow
53*b8aa3defSJoshua M. Clulow VERIFY(MUTEX_HELD(&smrt->smrt_mutex));
54*b8aa3defSJoshua M. Clulow
55*b8aa3defSJoshua M. Clulow if (count > SMRT_MAX_LOGDRV) {
56*b8aa3defSJoshua M. Clulow count = SMRT_MAX_LOGDRV;
57*b8aa3defSJoshua M. Clulow }
58*b8aa3defSJoshua M. Clulow
59*b8aa3defSJoshua M. Clulow for (unsigned i = 0; i < count; i++) {
60*b8aa3defSJoshua M. Clulow smrt_volume_t *smlv;
61*b8aa3defSJoshua M. Clulow char id[SCSI_MAXNAMELEN];
62*b8aa3defSJoshua M. Clulow
63*b8aa3defSJoshua M. Clulow DTRACE_PROBE2(read_logvol, unsigned, i,
64*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_ent_t *, &ents[i]);
65*b8aa3defSJoshua M. Clulow
66*b8aa3defSJoshua M. Clulow if ((smlv = smrt_logvol_lookup_by_id(smrt,
67*b8aa3defSJoshua M. Clulow ents[i].smrle_addr.VolId)) == NULL) {
68*b8aa3defSJoshua M. Clulow
69*b8aa3defSJoshua M. Clulow /*
70*b8aa3defSJoshua M. Clulow * This is a new Logical Volume, so add it the the list.
71*b8aa3defSJoshua M. Clulow */
72*b8aa3defSJoshua M. Clulow if ((smlv = kmem_zalloc(sizeof (*smlv), KM_NOSLEEP)) ==
73*b8aa3defSJoshua M. Clulow NULL) {
74*b8aa3defSJoshua M. Clulow return (ENOMEM);
75*b8aa3defSJoshua M. Clulow }
76*b8aa3defSJoshua M. Clulow
77*b8aa3defSJoshua M. Clulow list_create(&smlv->smlv_targets,
78*b8aa3defSJoshua M. Clulow sizeof (smrt_target_t),
79*b8aa3defSJoshua M. Clulow offsetof(smrt_target_t, smtg_link_lun));
80*b8aa3defSJoshua M. Clulow
81*b8aa3defSJoshua M. Clulow smlv->smlv_ctlr = smrt;
82*b8aa3defSJoshua M. Clulow list_insert_tail(&smrt->smrt_volumes, smlv);
83*b8aa3defSJoshua M. Clulow }
84*b8aa3defSJoshua M. Clulow
85*b8aa3defSJoshua M. Clulow /*
86*b8aa3defSJoshua M. Clulow * Always make sure that the address and the generation are up
87*b8aa3defSJoshua M. Clulow * to date, regardless of where this came from.
88*b8aa3defSJoshua M. Clulow */
89*b8aa3defSJoshua M. Clulow smlv->smlv_addr.LogDev = ents[i].smrle_addr;
90*b8aa3defSJoshua M. Clulow smlv->smlv_gen = gen;
91*b8aa3defSJoshua M. Clulow (void) snprintf(id, sizeof (id), "%x",
92*b8aa3defSJoshua M. Clulow smlv->smlv_addr.LogDev.VolId);
93*b8aa3defSJoshua M. Clulow if (!ddi_in_panic() &&
94*b8aa3defSJoshua M. Clulow scsi_hba_tgtmap_set_add(smrt->smrt_virt_tgtmap,
95*b8aa3defSJoshua M. Clulow SCSI_TGT_SCSI_DEVICE, id, NULL) != DDI_SUCCESS) {
96*b8aa3defSJoshua M. Clulow return (EIO);
97*b8aa3defSJoshua M. Clulow }
98*b8aa3defSJoshua M. Clulow }
99*b8aa3defSJoshua M. Clulow
100*b8aa3defSJoshua M. Clulow return (0);
101*b8aa3defSJoshua M. Clulow }
102*b8aa3defSJoshua M. Clulow
103*b8aa3defSJoshua M. Clulow static int
smrt_read_logvols_ext(smrt_t * smrt,smrt_report_logical_lun_t * smrll,uint64_t gen)104*b8aa3defSJoshua M. Clulow smrt_read_logvols_ext(smrt_t *smrt, smrt_report_logical_lun_t *smrll,
105*b8aa3defSJoshua M. Clulow uint64_t gen)
106*b8aa3defSJoshua M. Clulow {
107*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_extent_t *extents =
108*b8aa3defSJoshua M. Clulow smrll->smrll_data.extents;
109*b8aa3defSJoshua M. Clulow uint32_t count = BE_32(smrll->smrll_datasize) /
110*b8aa3defSJoshua M. Clulow sizeof (smrt_report_logical_lun_extent_t);
111*b8aa3defSJoshua M. Clulow
112*b8aa3defSJoshua M. Clulow VERIFY(MUTEX_HELD(&smrt->smrt_mutex));
113*b8aa3defSJoshua M. Clulow
114*b8aa3defSJoshua M. Clulow if (count > SMRT_MAX_LOGDRV) {
115*b8aa3defSJoshua M. Clulow count = SMRT_MAX_LOGDRV;
116*b8aa3defSJoshua M. Clulow }
117*b8aa3defSJoshua M. Clulow
118*b8aa3defSJoshua M. Clulow for (unsigned i = 0; i < count; i++) {
119*b8aa3defSJoshua M. Clulow smrt_volume_t *smlv;
120*b8aa3defSJoshua M. Clulow char id[SCSI_MAXNAMELEN];
121*b8aa3defSJoshua M. Clulow
122*b8aa3defSJoshua M. Clulow DTRACE_PROBE2(read_logvol_ext, unsigned, i,
123*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_extent_t *, &extents[i]);
124*b8aa3defSJoshua M. Clulow
125*b8aa3defSJoshua M. Clulow if ((smlv = smrt_logvol_lookup_by_id(smrt,
126*b8aa3defSJoshua M. Clulow extents[i].smrle_addr.VolId)) != NULL) {
127*b8aa3defSJoshua M. Clulow if ((smlv->smlv_flags & SMRT_VOL_FLAG_WWN) &&
128*b8aa3defSJoshua M. Clulow bcmp(extents[i].smrle_wwn, smlv->smlv_wwn,
129*b8aa3defSJoshua M. Clulow 16) != 0) {
130*b8aa3defSJoshua M. Clulow dev_err(smrt->smrt_dip, CE_PANIC, "logical "
131*b8aa3defSJoshua M. Clulow "volume %u WWN changed unexpectedly", i);
132*b8aa3defSJoshua M. Clulow }
133*b8aa3defSJoshua M. Clulow } else {
134*b8aa3defSJoshua M. Clulow /*
135*b8aa3defSJoshua M. Clulow * This is a new Logical Volume, so add it the the list.
136*b8aa3defSJoshua M. Clulow */
137*b8aa3defSJoshua M. Clulow if ((smlv = kmem_zalloc(sizeof (*smlv), KM_NOSLEEP)) ==
138*b8aa3defSJoshua M. Clulow NULL) {
139*b8aa3defSJoshua M. Clulow return (ENOMEM);
140*b8aa3defSJoshua M. Clulow }
141*b8aa3defSJoshua M. Clulow
142*b8aa3defSJoshua M. Clulow bcopy(extents[i].smrle_wwn, smlv->smlv_wwn, 16);
143*b8aa3defSJoshua M. Clulow smlv->smlv_flags |= SMRT_VOL_FLAG_WWN;
144*b8aa3defSJoshua M. Clulow
145*b8aa3defSJoshua M. Clulow list_create(&smlv->smlv_targets,
146*b8aa3defSJoshua M. Clulow sizeof (smrt_target_t),
147*b8aa3defSJoshua M. Clulow offsetof(smrt_target_t, smtg_link_lun));
148*b8aa3defSJoshua M. Clulow
149*b8aa3defSJoshua M. Clulow smlv->smlv_ctlr = smrt;
150*b8aa3defSJoshua M. Clulow list_insert_tail(&smrt->smrt_volumes, smlv);
151*b8aa3defSJoshua M. Clulow }
152*b8aa3defSJoshua M. Clulow
153*b8aa3defSJoshua M. Clulow /*
154*b8aa3defSJoshua M. Clulow * Always make sure that the address and the generation are up
155*b8aa3defSJoshua M. Clulow * to date. The address may have changed on a reset.
156*b8aa3defSJoshua M. Clulow */
157*b8aa3defSJoshua M. Clulow smlv->smlv_addr.LogDev = extents[i].smrle_addr;
158*b8aa3defSJoshua M. Clulow smlv->smlv_gen = gen;
159*b8aa3defSJoshua M. Clulow (void) snprintf(id, sizeof (id), "%x",
160*b8aa3defSJoshua M. Clulow smlv->smlv_addr.LogDev.VolId);
161*b8aa3defSJoshua M. Clulow if (!ddi_in_panic() &&
162*b8aa3defSJoshua M. Clulow scsi_hba_tgtmap_set_add(smrt->smrt_virt_tgtmap,
163*b8aa3defSJoshua M. Clulow SCSI_TGT_SCSI_DEVICE, id, NULL) != DDI_SUCCESS) {
164*b8aa3defSJoshua M. Clulow return (EIO);
165*b8aa3defSJoshua M. Clulow }
166*b8aa3defSJoshua M. Clulow }
167*b8aa3defSJoshua M. Clulow
168*b8aa3defSJoshua M. Clulow return (0);
169*b8aa3defSJoshua M. Clulow }
170*b8aa3defSJoshua M. Clulow
171*b8aa3defSJoshua M. Clulow /*
172*b8aa3defSJoshua M. Clulow * Discover the currently visible set of Logical Volumes exposed by the
173*b8aa3defSJoshua M. Clulow * controller.
174*b8aa3defSJoshua M. Clulow */
175*b8aa3defSJoshua M. Clulow int
smrt_logvol_discover(smrt_t * smrt,uint16_t timeout,uint64_t gen)176*b8aa3defSJoshua M. Clulow smrt_logvol_discover(smrt_t *smrt, uint16_t timeout, uint64_t gen)
177*b8aa3defSJoshua M. Clulow {
178*b8aa3defSJoshua M. Clulow smrt_command_t *smcm;
179*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_t *smrll;
180*b8aa3defSJoshua M. Clulow smrt_report_logical_lun_req_t smrllr = { 0 };
181*b8aa3defSJoshua M. Clulow int r;
182*b8aa3defSJoshua M. Clulow
183*b8aa3defSJoshua M. Clulow /*
184*b8aa3defSJoshua M. Clulow * Allocate the command to send to the device, including buffer space
185*b8aa3defSJoshua M. Clulow * for the returned list of Logical Volumes.
186*b8aa3defSJoshua M. Clulow */
187*b8aa3defSJoshua M. Clulow if ((smcm = smrt_command_alloc(smrt, SMRT_CMDTYPE_INTERNAL,
188*b8aa3defSJoshua M. Clulow KM_NOSLEEP)) == NULL || smrt_command_attach_internal(smrt, smcm,
189*b8aa3defSJoshua M. Clulow sizeof (smrt_report_logical_lun_t), KM_NOSLEEP) != 0) {
190*b8aa3defSJoshua M. Clulow r = ENOMEM;
191*b8aa3defSJoshua M. Clulow mutex_enter(&smrt->smrt_mutex);
192*b8aa3defSJoshua M. Clulow goto out;
193*b8aa3defSJoshua M. Clulow }
194*b8aa3defSJoshua M. Clulow
195*b8aa3defSJoshua M. Clulow smrll = smcm->smcm_internal->smcmi_va;
196*b8aa3defSJoshua M. Clulow
197*b8aa3defSJoshua M. Clulow smrt_write_controller_lun_addr(&smcm->smcm_va_cmd->Header.LUN);
198*b8aa3defSJoshua M. Clulow
199*b8aa3defSJoshua M. Clulow smcm->smcm_va_cmd->Request.CDBLen = sizeof (smrllr);
200*b8aa3defSJoshua M. Clulow smcm->smcm_va_cmd->Request.Timeout = LE_16(timeout);
201*b8aa3defSJoshua M. Clulow smcm->smcm_va_cmd->Request.Type.Type = CISS_TYPE_CMD;
202*b8aa3defSJoshua M. Clulow smcm->smcm_va_cmd->Request.Type.Attribute = CISS_ATTR_SIMPLE;
203*b8aa3defSJoshua M. Clulow smcm->smcm_va_cmd->Request.Type.Direction = CISS_XFER_READ;
204*b8aa3defSJoshua M. Clulow
205*b8aa3defSJoshua M. Clulow /*
206*b8aa3defSJoshua M. Clulow * The Report Logical LUNs command is essentially a vendor-specific
207*b8aa3defSJoshua M. Clulow * SCSI command, which we assemble into the CDB region of the command
208*b8aa3defSJoshua M. Clulow * block.
209*b8aa3defSJoshua M. Clulow */
210*b8aa3defSJoshua M. Clulow bzero(&smrllr, sizeof (smrllr));
211*b8aa3defSJoshua M. Clulow smrllr.smrllr_opcode = CISS_SCMD_REPORT_LOGICAL_LUNS;
212*b8aa3defSJoshua M. Clulow smrllr.smrllr_extflag = 1;
213*b8aa3defSJoshua M. Clulow smrllr.smrllr_datasize = htonl(sizeof (smrt_report_logical_lun_t));
214*b8aa3defSJoshua M. Clulow bcopy(&smrllr, &smcm->smcm_va_cmd->Request.CDB[0],
215*b8aa3defSJoshua M. Clulow MIN(CISS_CDBLEN, sizeof (smrllr)));
216*b8aa3defSJoshua M. Clulow
217*b8aa3defSJoshua M. Clulow mutex_enter(&smrt->smrt_mutex);
218*b8aa3defSJoshua M. Clulow
219*b8aa3defSJoshua M. Clulow /*
220*b8aa3defSJoshua M. Clulow * Send the command to the device.
221*b8aa3defSJoshua M. Clulow */
222*b8aa3defSJoshua M. Clulow smcm->smcm_status |= SMRT_CMD_STATUS_POLLED;
223*b8aa3defSJoshua M. Clulow if ((r = smrt_submit(smrt, smcm)) != 0) {
224*b8aa3defSJoshua M. Clulow goto out;
225*b8aa3defSJoshua M. Clulow }
226*b8aa3defSJoshua M. Clulow
227*b8aa3defSJoshua M. Clulow /*
228*b8aa3defSJoshua M. Clulow * Poll for completion.
229*b8aa3defSJoshua M. Clulow */
230*b8aa3defSJoshua M. Clulow smcm->smcm_expiry = gethrtime() + timeout * NANOSEC;
231*b8aa3defSJoshua M. Clulow if ((r = smrt_poll_for(smrt, smcm)) != 0) {
232*b8aa3defSJoshua M. Clulow VERIFY3S(r, ==, ETIMEDOUT);
233*b8aa3defSJoshua M. Clulow VERIFY0(smcm->smcm_status & SMRT_CMD_STATUS_POLL_COMPLETE);
234*b8aa3defSJoshua M. Clulow
235*b8aa3defSJoshua M. Clulow /*
236*b8aa3defSJoshua M. Clulow * The command timed out; abandon it now. Remove the POLLED
237*b8aa3defSJoshua M. Clulow * flag so that the periodic routine will send an abort to
238*b8aa3defSJoshua M. Clulow * clean it up next time around.
239*b8aa3defSJoshua M. Clulow */
240*b8aa3defSJoshua M. Clulow smcm->smcm_status |= SMRT_CMD_STATUS_ABANDONED;
241*b8aa3defSJoshua M. Clulow smcm->smcm_status &= ~SMRT_CMD_STATUS_POLLED;
242*b8aa3defSJoshua M. Clulow smcm = NULL;
243*b8aa3defSJoshua M. Clulow goto out;
244*b8aa3defSJoshua M. Clulow }
245*b8aa3defSJoshua M. Clulow
246*b8aa3defSJoshua M. Clulow if (smcm->smcm_status & SMRT_CMD_STATUS_RESET_SENT) {
247*b8aa3defSJoshua M. Clulow /*
248*b8aa3defSJoshua M. Clulow * The controller was reset while we were trying to discover
249*b8aa3defSJoshua M. Clulow * logical volumes. Report failure.
250*b8aa3defSJoshua M. Clulow */
251*b8aa3defSJoshua M. Clulow r = EIO;
252*b8aa3defSJoshua M. Clulow goto out;
253*b8aa3defSJoshua M. Clulow }
254*b8aa3defSJoshua M. Clulow
255*b8aa3defSJoshua M. Clulow if (smcm->smcm_status & SMRT_CMD_STATUS_ERROR) {
256*b8aa3defSJoshua M. Clulow ErrorInfo_t *ei = smcm->smcm_va_err;
257*b8aa3defSJoshua M. Clulow
258*b8aa3defSJoshua M. Clulow if (ei->CommandStatus != CISS_CMD_DATA_UNDERRUN) {
259*b8aa3defSJoshua M. Clulow dev_err(smrt->smrt_dip, CE_WARN, "logical volume "
260*b8aa3defSJoshua M. Clulow "discovery error: status 0x%x", ei->CommandStatus);
261*b8aa3defSJoshua M. Clulow r = EIO;
262*b8aa3defSJoshua M. Clulow goto out;
263*b8aa3defSJoshua M. Clulow }
264*b8aa3defSJoshua M. Clulow }
265*b8aa3defSJoshua M. Clulow
266*b8aa3defSJoshua M. Clulow if (!ddi_in_panic() &&
267*b8aa3defSJoshua M. Clulow scsi_hba_tgtmap_set_begin(smrt->smrt_virt_tgtmap) != DDI_SUCCESS) {
268*b8aa3defSJoshua M. Clulow dev_err(smrt->smrt_dip, CE_WARN, "failed to begin target map "
269*b8aa3defSJoshua M. Clulow "observation on %s", SMRT_IPORT_VIRT);
270*b8aa3defSJoshua M. Clulow r = EIO;
271*b8aa3defSJoshua M. Clulow goto out;
272*b8aa3defSJoshua M. Clulow }
273*b8aa3defSJoshua M. Clulow
274*b8aa3defSJoshua M. Clulow if ((smrll->smrll_extflag & 0x1) != 0) {
275*b8aa3defSJoshua M. Clulow r = smrt_read_logvols_ext(smrt, smrll, gen);
276*b8aa3defSJoshua M. Clulow } else {
277*b8aa3defSJoshua M. Clulow r = smrt_read_logvols(smrt, smrll, gen);
278*b8aa3defSJoshua M. Clulow }
279*b8aa3defSJoshua M. Clulow
280*b8aa3defSJoshua M. Clulow if (r == 0 && !ddi_in_panic()) {
281*b8aa3defSJoshua M. Clulow if (scsi_hba_tgtmap_set_end(smrt->smrt_virt_tgtmap, 0) !=
282*b8aa3defSJoshua M. Clulow DDI_SUCCESS) {
283*b8aa3defSJoshua M. Clulow dev_err(smrt->smrt_dip, CE_WARN, "failed to end target "
284*b8aa3defSJoshua M. Clulow "map observation on %s", SMRT_IPORT_VIRT);
285*b8aa3defSJoshua M. Clulow r = EIO;
286*b8aa3defSJoshua M. Clulow }
287*b8aa3defSJoshua M. Clulow } else if (r != 0 && !ddi_in_panic()) {
288*b8aa3defSJoshua M. Clulow if (scsi_hba_tgtmap_set_flush(smrt->smrt_virt_tgtmap) !=
289*b8aa3defSJoshua M. Clulow DDI_SUCCESS) {
290*b8aa3defSJoshua M. Clulow dev_err(smrt->smrt_dip, CE_WARN, "failed to end target "
291*b8aa3defSJoshua M. Clulow "map observation on %s", SMRT_IPORT_VIRT);
292*b8aa3defSJoshua M. Clulow r = EIO;
293*b8aa3defSJoshua M. Clulow }
294*b8aa3defSJoshua M. Clulow }
295*b8aa3defSJoshua M. Clulow
296*b8aa3defSJoshua M. Clulow if (r == 0) {
297*b8aa3defSJoshua M. Clulow /*
298*b8aa3defSJoshua M. Clulow * Update the time of the last successful Logical Volume
299*b8aa3defSJoshua M. Clulow * discovery:
300*b8aa3defSJoshua M. Clulow */
301*b8aa3defSJoshua M. Clulow smrt->smrt_last_log_discovery = gethrtime();
302*b8aa3defSJoshua M. Clulow }
303*b8aa3defSJoshua M. Clulow
304*b8aa3defSJoshua M. Clulow out:
305*b8aa3defSJoshua M. Clulow mutex_exit(&smrt->smrt_mutex);
306*b8aa3defSJoshua M. Clulow
307*b8aa3defSJoshua M. Clulow if (smcm != NULL) {
308*b8aa3defSJoshua M. Clulow smrt_command_free(smcm);
309*b8aa3defSJoshua M. Clulow }
310*b8aa3defSJoshua M. Clulow return (r);
311*b8aa3defSJoshua M. Clulow }
312*b8aa3defSJoshua M. Clulow
313*b8aa3defSJoshua M. Clulow void
smrt_logvol_tgtmap_activate(void * arg,char * addr,scsi_tgtmap_tgt_type_t type,void ** privpp)314*b8aa3defSJoshua M. Clulow smrt_logvol_tgtmap_activate(void *arg, char *addr, scsi_tgtmap_tgt_type_t type,
315*b8aa3defSJoshua M. Clulow void **privpp)
316*b8aa3defSJoshua M. Clulow {
317*b8aa3defSJoshua M. Clulow smrt_t *smrt = arg;
318*b8aa3defSJoshua M. Clulow unsigned long volume;
319*b8aa3defSJoshua M. Clulow char *eptr;
320*b8aa3defSJoshua M. Clulow
321*b8aa3defSJoshua M. Clulow VERIFY(type == SCSI_TGT_SCSI_DEVICE);
322*b8aa3defSJoshua M. Clulow VERIFY0(ddi_strtoul(addr, &eptr, 16, &volume));
323*b8aa3defSJoshua M. Clulow VERIFY3S(*eptr, ==, '\0');
324*b8aa3defSJoshua M. Clulow VERIFY3S(volume, >=, 0);
325*b8aa3defSJoshua M. Clulow VERIFY3S(volume, <, SMRT_MAX_LOGDRV);
326*b8aa3defSJoshua M. Clulow mutex_enter(&smrt->smrt_mutex);
327*b8aa3defSJoshua M. Clulow VERIFY(smrt_logvol_lookup_by_id(smrt, volume) != NULL);
328*b8aa3defSJoshua M. Clulow mutex_exit(&smrt->smrt_mutex);
329*b8aa3defSJoshua M. Clulow *privpp = NULL;
330*b8aa3defSJoshua M. Clulow }
331*b8aa3defSJoshua M. Clulow
332*b8aa3defSJoshua M. Clulow boolean_t
smrt_logvol_tgtmap_deactivate(void * arg,char * addr,scsi_tgtmap_tgt_type_t type,void * priv,scsi_tgtmap_deact_rsn_t reason)333*b8aa3defSJoshua M. Clulow smrt_logvol_tgtmap_deactivate(void *arg, char *addr,
334*b8aa3defSJoshua M. Clulow scsi_tgtmap_tgt_type_t type, void *priv, scsi_tgtmap_deact_rsn_t reason)
335*b8aa3defSJoshua M. Clulow {
336*b8aa3defSJoshua M. Clulow smrt_t *smrt = arg;
337*b8aa3defSJoshua M. Clulow smrt_volume_t *smlv;
338*b8aa3defSJoshua M. Clulow unsigned long volume;
339*b8aa3defSJoshua M. Clulow char *eptr;
340*b8aa3defSJoshua M. Clulow
341*b8aa3defSJoshua M. Clulow VERIFY(type == SCSI_TGT_SCSI_DEVICE);
342*b8aa3defSJoshua M. Clulow VERIFY(priv == NULL);
343*b8aa3defSJoshua M. Clulow VERIFY0(ddi_strtoul(addr, &eptr, 16, &volume));
344*b8aa3defSJoshua M. Clulow VERIFY3S(*eptr, ==, '\0');
345*b8aa3defSJoshua M. Clulow VERIFY3S(volume, >=, 0);
346*b8aa3defSJoshua M. Clulow VERIFY3S(volume, <, SMRT_MAX_LOGDRV);
347*b8aa3defSJoshua M. Clulow
348*b8aa3defSJoshua M. Clulow mutex_enter(&smrt->smrt_mutex);
349*b8aa3defSJoshua M. Clulow smlv = smrt_logvol_lookup_by_id(smrt, volume);
350*b8aa3defSJoshua M. Clulow VERIFY(smlv != NULL);
351*b8aa3defSJoshua M. Clulow
352*b8aa3defSJoshua M. Clulow list_remove(&smrt->smrt_volumes, smlv);
353*b8aa3defSJoshua M. Clulow smrt_logvol_free(smlv);
354*b8aa3defSJoshua M. Clulow mutex_exit(&smrt->smrt_mutex);
355*b8aa3defSJoshua M. Clulow
356*b8aa3defSJoshua M. Clulow return (B_FALSE);
357*b8aa3defSJoshua M. Clulow }
358*b8aa3defSJoshua M. Clulow
359*b8aa3defSJoshua M. Clulow void
smrt_logvol_teardown(smrt_t * smrt)360*b8aa3defSJoshua M. Clulow smrt_logvol_teardown(smrt_t *smrt)
361*b8aa3defSJoshua M. Clulow {
362*b8aa3defSJoshua M. Clulow smrt_volume_t *smlv;
363*b8aa3defSJoshua M. Clulow
364*b8aa3defSJoshua M. Clulow while ((smlv = list_remove_head(&smrt->smrt_volumes)) != NULL) {
365*b8aa3defSJoshua M. Clulow smrt_logvol_free(smlv);
366*b8aa3defSJoshua M. Clulow }
367*b8aa3defSJoshua M. Clulow }
368