Commit Graph

114 Commits

Author SHA1 Message Date
Ronnie Sahlberg
edd7d9b843 Remove the small allocations
This is not compatible with multithreading and would require a complete
re-design.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2025-04-26 08:56:16 +10:00
Ronnie Sahlberg
91cc1e4197 Protect outqueue and waitpdu with a spinlock
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2025-04-26 08:56:16 +10:00
hongleiwang
29e626c0f4 feat: add iscsi_reset_next_reconnect interface
When an iSCSI connection enters the reconnection phase, the backoff
time (next_reconnect) increases with reconnection retry_cnt. However,
if the client detects that the target has recovered before reaching
next_reconnect, calling iscsi_reconnect/iscsi_force_reconnect has no
any effect, making fast reconnection impossible.

This patch introduces an interface to reset next_reconnect, so that
the client can reset the backoff time upon detecting target recovery
and achieve faster reconnection.

Resolves: https://github.com/sahlberg/libiscsi/issues/428

Signed-off-by: raywang <honglei.wang@smartx.com>
2024-10-30 18:29:33 +08:00
Brian Meagher
882bcad53a Add support for Data Digest 2024-05-04 19:34:06 -07:00
zhenwei pi
7bf8091013 Add iscsi_set_fd_dup_cb
libiscsi is widely used by poll driven, include libiscsi itself,
QEMU. Using poll works fine after iscsi reconnect, but it does not work
in epoll, because the epoll event has been removed during duplicating
file descriptor in kernel.

Add a new function iscsi_set_fd_dup_cb to set callback, then uplayer
gets notified after duplicating. The following codes reproduce this
issue, and test this patch by compiling flags -DISCSI_FD_DUP_CB.

static void iscsi_epoll_event(struct iscsi_context *iscsi, int epollfd, bool new)
{
	static int epoll_event;
	struct epoll_event ev = { 0 };
	int pevent = iscsi_which_events(iscsi);
	int event = 0;

	if (pevent & POLLIN)
		event |= EPOLLIN;

	if (pevent & POLLOUT)
		event |= EPOLLOUT;

	ev.events = event;
	ev.data.fd = iscsi_get_fd(iscsi);
	if (new)
		epoll_ctl(epollfd, EPOLL_CTL_ADD, ev.data.fd, &ev);
	else if (epoll_event != event) {
		epoll_ctl(epollfd, EPOLL_CTL_MOD, ev.data.fd, &ev);
	}
	epoll_event = event;
}

static void iscsi_tsk_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	printf("iscsi_tsk_cb status %d\n", status);
	exit(0);
}

static void iscsi_fd_dup_cb(struct iscsi_context *iscsi, void *opaque)
{
	int epollfd = *(int *)opaque;

	iscsi_epoll_event(iscsi, epollfd, true);
}

static void iscsi_on_pollout(struct iscsi_context *iscsi, struct iscsi_url *iscsi_url, int epollfd)
{
	static struct scsi_task *tsk = NULL;

	iscsi_service(iscsi, POLLOUT);
	if (!tsk) {
		tsk = iscsi_readcapacity16_task(iscsi, iscsi_url->lun, iscsi_tsk_cb, NULL);
		assert(tsk);
	}
}

int main(int argc, char *argv[])
{
	struct iscsi_context *iscsi;
	struct iscsi_url *iscsi_url;
	struct epoll_event ev, revent;
	int epollfd;

	iscsi = iscsi_create_context("dummy");
	assert(iscsi);

	iscsi_url = iscsi_parse_full_url(iscsi, argv[1]);
	assert(iscsi_url);

	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	assert(!iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun));

	epollfd = epoll_create1(0);
	iscsi_epoll_event(iscsi, epollfd, true);

	iscsi_set_fd_dup_cb(iscsi, iscsi_fd_dup_cb, &epollfd);
	iscsi_reconnect(iscsi);

	while (epoll_wait(epollfd, &revent, 1, 100) >= 0) {
		if (revent.events & EPOLLIN)
			iscsi_service(iscsi, POLLIN);

		if (revent.events & EPOLLOUT)
			iscsi_on_pollout(iscsi, iscsi_url, epollfd);

		iscsi_epoll_event(iscsi, epollfd, false);
	}

	return 0;
}

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2023-06-06 13:29:52 +08:00
Li kunyu
c0fdc4655a connect: Add check after malloc allocation 2022-12-14 14:47:05 +08:00
John Levon
30dd7c6429 add iscsi_force_reconnect()
If a connection attempt is hung, then iscsi_reconnect() won't do anything. This
makes sense if we'd just re-try to connect to the same target, but if (for
example) login redirect might point us to a different, healthy, target, it
should be possible to restart the full connection process on request.

