diff --git a/cmds/send.c b/cmds/send.c index 006eb3cc..eaee0eac 100644 --- a/cmds/send.c +++ b/cmds/send.c @@ -246,6 +246,10 @@ static int do_send(struct btrfs_send *send, u64 parent_root_id, void *t_err = NULL; int subvol_fd = -1; int pipefd[2] = {-1, -1}; + struct stat out_fd_stat; + bool is_sock = false; + + memset(&io_send, 0, sizeof(io_send)); subvol_fd = openat(send->mnt_fd, subvol, O_RDONLY | O_NOATIME); if (subvol_fd < 0) { @@ -254,24 +258,35 @@ static int do_send(struct btrfs_send *send, u64 parent_root_id, goto out; } - ret = pipe(pipefd); - if (ret < 0) { + if (fstat(send->dump_fd, &out_fd_stat) < 0) { ret = -errno; - error("pipe failed: %m"); + error("fail to get out fd's stat: %s", strerror(errno)); goto out; } - memset(&io_send, 0, sizeof(io_send)); - io_send.send_fd = pipefd[1]; - send->send_fd = pipefd[0]; + is_sock = (out_fd_stat.st_mode & S_IFMT) == S_IFSOCK; - if (!ret) - ret = pthread_create(&t_read, NULL, read_sent_data, send); - if (ret) { - ret = -ret; - errno = -ret; - error("thread setup failed: %m"); - goto out; + if (!is_sock) { + ret = pipe(pipefd); + if (ret < 0) { + ret = -errno; + error("pipe failed: %m"); + goto out; + } + io_send.send_fd = pipefd[1]; + send->send_fd = pipefd[0]; + + if (!ret) + ret = pthread_create(&t_read, NULL, read_sent_data, + send); + if (ret) { + ret = -ret; + errno = -ret; + error("thread setup failed: %m"); + goto out; + } + } else { + io_send.send_fd = send->dump_fd; } io_send.flags = flags; @@ -294,24 +309,26 @@ static int do_send(struct btrfs_send *send, u64 parent_root_id, if (bconf.verbose > 1) fprintf(stderr, "BTRFS_IOC_SEND returned %d\n", ret); - if (bconf.verbose > 1) - fprintf(stderr, "joining genl thread\n"); + if (!is_sock) { + if (bconf.verbose > 1) + fprintf(stderr, "joining genl thread\n"); - close(pipefd[1]); - pipefd[1] = -1; + close(pipefd[1]); + pipefd[1] = -1; - ret = pthread_join(t_read, &t_err); - if (ret) { - ret = -ret; - errno = -ret; - error("pthread_join failed: %m"); - goto out; - } - if (t_err) { - ret = (long int)t_err; - error("failed to process send stream, ret=%ld (%s)", - (long int)t_err, strerror(-ret)); - goto out; + ret = pthread_join(t_read, &t_err); + if (ret) { + ret = -ret; + errno = -ret; + error("pthread_join failed: %m"); + goto out; + } + if (t_err) { + ret = (long int)t_err; + error("failed to process send stream, ret=%ld (%s)", + (long int)t_err, strerror(-ret)); + goto out; + } } ret = 0; diff --git a/common/ktls.c b/common/ktls.c index a4d670e3..5794916d 100644 --- a/common/ktls.c +++ b/common/ktls.c @@ -662,6 +662,36 @@ cleanup: return EXIT_FAILURE; } +static int ktls_enlarge_buffer(int sock, bool is_sender) +{ + FILE *wmem = NULL; + int min_buf = 0, dft_buf = 0, max_buf = 0; + int ret = EXIT_FAILURE; + + if (sock < 0) + goto cleanup; + + wmem = fopen("/proc/sys/net/ipv4/tcp_wmem", "r"); + if (!wmem) + goto cleanup; + + if (fscanf(wmem, "%d%d%d", &min_buf, &dft_buf, &max_buf) != 3) { + error("cannot get buffer size"); + goto cleanup; + } + + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&min_buf, + sizeof(min_buf)); + + ret = EXIT_SUCCESS; + +cleanup: + if (wmem) + fclose(wmem); + + return ret; +} + int ktls_create_sock_oneshot(struct ktls_session *session, const char *host, const char *port) { @@ -691,6 +721,8 @@ int ktls_create_sock_oneshot(struct ktls_session *session, const char *host, sock = accepted_sock; } + ktls_enlarge_buffer(sock, is_sender); + if (ktls_handshake_tls(session, sock)) goto cleanup;