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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user