Signed-off-by: John Levon <john.levon@nutanix.com>
2022-01-17 13:14:49 -08:00
Bart Van Assche
2a5a0b3291 Enable -Wno-unused-parameter
Instead of adding __attribute__((unused)) to unused arguments, add the
-Wno-unused-parameter compiler flag.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
2021-05-23 13:23:41 -07:00
wanghonghao
0659c74302 reconnect: collect mallocs/frees of the previous reconnection
Signed-off-by: wanghonghao <wanghonghao@bytedance.com>
2020-04-11 12:46:44 +08:00
wanghonghao
2212021747 iser: enhance connection procedure
This patch is used to fix the following problems in the current connection
method:
1. iscsi_iser_connect() waits until the connection is established or failed,
and may block the caller for a long time.
2. Although there's a cm_thread handles communication events, but in fact it
has no effects after the connection is established.
3. Resources are not released properly after reconnection failed. And once we
try to reconnect again, the resources will leak permanently.
(see iscsi_reconnect()).

This patch eliminate cm_thread and handle communication events in the caller
thread.
Connection procedure:
1. Create a mock fd by eventfd() (or just use old_iscsi->fd while reconnecting),
and assign it to iscsi->fd.
2. Create communication event channel, make it non-blocking and dup the
notifier fd to iscsi->fd.
3. Handle communication events by iscsi_which_events()/iscsi_service() loop
until connection established or falied.
4. If connection is established successfully, dup the notifier fd of completion
queue (CQ) events to iscsi->fd.
5. Handle completion queue (CQ) events by iscsi_which_events()/iscsi_service()
loop.
The entire procedure is non-blocking.

After established, whenever iscsi_service() is called with revents=0 or
queue_pdu() is called with a NOP pdu, communication events will be checked.

When connection failed, iser transport cleanup itself before callbacks.

Signed-off-by: wanghonghao <wanghonghao@bytedance.com>
2020-04-07 10:38:37 +08:00
zhenwei pi
3ccbceb6ff lib/connect.c: fix wrong transport type for iser reconnect
A new iscsi context is created as TCP transport type, but currently
missing iscsi_init_transport to change transport to iser in
reconnecting logic, then iser could never reconnect successfully.

Use orignal transport to initialize new iscsi context.

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
2020-02-27 22:13:08 +08:00
Tim Crawford
9347cfebf2 Replace file variables with .dir-locals.el
Signed-off-by: Tim Crawford <tcrawford@datto.com>
2019-02-21 11:54:02 -05:00
Bart Van Assche
663aad13ba Avoid that iscsi_reconnect() crashes
In the else branch, set the tmp_iscsi->old_iscsi pointer instead of the
iscsi->old_iscsi pointer.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
2019-01-13 11:48:28 -08:00
Felipe Franciosi
1891d502a0 iscsi_reconnect: improve local variable naming
The current iscsi context in iscsi_reconnect() is called "old_iscsi",
whilst the temporary context is called "iscsi". That is rather
confusing, and this fixes that by calling the current context "iscsi"
and the temporary context "tmp_iscsi".

Signed-off-by: Felipe Franciosi <felipe@nutanix.com>
2018-09-30 11:38:38 +01:00
Felipe Franciosi
b377eece90 lib/connect.c: Fix whitespace formatting
This fixes some identation in iscsi_reconnect_cb() where whitespaces
were used instead of hard tabs.

