Patchwork [11/14] ./block/iscsi/connect.c

login
register
mail settings
Submitter ronniesahlberg@gmail.com
Date Dec. 3, 2010, 11:09 a.m.
Message ID <1291374593-17448-12-git-send-email-ronniesahlberg@gmail.com>
Download mbox | patch
Permalink /patch/74125/
State New
Headers show

Comments

ronniesahlberg@gmail.com - Dec. 3, 2010, 11:09 a.m.
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>

iscsi  client library  : connect.c
This file contains helper functions to make simples use of iscsi resources
easier by for example baking tcp connect, login, testunit ready, verifying device is available,
into one simple to use function.

...

./block/iscsi/ contains a copy of a general purpose iscsi client
library which is aimed at providing a clientside api for iscsi
for both qemu/kvm as well as otther scsi related utilities.

As such, there is need to make merging across various consumers,
qemu/kvm being one of many here, as easy as possible when features
are added to the library.
As such, no consumer/qemu specific code is used in this library as well
as coding guidelined might not be adhered to 100%

It is the intention that this library will be useful for many
and that iscsi use spawned from this will flourish.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
---
 block/iscsi/connect.c |  127 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 0 deletions(-)
 create mode 100644 block/iscsi/connect.c

Patch

diff --git a/block/iscsi/connect.c b/block/iscsi/connect.c
new file mode 100644
index 0000000..235d3bd
--- /dev/null
+++ b/block/iscsi/connect.c
@@ -0,0 +1,127 @@ 
+/*
+   Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "iscsi.h"
+#include "iscsi-private.h"
+#include "scsi-lowlevel.h"
+
+struct connect_task {
+	iscsi_command_cb cb;
+	void *private_data;
+	int lun;
+};
+
+static void
+iscsi_testunitready_cb(struct iscsi_context *iscsi, int status,
+		       void *command_data, void *private_data)
+{
+	struct connect_task *ct = private_data;
+
+	if (status != 0) {
+		struct scsi_task *scsi = command_data;
+
+		if (scsi->sense.key == SCSI_SENSE_UNIT_ATTENTION
+		    && scsi->sense.ascq == SCSI_SENSE_ASCQ_BUS_RESET) {
+			/* This is just the normal unitattention/busreset
+			 * you always get just after a fresh login. Try
+			 * again.
+			 */
+			if (iscsi_testunitready_async(iscsi, ct->lun,
+						      iscsi_testunitready_cb,
+						      ct) != 0) {
+				iscsi_set_error(iscsi, "iscsi_testunitready "
+						"failed.");
+				ct->cb(iscsi, SCSI_STATUS_ERROR, NULL,
+				       ct->private_data);
+				free(ct);
+			}
+			return;
+		}
+	}
+
+	ct->cb(iscsi, status?SCSI_STATUS_ERROR:SCSI_STATUS_GOOD, NULL,
+	       ct->private_data);
+	free(ct);
+}
+
+static void
+iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data,
+	       void *private_data)
+{
+	struct connect_task *ct = private_data;
+
+	if (status != 0) {
+		iscsi_set_error(iscsi, "Failed to login to iSCSI target. "
+				"%s\n", iscsi_get_error(iscsi));
+		ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
+		free(ct);
+		return;
+	}
+
+	if (iscsi_testunitready_async(iscsi, ct->lun,
+				      iscsi_testunitready_cb, ct) != 0) {
+		iscsi_set_error(iscsi, "iscsi_testunitready_async failed.");
+		ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
+		free(ct);
+	}
+}
+
+static void
+iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
+		 void *private_data)
+{
+	struct connect_task *ct = private_data;
+
+	if (status != 0) {
+		iscsi_set_error(iscsi, "Failed to connect to iSCSI socket. "
+				"%s\n", iscsi_get_error(iscsi));
+		ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
+		free(ct);
+		return;
+	}
+
+	if (iscsi_login_async(iscsi, iscsi_login_cb, ct) != 0) {
+		iscsi_set_error(iscsi, "iscsi_login_async failed.");
+		ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
+		free(ct);
+	}
+}
+
+
+int
+iscsi_full_connect_async(struct iscsi_context *iscsi, const char *portal,
+			 int lun, iscsi_command_cb cb, void *private_data)
+{
+	struct connect_task *ct;
+
+	ct = malloc(sizeof(struct connect_task));
+	if (ct == NULL) {
+		iscsi_set_error(iscsi, "Out-of-memory. Failed to allocate "
+				"connect_task structure.");
+		return -ENOMEM;
+	}
+	ct->cb           = cb;
+	ct->lun          = lun;
+	ct->private_data = private_data;
+	if (iscsi_connect_async(iscsi, portal, iscsi_connect_cb, ct) != 0) {
+		free(ct);
+		return -ENOMEM;
+	}
+	return 0;
+}