From 3dfdebcba7d050191fdc5aabf9a0681776057455 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 15 Feb 2011 21:53:47 +1100 Subject: [PATCH] TaskMgmt : Add an initial function to create a iscsi tm PDU --- Makefile.in | 3 +- include/iscsi-private.h | 2 + include/iscsi.h | 23 +++++++++++ lib/task_mgmt.c | 91 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 lib/task_mgmt.c diff --git a/Makefile.in b/Makefile.in index b1be637..7db9a8d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,7 +5,8 @@ bindir = @bindir@ LIBS=-lpopt @LIBS@ CC=gcc CFLAGS=-g -O2 -fPIC -Wall -W -I. -I./include "-D_U_=__attribute__((unused))" -LIBISCSI_OBJ = lib/connect.o lib/crc32c.o lib/discovery.o lib/init.o lib/login.o lib/md5.o lib/nop.o lib/pdu.o lib/scsi-command.o lib/scsi-lowlevel.o lib/socket.o lib/sync.o +LIBISCSI_OBJ = lib/connect.o lib/crc32c.o lib/discovery.o lib/init.o lib/login.o lib/md5.o lib/nop.o lib/pdu.o lib/scsi-command.o lib/scsi-lowlevel.o lib/socket.o lib/sync.o lib/task_mgmt.o + INSTALLCMD = @install@ -c LIBISCSI_SO_NAME=libiscsi.so.1 diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 428c6c9..a60911a 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -233,6 +233,8 @@ int iscsi_process_scsi_data_in(struct iscsi_context *iscsi, int iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in); +int iscsi_process_task_mgmt_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, + struct iscsi_in_pdu *in); int iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in); diff --git a/include/iscsi.h b/include/iscsi.h index 01de647..ac18344 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -413,6 +413,29 @@ struct iscsi_discovery_address { int iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, unsigned char *data, int len, void *private_data); +/* + * Asynchronous call for task management + * + * Returns: + * 0 if the call was initiated and the task mgmt function will be invoked. + * the connection will be reported through the callback function. + * <0 if there was an error. The callback function will not be invoked. + * + * Callback parameters : + * status can be either of : + * ISCSI_STATUS_GOOD : Connection was successful. Command_data is NULL. + * + * ISCSI_STATUS_ERROR : Error. + * + * The callback will NOT be invoked if the session is explicitely torn down + * through a call to iscsi_disconnect() or iscsi_destroy_context(). + */ +int +iscsi_task_mgmt_async(struct iscsi_context *iscsi, + int lun, uint8_t function, + uint32_t ritt, uint32_t rcmdscn, + iscsi_command_cb cb, void *private_data); + diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c new file mode 100644 index 0000000..032b5ee --- /dev/null +++ b/lib/task_mgmt.c @@ -0,0 +1,91 @@ +/* + Copyright (C) 2011 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "iscsi-private.h" + +int +iscsi_task_mgmt_async(struct iscsi_context *iscsi, + int lun, uint8_t function, + uint32_t ritt, uint32_t rcmdsn, + iscsi_command_cb cb, void *private_data) +{ + struct iscsi_pdu *pdu; + + if (iscsi->is_loggedin == 0) { + iscsi_set_error(iscsi, "trying send nop-out while not logged " + "in"); + return -1; + } + + pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_TASK_MANAGEMENT_REQUEST, + ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE); + if (pdu == NULL) { + iscsi_set_error(iscsi, "Failed to allocate task mgmt pdu"); + return -1; + } + + /* immediate flag */ + iscsi_pdu_set_immediate(pdu); + + /* flags */ + iscsi_pdu_set_pduflags(pdu, 0x80 | function); + + /* lun */ + iscsi_pdu_set_lun(pdu, 2); + + /* ritt */ + iscsi_pdu_set_ritt(pdu, ritt); + + /* cmdsn is not increased if Immediate delivery*/ + iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); + pdu->cmdsn = iscsi->cmdsn; + + /* rcmdsn */ + iscsi_pdu_set_rcmdsn(pdu, rcmdsn); + + + pdu->callback = cb; + pdu->private_data = private_data; + + if (iscsi_queue_pdu(iscsi, pdu) != 0) { + iscsi_set_error(iscsi, "failed to queue iscsi taskmgmt pdu"); + iscsi_free_pdu(iscsi, pdu); + return -1; + } + + return 0; +} + +int +iscsi_process_task_mgmt_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, + struct iscsi_in_pdu *in) +{ + struct iscsi_data data; + + data.data = NULL; + data.size = 0; + + if (in->data_pos > ISCSI_HEADER_SIZE) { + data.data = in->data; + data.size = in->data_pos; + } + pdu->callback(iscsi, SCSI_STATUS_GOOD, &data, pdu->private_data); + + return 0; +}