Signed-off-by: Felipe Franciosi <felipe@nutanix.com>
2018-09-30 11:12:30 +01:00
Felipe Franciosi
3c4925e8da pdu: Introduce iscsi_cancel_pdus()
Introduce a helper exported from lib/pdu.c which cancels all pdus for a
given context. This patch eliminates repeated code from various other
files which have the same purpose. The only functional difference is
that the cancellation done from iscsi-command.c was (incorrectly) not
checking for iscsi->is_loggedin before issuing callbacks.

Signed-off-by: Felipe Franciosi <felipe@nutanix.com>
2017-11-25 17:03:01 +00:00
Tim Crawford
aba0f7da1a Replace WIN32 with _WIN32
Using WIN32 depends on the build environment defining the variable.
_WIN32 is a predefined MSVC macro and is always available.

Signed-off-by: Tim Crawford <crawfxrd@gmail.com>
2017-11-29 10:07:44 -05:00
Ronnie Sahlberg
f750101980 Add initial visual studio project files and fix the win32 build
Win32 has been rotting for a while. This patch adds vs17 build files
as well as fixing up all build errors that have accumulated.
There are still build warnings but those can be addressed in a followup
patch.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2017-05-11 21:19:14 -07:00
Peter Lieven
eb7c1d9b0c socket: process PDUs directly after receiving them
this eliminated the need for an inqueue

Signed-off-by: Peter Lieven <pl@kamp.de>
2017-01-06 11:48:17 +01:00
Peter Lieven
fa123fc397 abstract transport to static driver functions and opaque driver specific information.
This splits a transport into static driver specific functions for the common
iscsi commands. Optionally, a driver specific opaque memory is introduced
which is currently only used by iSER transport.
Last a lot of functions changed to static.

Signed-off-by: Peter Lieven <pl@kamp.de>
2016-08-05 11:28:43 +02:00
Peter Lieven
f2850fdcc6 connect: do not leak transport struct on iscsi_reconnect_cb
Signed-off-by: Peter Lieven <pl@kamp.de>
2016-07-07 11:47:58 +02:00
Roy Shterman
6c1bdb4808 Libiscsi: Adding free_pdu function to transport abstraction
Signed-off-by: Roy Shterman <roysh@mellanox.com>
2016-06-03 18:47:23 -07:00
Peter Lieven
cde2043891 pdu: drop ISCSI_PDU_NO_CALLBACK
we use the flag ISCSI_PDU_NO_CALLBACK and pdu->callback simultaneously, but
check only for one of them in various places. So drop ISCSI_PDU_NO_CALLBACK
and check for pdu->callback != NULL instead.

All PDUs that carried this flag have pdu->callback set to NULL.

Signed-off-by: Peter Lieven <pl@kamp.de>
2016-05-02 10:40:15 +02:00
Peter Lieven
a7c94a7af5 connect: invoke all callbacks for dropped PDUs
if we drop a PDU which has a callback we should invoke it otherwise
the caller may wait infinetely for a command completion.

Signed-off-by: Peter Lieven <pl@kamp.de>
2016-03-17 12:08:26 +01:00
Peter Lieven
97406c5b36 Revert "Fail pending LOGOUT commands on session reconnect"
This seriously breaks qemu NOP timeouts and probably other things.
The reason is that the

define ISCSI_PDU_ERROR_ON_RECONNECT	0x00000016

is masking bits 0x2 and 0x4 as well.

Correctly it should read:
define ISCSI_PDU_ERROR_ON_RECONNECT	0x00000010

However, the better solution for this approach is invoke all callbacks
of PDUs which carry the ISCSI_PDU_DROP_ON_RECONNECT flag. This will
make sure that callbacks of whatever sync tasks are invoked.

