Daemonize before forking in NFS proxy to fix OSD RDMA support (fix #107)

This commit is contained in:
Vitaliy Filippov
2025-11-09 01:07:11 +03:00
parent 65872f5d0e
commit d6b8d921d6
2 changed files with 38 additions and 15 deletions
+36 -14
View File
@@ -276,6 +276,19 @@ void nfs_proxy_t::run(json11::Json cfg)
} }
// Check default pool // Check default pool
check_default_pool(); check_default_pool();
// Daemonize before initializing messenger and RDMA because otherwise RDMA doesn't survive fork()
bool bg = cfg["foreground"].is_null() && cfg["cmd"].is_null();
int notifyfd[2] = { -1, -1 };
if (bg)
{
if (socketpair(AF_UNIX, SOCK_STREAM, 0, notifyfd) < 0)
{
perror("socketpair");
exit(1);
}
daemonize_fork(notifyfd);
close(notifyfd[0]);
}
// Init VitastorFS after starting client because it depends on loaded inode configuration // Init VitastorFS after starting client because it depends on loaded inode configuration
if (fsname != "") if (fsname != "")
{ {
@@ -294,6 +307,13 @@ void nfs_proxy_t::run(json11::Json cfg)
{ {
kvfs->upgrade_db([this](int res) { finished = true; }); kvfs->upgrade_db([this](int res) { finished = true; });
} }
if (bg)
{
daemonize_reopen_stdio();
int ok = 0;
(void)write(notifyfd[1], &ok, sizeof(ok));
close(notifyfd[1]);
}
while (!finished) while (!finished)
{ {
ringloop->loop(); ringloop->loop();
@@ -409,10 +429,6 @@ void nfs_proxy_t::run_server(json11::Json cfg)
{ {
mount_fs(); mount_fs();
} }
if (cfg["foreground"].is_null())
{
daemonize();
}
if (pidfile != "") if (pidfile != "")
{ {
write_pid(); write_pid();
@@ -699,7 +715,8 @@ void nfs_client_t::handle_read(int result)
return; return;
if (result <= 0 && result != -EAGAIN && result != -EINTR && result != -ECANCELED) if (result <= 0 && result != -EAGAIN && result != -EINTR && result != -ECANCELED)
{ {
printf("Failed read from client %d: %d (%s)\n", nfs_fd, result, strerror(-result)); if (result != 0)
printf("Failed read from client %d: %d (%s)\n", nfs_fd, result, strerror(-result));
stop(); stop();
return; return;
} }
@@ -1224,26 +1241,31 @@ void nfs_client_t::free_or_rdma(rpc_op_t *rop, void *buf)
#endif #endif
} }
void nfs_proxy_t::daemonize() void nfs_proxy_t::daemonize_fork(int *notifyfd)
{ {
// Stop all clients because client I/O sometimes breaks during daemonize
// I.e. the new process stops receiving events on the old FD
// It doesn't happen if we call sleep(1) here, but we don't want to call sleep(1)...
for (auto & cli: rpc_clients)
cli->stop();
if (fork()) if (fork())
exit(0); {
// Parent - check status
close(notifyfd[1]);
int child_errno = 1;
(void)read(notifyfd[0], &child_errno, sizeof(child_errno));
exit(child_errno);
}
setsid(); setsid();
if (fork()) if (fork())
exit(0); exit(0);
if (chdir("/") != 0) }
fprintf(stderr, "Warning: Failed to chdir into /\n");
void nfs_proxy_t::daemonize_reopen_stdio()
{
close(0); close(0);
close(1); close(1);
close(2); close(2);
open("/dev/null", O_RDONLY); open("/dev/null", O_RDONLY);
open(logfile.c_str(), O_WRONLY|O_APPEND|O_CREAT, 0666); open(logfile.c_str(), O_WRONLY|O_APPEND|O_CREAT, 0666);
open(logfile.c_str(), O_WRONLY|O_APPEND|O_CREAT, 0666); open(logfile.c_str(), O_WRONLY|O_APPEND|O_CREAT, 0666);
if (chdir("/") != 0)
fprintf(stderr, "Warning: Failed to chdir into /\n");
} }
void nfs_proxy_t::write_pid() void nfs_proxy_t::write_pid()
+2 -1
View File
@@ -83,7 +83,8 @@ public:
void check_default_pool(); void check_default_pool();
nfs_client_t* create_client(); nfs_client_t* create_client();
void do_accept(int listen_fd); void do_accept(int listen_fd);
void daemonize(); void daemonize_fork(int *notifyfd);
void daemonize_reopen_stdio();
void write_pid(); void write_pid();
void mount_fs(); void mount_fs();
void check_already_mounted(); void check_already_mounted();