xref: /netbsd/external/bsd/iscsi/dist/src/lib/osd_ops.c (revision 6550d01e)
1 /*
2  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
3  * using the software you agree to this license. If you do not agree to this license, do not download, install,
4  * copy or use the software.
5  *
6  * Intel License Agreement
7  *
8  * Copyright (c) 2002, Intel Corporation
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
12  * the following conditions are met:
13  *
14  * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
15  *  following disclaimer.
16  *
17  * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
18  *  following disclaimer in the documentation and/or other materials provided with the distribution.
19  *
20  * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
21  *  without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Transport-independent Methods
35  */
36 #include "config.h"
37 
38 
39 #include "osd.h"
40 #include "iscsiutil.h"
41 #include "compat.h"
42 #include "osd_ops.h"
43 
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
46 #endif
47 
48 static int
49 extract_attribute(uint32_t page, uint32_t n, uint16_t len,
50 		  uint8_t * data, unsigned length, void *val)
51 {
52 	int             i = 0;
53 
54 	for (i = 0; i < length;) {
55 		if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != page) {
56 			iscsi_err(__FILE__, __LINE__, "page mismatch: got 0x%x, expected 0x%x\n", ISCSI_NTOHL(*(uint32_t *) (data + i)), page);
57 			return -1;
58 		}
59 		i += 4;
60 		if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != n) {
61 			iscsi_err(__FILE__, __LINE__, "index mismatch\n");
62 			return -1;
63 		}
64 		i += 4;
65 		if (ISCSI_NTOHS(*(uint16_t *) (data + i)) != len) {
66 			iscsi_err(__FILE__, __LINE__, "len mismatch\n");
67 			return -1;
68 		}
69 		i += 2;
70 		iscsi_trace(TRACE_DEBUG, "page 0x%x, index %u, len %u\n", page, n, len);
71 		memcpy(val, data + i, len);
72 		i += len;
73 	}
74 	iscsi_trace(TRACE_DEBUG, "parsed %i bytes\n", i);
75 	return i;
76 }
77 
78 
79 int
80 osd_create_group(void *dev,
81 	  int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
82 		 uint32_t * GroupID)
83 {
84 	osd_args_t      args;
85 #if 0
86 	uint8_t         get_list[8];
87 #endif
88 	uint8_t         get_data[14];
89 	OSD_OPS_MEM     mem;
90 
91 	mem.recv_data = get_data;
92 	mem.recv_len = 14;
93 	mem.recv_sg = 0;
94 
95 	memset(&args, 0, sizeof(osd_args_t));
96 	args.opcode = 0x7F;
97 	args.service_action = OSD_CREATE_GROUP;
98 
99 #if 0
100 	args.length = 8;
101 	args.get_attributes_list_length = 8;
102 	*((unsigned long *) get_list) = ISCSI_HTONL(0x40000001);
103 	*((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x1);
104 	mem.send_data = get_list;
105 	mem.send_len = 8;
106 	mem.send_sg = 0;
107 #else
108 	args.get_attributes_page = 0x40000001;
109 	mem.send_data = NULL;
110 	mem.send_len = 0;
111 	mem.send_sg = 0;
112 #endif
113 
114 	args.get_attributes_allocation_length = 14;
115 	if (osd_exec(dev, &args, &mem) != 0) {
116 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
117 		return -1;
118 	}
119 	if (extract_attribute(0x40000001, 0x1, 4, get_data, 14, GroupID) == -1) {
120 		iscsi_err(__FILE__, __LINE__, "extract_attributes() failed\n");
121 		return -1;
122 	}
123 	*GroupID = ISCSI_NTOHL(*GroupID);
124 	iscsi_trace(TRACE_OSD, "osd_create_group() OK --> GroupID 0x%x\n", *GroupID);
125 
126 	return 0;
127 }
128 
129 int
130 osd_create(void *dev, uint32_t GroupID,
131 	   int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
132 	   uint64_t * UserID)
133 {
134 	osd_args_t      args;
135 #if 0
136 	uint8_t         get_list[8];
137 #endif
138 	uint8_t         get_data[18];
139 	OSD_OPS_MEM     mem;
140 
141 	mem.recv_data = get_data;
142 	mem.recv_len = 18;
143 	mem.recv_sg = 0;
144 
145 	memset(&args, 0, sizeof(osd_args_t));
146 	args.opcode = 0x7F;
147 	args.service_action = OSD_CREATE;
148 	args.GroupID = GroupID;
149 
150 #if 0
151 	args.length = 8;
152 	args.get_attributes_list_length = 8;
153 	*((unsigned long *) get_list) = ISCSI_HTONL(0x00000001);
154 	*((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x2);
155 	mem.send_data = get_list;
156 	mem.send_len = 8;
157 	mem.send_sg = 0;
158 #else
159 	args.get_attributes_page = 0x000000001;
160 	mem.send_data = NULL;
161 	mem.send_len = 0;
162 	mem.send_sg = 0;
163 #endif
164 
165 	args.get_attributes_allocation_length = 18;
166 	if (osd_exec(dev, &args, &mem) != 0) {
167 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
168 		return -1;
169 	}
170 	if (extract_attribute(0x00000001, 0x2, 8, get_data, 18, UserID) == -1) {
171 		iscsi_err(__FILE__, __LINE__, "extract_attributes() failed\n");
172 		return -1;
173 	}
174 	*UserID = ISCSI_NTOHLL(*UserID);
175 	iscsi_trace(TRACE_OSD, "osd_create(GroupID 0x%x) OK --> UserID 0x%llx\n", GroupID, *UserID);
176 
177 	return 0;
178 }
179 
180 int
181 osd_remove_group(void *dev, uint32_t GroupID,
182 	  int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
183 {
184 	osd_args_t      args;
185 	OSD_OPS_MEM     mem;
186 
187 	mem.send_data = NULL;
188 	mem.send_len = 0;
189 	mem.send_sg = 0;
190 	mem.recv_data = NULL;
191 	mem.recv_len = 0;
192 	mem.recv_sg = 0;
193 
194 	memset(&args, 0, sizeof(osd_args_t));
195 	args.opcode = 0x7F;
196 	args.service_action = OSD_REMOVE_GROUP;
197 	args.GroupID = GroupID;
198 	if (osd_exec(dev, &args, &mem) != 0) {
199 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
200 		return -1;
201 	}
202 	iscsi_trace(TRACE_OSD, "osd_remove_group(Group ID 0x%x) OK\n", GroupID);
203 
204 	return 0;
205 }
206 
207 int
208 osd_remove(void *dev, uint32_t GroupID, uint64_t UserID,
209 	   int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
210 {
211 	osd_args_t      args;
212 	OSD_OPS_MEM     mem;
213 
214 	mem.send_data = NULL;
215 	mem.send_len = 0;
216 	mem.send_sg = 0;
217 	mem.recv_data = NULL;
218 	mem.recv_len = 0;
219 	mem.recv_sg = 0;
220 
221 	memset(&args, 0, sizeof(osd_args_t));
222 	args.opcode = 0x7F;
223 	args.service_action = OSD_REMOVE;
224 	args.UserID = UserID;
225 	args.GroupID = GroupID;
226 	if (osd_exec(dev, &args, &mem) != 0) {
227 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
228 		return -1;
229 	}
230 	iscsi_trace(TRACE_OSD, "osd_remove(GroupID 0x%x, UserID 0x%llx) OK\n", GroupID, UserID);
231 
232 	return 0;
233 }
234 
235 int
236 osd_write(void *dev,
237 	  uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, const void *send_data, int sg_len,
238 	  int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
239 {
240 	osd_args_t      args;
241 	OSD_OPS_MEM     mem;
242 
243 	iscsi_trace(TRACE_OSD, "osd_write(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len);
244 	mem.send_data = send_data;
245 	mem.send_len = len;
246 	mem.send_sg = sg_len;
247 	mem.recv_data = NULL;
248 	mem.recv_len = 0;
249 	mem.recv_sg = 0;
250 	memset(&args, 0, sizeof(osd_args_t));
251 	args.opcode = 0x7F;
252 	args.service_action = OSD_WRITE;
253 	args.GroupID = GroupID;
254 	args.UserID = UserID;
255 	args.offset = offset;
256 	args.length = len;
257 	if (osd_exec(dev, &args, &mem) != 0) {
258 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
259 		return -1;
260 	}
261 	return 0;
262 }
263 
264 int
265 osd_read(void *dev,
266 	 uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, void *recv_data, int sg_len,
267 	 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
268 {
269 	osd_args_t      args;
270 	OSD_OPS_MEM     mem;
271 
272 	iscsi_trace(TRACE_OSD, "osd_read(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len);
273 	mem.send_data = NULL;
274 	mem.send_len = 0;
275 	mem.send_sg = 0;
276 	mem.recv_data = recv_data;
277 	mem.recv_len = len;
278 	mem.recv_sg = sg_len;
279 	memset(&args, 0, sizeof(osd_args_t));
280 	args.opcode = 0x7F;
281 	args.service_action = OSD_READ;
282 	args.GroupID = GroupID;
283 	args.UserID = UserID;
284 	args.offset = offset;
285 	args.length = len;
286 	if (osd_exec(dev, &args, &mem) != 0) {
287 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
288 		return -1;
289 	}
290 	return 0;
291 }
292 
293 int
294 osd_set_one_attr(void *dev,
295 		 uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t len, void *value,
296 	  int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
297 {
298 	osd_args_t      args;
299 	OSD_OPS_MEM     mem;
300 	uint8_t         list[10];
301 #if 0
302 	struct iovec    sg[2];
303 #else
304 	uint8_t        *buffer = NULL;
305 #endif
306 
307 	iscsi_trace(TRACE_OSD, "osd_set_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Len %u)\n",
308 	      GroupID, UserID, page, n, len);
309 	memset(&args, 0, sizeof(osd_args_t));
310 	args.opcode = 0x7F;
311 	args.service_action = OSD_SET_ATTR;
312 	args.GroupID = GroupID;
313 	args.UserID = UserID;
314 	args.length = 10 + len;
315 	args.set_attributes_list_length = 10 + len;
316 	*((uint32_t *) (list + 0)) = ISCSI_HTONL(page);
317 	*((uint32_t *) (list + 4)) = ISCSI_HTONL(n);
318 	*((uint16_t *) (list + 8)) = ISCSI_HTONS(len);
319 #if 0
320 	sg[0].iov_base = list;
321 	sg[0].iov_len = 10;
322 	sg[1].iov_base = value;
323 	sg[1].iov_len = len;
324 	mem.send_data = sg;
325 	mem.send_len = 10 + len;
326 	mem.send_sg = 2;
327 #else
328 	if ((buffer = iscsi_malloc_atomic(10 + len)) == NULL) {
329 		iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
330 		return -1;
331 	}
332 	memcpy(buffer, list, 10);
333 	memcpy(buffer + 10, value, len);
334 	mem.send_data = buffer;
335 	mem.send_len = 10 + len;
336 	mem.send_sg = 0;
337 #endif
338 	mem.recv_data = NULL;
339 	mem.recv_len = 0;
340 	mem.recv_sg = 0;
341 
342 	if (osd_exec(dev, &args, &mem) != 0) {
343 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
344 		return -1;
345 	}
346 	if (buffer)
347 		iscsi_free_atomic(buffer);
348 
349 	return 0;
350 }
351 
352 int
353 osd_get_one_attr(void *dev,
354 		 uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t alloc_len,
355 	  int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
356 		 uint16_t * len, void *value)
357 {
358 	osd_args_t      args;
359 	OSD_OPS_MEM     mem;
360 	uint8_t         list_out[8];
361 #if 0
362 	uint8_t         list_in[10];
363 	struct iovec    sg[2];
364 #else
365 	uint8_t        *buffer;
366 #endif
367 
368 	iscsi_trace(TRACE_OSD, "osd_get_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Alloc Len %u)\n",
369 	      GroupID, UserID, page, n, alloc_len);
370 	memset(&args, 0, sizeof(osd_args_t));
371 	args.opcode = 0x7F;
372 	args.service_action = OSD_GET_ATTR;
373 	args.GroupID = GroupID;
374 	args.UserID = UserID;
375 	if (n) {
376 		args.length = 8;
377 		*((uint32_t *) (list_out + 0)) = ISCSI_HTONL(page);
378 		*((uint32_t *) (list_out + 4)) = ISCSI_HTONL(n);
379 		args.get_attributes_list_length = 8;
380 		mem.send_data = list_out;
381 		mem.send_len = 8;
382 		mem.send_sg = 0;
383 	} else {
384 		iscsi_trace(TRACE_OSD, "requesting entire page or reference page\n");
385 		mem.send_data = NULL;
386 		mem.send_len = 0;
387 		mem.send_sg = 0;
388 		args.get_attributes_page = page;
389 	}
390 #if 0
391 	sg[0].iov_base = list_in;
392 	sg[0].iov_len = 10;
393 	sg[1].iov_base = value;
394 	sg[1].iov_len = alloc_len;
395 	mem.recv_data = sg;
396 	mem.recv_len = 10 + alloc_len;
397 	mem.recv_sg = 2;
398 #else
399 	if ((buffer = iscsi_malloc_atomic(10 + alloc_len)) == NULL) {
400 		iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
401 		return -1;
402 	}
403 	mem.recv_data = buffer;
404 	mem.recv_len = 10 + alloc_len;
405 	mem.recv_sg = 0;
406 #endif
407 	args.get_attributes_allocation_length = 10 + alloc_len;
408 	if (osd_exec(dev, &args, &mem) != 0) {
409 		iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n");
410 		return -1;
411 	}
412 	memcpy(value, buffer + 10, alloc_len);
413 	if (buffer)
414 		iscsi_free_atomic(buffer);
415 	return 0;
416 }
417