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>
This commit is contained in:
zhenwei pi
2023-06-06 11:47:25 +08:00
parent 5233a80de4
commit 7bf8091013
7 changed files with 33 additions and 3 deletions

View File

@@ -19,6 +19,7 @@
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#if defined(_WIN32)
#include <basetsd.h>
@@ -171,6 +172,8 @@ struct iscsi_context {
struct iscsi_context *old_iscsi;
int retry_cnt;
int no_ua_on_reconnect;
void (*fd_dup_cb)(struct iscsi_context *iscsi, void *opaque);
void *fd_dup_opaque;
};
#define ISCSI_PDU_IMMEDIATE 0x40
@@ -397,6 +400,15 @@ typedef struct iscsi_transport {
int (*which_events)(struct iscsi_context *iscsi);
} iscsi_transport;
static inline int iscsi_dup2(struct iscsi_context *iscsi, int oldfd, int newfd)
{
int ret = dup2(oldfd, newfd);
if ((ret >= 0) && iscsi->fd_dup_cb)
iscsi->fd_dup_cb(iscsi, iscsi->fd_dup_opaque);
return ret;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1648,6 +1648,12 @@ iscsi_set_reconnect_max_retries(struct iscsi_context *iscsi, int count);
EXTERN void
iscsi_set_no_ua_on_reconnect(struct iscsi_context *iscsi, int state);
/* Set callback on iscsi file descriptor on duplicating */
EXTERN void
iscsi_set_fd_dup_cb(struct iscsi_context *iscsi,
void (*cb)(struct iscsi_context *iscsi, void *opaque),
void *opaque);
#ifdef __cplusplus
}
#endif