2 * iSCSI Ioctl/Unix Interface
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * maintained by open-iscsi@googlegroups.com
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * See the file COPYING included with this distribution for more details.
27 #include <sys/types.h>
33 #include "iscsi_ipc.h"
35 #define CTL_DEVICE "/dev/iscsictl"
38 static void *xmitbuf
= NULL
;
39 static int xmitlen
= 0;
40 static void *recvbuf
= NULL
;
41 static int recvlen
= 0;
42 static void *ioctl_sendbuf
;
43 static void *ioctl_recvbuf
;
44 static void *pdu_sendbuf
;
46 #define IOCTL_BUF_DEFAULT_MAX \
47 (ISCSI_DEF_MAX_RECV_SEG_LEN + sizeof(struct iscsi_hdr))
49 #define PDU_SENDBUF_DEFAULT_MAX \
50 (ISCSI_DEF_MAX_RECV_SEG_LEN + sizeof(struct iscsi_hdr))
53 kread(char *data
, int count
)
55 log_debug(7, "in %s", __FUNCTION__
);
60 kwritev(enum iscsi_uevent_e type
, struct iovec
*iovp
, int count
)
62 log_debug(7, "in %s", __FUNCTION__
);
67 * __kipc_call() should never block
70 __kipc_call(void *iov_base
, int iov_len
)
72 log_debug(7, "in %s", __FUNCTION__
);
77 kcreate_session(uint64_t transport_handle
, uint32_t initial_cmdsn
,
78 uint32_t *out_sid
, uint32_t *out_hostno
)
81 struct iscsi_uevent ev
;
83 log_debug(7, "in %s", __FUNCTION__
);
85 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
87 ev
.type
= ISCSI_UEVENT_CREATE_SESSION
;
88 ev
.transport_handle
= transport_handle
;
89 ev
.u
.c_session
.initial_cmdsn
= initial_cmdsn
;
91 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
94 if (!ev
.r
.c_session_ret
.session_handle
|| ev
.r
.c_session_ret
.sid
< 0)
97 *out_handle
= ev
.r
.c_session_ret
.session_handle
;
98 *out_sid
= ev
.r
.c_session_ret
.sid
;
104 kdestroy_session(uint64_t transport_handle
, uint64_t sessionh
, uint32_t sid
)
107 struct iscsi_uevent ev
;
109 log_debug(7, "in %s", __FUNCTION__
);
111 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
113 ev
.type
= ISCSI_UEVENT_DESTROY_SESSION
;
114 ev
.transport_handle
= transport_handle
;
115 ev
.u
.d_session
.session_handle
= sessionh
;
116 ev
.u
.d_session
.sid
= sid
;
118 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
126 kcreate_conn(uint64_t transport_handle
, uint64_t sessionh
, uint32_t sid
,
127 uint32_t cid
, uint64_t *out_handle
)
130 struct iscsi_uevent ev
;
132 log_debug(7, "in %s", __FUNCTION__
);
134 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
136 ev
.type
= ISCSI_UEVENT_CREATE_CONN
;
137 ev
.transport_handle
= transport_handle
;
138 ev
.u
.c_conn
.session_handle
= sessionh
;
139 ev
.u
.c_conn
.cid
= cid
;
140 ev
.u
.c_conn
.sid
= sid
;
142 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
148 *out_handle
= ev
.r
.handle
;
153 kdestroy_conn(uint64_t transport_handle
, uint64_t connh
, int cid
)
156 struct iscsi_uevent ev
;
158 log_debug(7, "in %s", __FUNCTION__
);
160 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
162 ev
.type
= ISCSI_UEVENT_DESTROY_CONN
;
163 ev
.transport_handle
= transport_handle
;
164 ev
.u
.d_conn
.conn_handle
= connh
;
165 ev
.u
.d_conn
.cid
= cid
;
167 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
175 kbind_conn(uint64_t transport_handle
, uint64_t sessionh
, uint64_t connh
,
176 uint32_t transport_fd
, int is_leading
, int *retcode
)
179 struct iscsi_uevent ev
;
181 log_debug(7, "in %s", __FUNCTION__
);
183 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
185 ev
.type
= ISCSI_UEVENT_BIND_CONN
;
186 ev
.transport_handle
= transport_handle
;
187 ev
.u
.b_conn
.session_handle
= sessionh
;
188 ev
.u
.b_conn
.conn_handle
= connh
;
189 ev
.u
.b_conn
.transport_fd
= transport_fd
;
190 ev
.u
.b_conn
.is_leading
= is_leading
;
192 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
196 *retcode
= ev
.r
.retcode
;
202 ksend_pdu_begin(uint64_t transport_handle
, uint64_t connh
,
203 int hdr_size
, int data_size
)
205 struct iscsi_uevent
*ev
;
207 log_debug(7, "in %s", __FUNCTION__
);
210 log_error("send's begin state machine bug?");
214 xmitbuf
= pdu_sendbuf
;
215 memset(xmitbuf
, 0, sizeof(*ev
) + hdr_size
+ data_size
);
216 xmitlen
= sizeof(*ev
);
218 memset(ev
, 0, sizeof(*ev
));
219 ev
->type
= ISCSI_UEVENT_SEND_PDU
;
220 ev
->transport_handle
= transport_handle
;
221 ev
->u
.send_pdu
.conn_handle
= connh
;
222 ev
->u
.send_pdu
.hdr_size
= hdr_size
;
223 ev
->u
.send_pdu
.data_size
= data_size
;
225 log_debug(3, "send PDU began for hdr %d bytes and data %d bytes",
226 hdr_size
, data_size
);
230 ksend_pdu_end(uint64_t transport_handle
, uint64_t connh
, int *retcode
)
233 struct iscsi_uevent
*ev
;
236 log_debug(7, "in %s", __FUNCTION__
);
239 log_error("send's end state machine bug?");
243 if (ev
->u
.send_pdu
.conn_handle
!= connh
) {
244 log_error("send's end state machine corruption?");
248 iov
.iov_base
= xmitbuf
;
249 iov
.iov_len
= xmitlen
;
251 if ((rc
= __kipc_call(xmitbuf
, xmitlen
)) < 0)
254 *retcode
= ev
->r
.retcode
;
257 if (ev
->type
!= ISCSI_UEVENT_SEND_PDU
) {
258 log_error("bad event: bug on send_pdu_end?");
262 log_debug(3, "send PDU finished for conn (handle %p)", iscsi_ptr(connh
));
274 kset_param(uint64_t transport_handle
, uint64_t connh
,
275 enum iscsi_param param
, uint32_t value
, int *retcode
)
278 struct iscsi_uevent ev
;
280 log_debug(7, "in %s", __FUNCTION__
);
282 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
284 ev
.type
= ISCSI_UEVENT_SET_PARAM
;
285 ev
.transport_handle
= transport_handle
;
286 ev
.u
.set_param
.conn_handle
= connh
;
287 ev
.u
.set_param
.param
= param
;
288 ev
.u
.set_param
.value
= value
;
290 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
294 *retcode
= ev
.r
.retcode
;
300 kstop_conn(uint64_t transport_handle
, uint64_t connh
, int flag
)
303 struct iscsi_uevent ev
;
305 log_debug(7, "in %s", __FUNCTION__
);
307 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
309 ev
.type
= ISCSI_UEVENT_STOP_CONN
;
310 ev
.transport_handle
= transport_handle
;
311 ev
.u
.stop_conn
.conn_handle
= connh
;
312 ev
.u
.stop_conn
.flag
= flag
;
314 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
322 kstart_conn(uint64_t transport_handle
, uint64_t connh
, int *retcode
)
325 struct iscsi_uevent ev
;
327 log_debug(7, "in %s", __FUNCTION__
);
329 memset(&ev
, 0, sizeof(struct iscsi_uevent
));
331 ev
.type
= ISCSI_UEVENT_START_CONN
;
332 ev
.transport_handle
= transport_handle
;
333 ev
.u
.start_conn
.conn_handle
= connh
;
335 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
339 *retcode
= ev
.r
.retcode
;
344 krecv_pdu_begin(uint64_t transport_handle
, uint64_t connh
,
345 uintptr_t recv_handle
, uintptr_t *pdu_handle
, int *pdu_size
)
347 log_debug(7, "in %s", __FUNCTION__
);
350 log_error("recv's begin state machine bug?");
353 recvbuf
= (void*)recv_handle
+ sizeof(struct iscsi_uevent
);
355 *pdu_handle
= recv_handle
;
357 log_debug(3, "recv PDU began, pdu handle 0x%p",
364 krecv_pdu_end(uint64_t transport_handle
, uintptr_t conn_handle
,
365 uintptr_t pdu_handle
)
367 log_debug(7, "in %s", __FUNCTION__
);
370 log_error("recv's end state machine bug?");
374 log_debug(3, "recv PDU finished for pdu handle 0x%p",
377 recvpool_put((void*)conn_handle
, (void*)pdu_handle
);
385 struct iscsi_uevent ev
;
388 log_debug(7, "in %s", __FUNCTION__
);
390 memset(ev
, 0, sizeof(struct iscsi_uevent
));
392 * need to define this for bsd
394 ev
->type
= ISCSI_UEVENT_TRANS_LIST
;
396 if ((rc
= __kipc_call(&ev
, sizeof(ev
))) < 0) {
400 for (i
= 0; i
< ISCSI_TRANSPORT_MAX
; i
++) {
401 if (ev
.r
.t_list
.elements
[i
].trans_handle
) {
403 ev
.r
.t_list
.elements
[i
].trans_handle
;
404 strncpy(provider
[i
].name
, ev
.r
.t_list
.elements
[i
].name
,
405 ISCSI_TRANSPORT_NAME_MAXLEN
);
406 provider
[i
].caps
= ev
.r
.t_list
.elements
[i
].caps
;
415 log_debug(7, "in %s", __FUNCTION__
);
422 log_debug(7, "in %s", __FUNCTION__
);
424 ioctl_sendbuf
= calloc(1, IOCTL_BUF_DEFAULT_MAX
);
425 if (!ioctl_sendbuf
) {
426 log_error("can not allocate ioctl_sendbuf");
430 ioctl_recvbuf
= calloc(1, IOCTL_BUF_DEFAULT_MAX
);
431 if (!ioctl_recvbuf
) {
433 log_error("can not allocate ioctl_recvbuf");
437 pdu_sendbuf
= calloc(1, PDU_SENDBUF_DEFAULT_MAX
);
441 log_error("can not allocate ioctl_sendbuf");
457 struct iscsi_ipc ioctl_ipc
= {
458 .name
= "Open-iSCSI Kernel IPC/IOCTL v.1",
459 .ctldev_bufmax
= IOCTL_BUF_DEFAULT_MAX
,
460 .ctldev_open
= ctldev_open
,
461 .ctldev_close
= ctldev_close
,
462 .ctldev_handle
= ctldev_handle
,
463 .trans_list
= ktrans_list
,
464 .create_session
= kcreate_session
,
465 .destroy_session
= kdestroy_session
,
466 .create_conn
= kcreate_conn
,
467 .destroy_conn
= kdestroy_conn
,
468 .bind_conn
= kbind_conn
,
469 .set_param
= kset_param
,
471 .start_conn
= kstart_conn
,
472 .stop_conn
= kstop_conn
,
474 .send_pdu_begin
= ksend_pdu_begin
,
475 .send_pdu_end
= ksend_pdu_end
,
477 .recv_pdu_begin
= krecv_pdu_begin
,
478 .recv_pdu_end
= krecv_pdu_end
,
480 struct iscsi_ipc
*ipc
= &ioctl_ipc
;