This reverts commit 0407cf6aed.
2016-03-17 12:08:20 +01:00
Ronnie Sahlberg
0629d44e83 Remove C99 style variable declarations
Make it slightly more portable and move the declarations to the start of the
function.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2016-02-18 21:50:35 -08:00
Ronnie Sahlberg
99a5f99527 Add some emacs defaults. Tabs are 8 spaces.
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2016-02-18 21:34:43 -08:00
Ronnie Sahlberg
0407cf6aed Fail pending LOGOUT commands on session reconnect
Certain iSCSI commands such as NOP and LOGOUT commands are discarded instead
of re-queued when we have a session failure and reconnect.
Change the LOGOUT command to instead fail with SCSI_STATUS_ERROR when this
happens.

Otherwise, IF we are in iscsi_logout_sync() and we get a session failure
at the same-ish time we may end up automatically re-connecting the
session, but since we have discarded the logout command we will never
get a reply and will hang indefinitely in the event loop for synchronous
commands.
Arguably, we could also just return SCSI_STATUS_GOOD here since
when we perform a logout, we probably don't care too much about how we
disconnected from the server, only that we did disconnect from the server.
That is academic anyway since this only affects the sync API which is only
meant for trivial applications, which will likely not inspect the result
and just do a:
...
iscsi_logout_sync()
iscsi_destroy_context()
...
anyway.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-12-15 21:17:50 -08:00
Ronnie Sahlberg
916fef6c03 Allow sending TUR to consume all UAs during reconnect
During reconnect we normally defer any SCSI commands that are issued
to be queued and sent later, once the re-connect has completed and we have
swapped the contexts.
This is what we want for almost all situations, except when we are
reconnecting very simple applications which request "no ua on reconnect".
For these applications we want to actually send the TURs that are used
during the login phase on the temporary context.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-12-15 19:05:55 -08:00
Ronnie Sahlberg
3c44092635 Add a feature to request transparent reconnects without any UA
Normal applications want the current behaviour where we have the library
consume any/all of the UnitAttentions that the target may have queued on the
initial connection, but when we reconnect the session after a failure the
library will pass all the UAs back to the application to process.

Some applications, such as the test suite or really trivial applications
might not want to have to deal with handling of UAs and just "make it work".
Those applications can now request that upon any reconnection of the session
that libiscsi will automatically consume any and all UAs and hide them from
the application.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-12-13 14:29:32 -08:00
Peter Lieven
0a3e157844 reconnect: copy scsi_timeout on reconnect
Signed-off-by: Peter Lieven <pl@kamp.de>
2015-06-16 11:33:57 +02:00
Ronnie Sahlberg
cb4ad5f774 Connect: Don't use the TUR checks on re-connects
Only use TUR to eat any pending unit attentions on the initial connect
but not during reconnect.

From Peter Lieven <pl@kamp.de>

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-05-19 19:21:26 -07:00
Peter Lieven
b4098c535e init: make LIBISCSI_CACHE_ALLOCATIONS a public environment variable
this variable was introduced for iscsi-test-cu only. This patch
makes it a generic environment variable that can be set per context.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-05-05 14:10:44 +02:00
Peter Lieven
cd0f4a30d6 connect: fir off by one error in iscsi->reconnect_max_retries
Before b152d26 it was possible to set iscsi->reconnect_max_retries to 0.
This allowed reconnects, but aborted as soon as the reconnect failed.
The same behaviour is currenltly only possible by setting iscsi->reconnect_max_retries
to 1. iscsi->reconnect_max_retries == 0 forbids reconnecting completly.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-04-23 14:16:17 +02:00
Peter Lieven
913b2ab708 reconnect: avoid deadlock if socker error is received during reconnect
If we are reconnecting and the connection is already established we
end up looping forever if there is a socket error before we finish
the login process. Fix this by invoking the reconnect callback if
there is an error and no new reconnect is scheduled.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-04-13 12:11:03 +02:00
Peter Lieven
a8b33cefac drop iscsi->is_reconnecting
iscsi->is_reconnecting != 0 is equal to iscsi->old_iscsi != NULL.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-04-13 10:13:36 +02:00
Peter Lieven
63fd8679fa reconnect: do not queue TESTUNIT_READY cdbs
those are part of the login process to consume UNIT_ATTENTIONS.

Its questionable if we should consume them at all, but iff we change
that behaviour we should do it for the initial login as well as
for a reconnect.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-04-13 10:06:32 +02:00
Peter Lieven
b152d26eb9 connect: make the reconnect async
Signed-off-by: Peter Lieven <pl@kamp.de>
2015-03-31 16:21:00 +02:00
Peter Lieven
fe265aef9c connect: allow to avoid the testunit ready call in iscsi_full_connect_async
iscsi-ls show luns command does not work when the target redirects at login.
to avoid redundant code allow iscsi_full_connect_async to skip the testunit ready
part.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-03-26 10:48:01 +01:00
Peter Lieven
a45094b7a7 init: fix segfaul in iscsi_parse_url
We allowed iscsi to be NULL in iscsi_parse_url. Especially
qemu does this and currently segfaults at start. Change the
usage guidelines for target username/password to be the same
as for chap username/password.

Signed-off-by: Peter Lieven <pl@kamp.de>
2015-03-26 10:07:52 +01:00
Peter Lieven
b55ce5cc09 reconnect: do not leak free small allocations
Signed-off-by: Peter Lieven <pl@kamp.de>
2015-03-24 15:22:37 +01:00
Peter Lieven
3b6f796a1b reconnect: do not leak immediate PDUs
Signed-off-by: Peter Lieven <pl@kamp.de>
2015-03-24 14:33:06 +01:00
Ronnie Sahlberg
b1d0ac45f1 Add support for bidirectional CHAP
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-03-14 10:43:03 -07:00
Ronnie Sahlberg
ec4266392e connect.c: improve comment in reconnect code that we ONLY requeue SCSI COMMAND
The only PDU type that does not have ISCSI_PDU_DROP_ON_RECONNECT is the
SCSI COMMAND PDU. Thsi is the only PDU that we re-queue on reconnect.
All other, including DATA-OUT, NOP, task management, PDUs are simply
dropped.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-02-24 07:01:20 -08:00
Ronnie Sahlberg
6822baee3f reconnect: we need to reset the in/out iovectors on reconnect
This is a bug that has been there a long time.
When we reconnect and requeue a PDU we must reset the iovectors
for the task. Otherwise, any partially sent/received data when the
command is reconnected would end up containing garbage.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-02-24 06:54:18 -08:00
Ronnie Sahlberg
76f8296dbb reconnect logic and pdu handling
Rework the reconnect logic so we just call iscsi_scsi_command_async()
for the scsi commands we are re-quining instead of poking into the
private fields of the structures themself.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-02-23 20:46:57 -08:00
Ronnie Sahlberg
2f5d21b09c iscsi-command.c: Use common function to write unsolicited data-out pdus.
We write unsolicited data-out PDUs from two places;
when we originally write the command in iscsi_scsi_command_async()
but also when we re-queue the PDUs during a session reconnect.

The re-queuing during the session re-connect was recently (almost) fixed
but was still buggy in that it did not correctly clamp the amount of written
data as per first burst length restriction.
This attempts to fix that.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-02-20 20:51:14 -08:00
Ronnie Sahlberg
b001d980ef reconnect: we must re-queue any missing data-outs during reconnect
If we have writes that do not have the Final bit set during reconnect
we must send out any missing data-out PDU.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2015-02-17 06:46:58 -08:00
Ronnie Sahlberg
e07498e5c3 connect.c: improve the error message when iscsi_connect_async fails
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2014-12-07 10:08:38 -08:00
Ronnie Sahlberg
f6d57ef3b0 connect.c: remove UA whitelist and just consume up to 10 UAs before failing
Lets not use a whitelist of UnitAttentions that we consume during the connect
phase. Instead we can just loop and fail after the 10th.
If there are more than 10 UAs then we have a problem, otherwise
just consume them all, forget them  and then pass control back to the caller.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2014-09-23 17:23:27 -07:00