Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: reserve the fd on reconnect #432

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tianrenz2
Copy link

On reconnect case, the iscsi_tcp_connect tries to reuse the fd number of old_iscsi. However, this fd could have been already closed in previous iscsi_tcp_disconnect if iscsi->fd == iscsi->old_iscsi->fd and the fd number might have been allocated to some other caller, in this case the fd reuse in iscsi_tcp_connect is not safe anymore.

Solve this by not closing the fd if iscsi and old_iscsi share the same fd on reconnect to "really" reserve this fd number.

On reconnect case, the iscsi_tcp_connect tries to reuse
the fd number of old_iscsi. However, this fd could have been
already closed in previous iscsi_tcp_disconnect if
iscsi->fd == iscsi->old_iscsi->fd and the fd number
might have been allocated to some other caller, in this
case the fd reuse in iscsi_tcp_connect is not safe anymore.

Solve this by not closing the fd if iscsi and old_iscsi
share the same fd on reconnect to "really" reserve this
fd number.

Signed-off-by: Tianren Zhang <[email protected]>
@tianrenz2
Copy link
Author

tianrenz2 commented Nov 22, 2024

Here is a script below that could quickly reproduce this issue, when you see any socket connect error output, then it's likely the bug happens, replace xxxxxxx based on your environment :)

Another possible prerequisite: on each reconnect, the iscsi target should return SCSI_STATUS_REDIRECT on the login thus invoke the second connection establishment.

#include <iscsi/iscsi.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>


// Function executed by the iSCSI thread
void *iscsi_thread(void *arg) {
	struct iscsi_context *iscsi;
    char *target = "xxxxxxx";
    char *initiator = "xxxxxxxx";
    struct iscsi_url *iscsi_url;
    iscsi = iscsi_create_context(initiator);

    iscsi_url = iscsi_parse_full_url(iscsi, "xxxxxxx");

    iscsi_set_targetname(iscsi, iscsi_url->target);
    iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
    iscsi_set_timeout(iscsi, 5);

    iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun);

    while (1) {
        iscsi_reconnect_sync(iscsi);
    }
    return NULL;
}

// Function executed by the open file thread
void *file_thread(void *arg) {
    while (1) {
        int fd = open("xxxxxxxxx", O_CREAT | O_RDWR, 0644);
        if (fd == -1) {
            perror("[Thread 2] Error opening file");
        } else {
            // printf("[Thread 2] File opened successfully (fd: %d)\n", fd);
            close(fd);
        }
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    // Create iSCSI reconnect thread
    if (pthread_create(&thread1, NULL, iscsi_thread, NULL) != 0) {
        perror("Failed to create iSCSI thread");
        return 1;
    }

    // Create file opening thread
    if (pthread_create(&thread2, NULL, file_thread, NULL) != 0) {
        perror("Failed to create file thread");
        return 1;
    }

    // Wait for threads to finish (infinite loop in this case)
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant