[libssh2] fix very slow sftp upload to localhost

Kamil Dudka kdudka at fedoraproject.org
Wed Aug 14 16:00:31 UTC 2013


commit 68034f3fb240e170ed1c9565b369fc017178777c
Author: Kamil Dudka <kdudka at redhat.com>
Date:   Wed Aug 14 17:49:59 2013 +0200

    fix very slow sftp upload to localhost

 ...evert-window_size-explicit-adjustments-on.patch |   69 ++++++++++++++++++++
 libssh2-1.4.2-utf8.patch                           |    2 +-
 libssh2.spec                                       |    9 ++-
 3 files changed, 78 insertions(+), 2 deletions(-)
---
diff --git a/0004-partially-revert-window_size-explicit-adjustments-on.patch b/0004-partially-revert-window_size-explicit-adjustments-on.patch
new file mode 100644
index 0000000..fe7751a
--- /dev/null
+++ b/0004-partially-revert-window_size-explicit-adjustments-on.patch
@@ -0,0 +1,69 @@
+From 9e56b84c41efcaf3349f82a93c3dc854e172e5c4 Mon Sep 17 00:00:00 2001
+From: Kamil Dudka <kdudka at redhat.com>
+Date: Fri, 9 Aug 2013 16:22:08 +0200
+Subject: [PATCH 4/5] partially revert "window_size: explicit adjustments only"
+
+This partially reverts commit 03ca9020756a4e16f0294e5b35e9826ee6af2364
+in order to fix extreme slowdown when uploading to localhost via SFTP.
+
+I was able to repeat the issue on RHEL-7 on localhost only.  It did not
+occur when uploading via network and it did not occur on a RHEL-6 box
+with the same version of libssh2.
+
+The problem was that sftp_read() used a read-ahead logic to figure out
+the window_size, but sftp_packet_read() called indirectly from
+sftp_write() did not use any read-ahead logic.
+---
+ src/channel.c |   29 +++++++++++++++++++++++++++++
+ 1 files changed, 29 insertions(+), 0 deletions(-)
+
+diff --git a/src/channel.c b/src/channel.c
+index 4f41e1f..d4ffdce 100644
+--- a/src/channel.c
++++ b/src/channel.c
+@@ -1759,6 +1759,15 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
+         channel->read_state = libssh2_NB_state_created;
+     }
+ 
++    /*
++     * =============================== NOTE ===============================
++     * I know this is very ugly and not a really good use of "goto", but
++     * this case statement would be even uglier to do it any other way
++     */
++    if (channel->read_state == libssh2_NB_state_jump1) {
++        goto channel_read_window_adjust;
++    }
++
+     rc = 1; /* set to >0 to let the while loop start */
+ 
+     /* Process all pending incoming packets in all states in order to "even
+@@ -1867,6 +1876,26 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
+            more off the network again */
+         channel->read_state = libssh2_NB_state_created;
+ 
++    if(channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)) {
++        /* the window is getting too narrow, expand it! */
++
++      channel_read_window_adjust:
++        channel->read_state = libssh2_NB_state_jump1;
++        /* the actual window adjusting may not finish so we need to deal with
++           this special state here */
++        rc = _libssh2_channel_receive_window_adjust(channel,
++                                                    (LIBSSH2_CHANNEL_WINDOW_DEFAULT*60), 0, NULL);
++        if (rc)
++            return rc;
++
++        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
++                       "channel_read() filled %d adjusted %d",
++                       bytes_read, buflen);
++        /* continue in 'created' state to drain the already read packages
++           first before starting to empty the socket further */
++        channel->read_state = libssh2_NB_state_created;
++    }
++
+     return bytes_read;
+ }
+ 
+-- 
+1.7.1
+
diff --git a/libssh2-1.4.2-utf8.patch b/libssh2-1.4.2-utf8.patch
index aa1e854..9177691 100644
--- a/libssh2-1.4.2-utf8.patch
+++ b/libssh2-1.4.2-utf8.patch
@@ -3,7 +3,7 @@
 
 --- libssh2/NEWS
 +++ libssh2/NEWS
-@@ -3284,7 +3284,7 @@ Simon Josefsson (16 Nov 2009)
+@@ -3552,7 +3552,7 @@ Simon Josefsson (16 Nov 2009)
  - support arcfour128 cipher per RFC 4345
  
  Daniel Stenberg (21 Oct 2009)
diff --git a/libssh2.spec b/libssh2.spec
index 63ce2a0..c485e67 100644
--- a/libssh2.spec
+++ b/libssh2.spec
@@ -12,7 +12,7 @@
 
 Name:		libssh2
 Version:	1.4.3
-Release:	7%{?dist}
+Release:	8%{?dist}
 Summary:	A library implementing the SSH2 protocol
 Group:		System Environment/Libraries
 License:	BSD
@@ -22,6 +22,7 @@ Patch0:		libssh2-1.4.2-utf8.patch
 Patch1:		0001-sftp-seek-Don-t-flush-buffers-on-same-offset.patch
 Patch2:		0002-sftp-statvfs-Along-error-path-reset-the-correct-stat.patch
 Patch3:		0003-sftp-Add-support-for-fsync-OpenSSH-extension.patch
+Patch4:		0004-partially-revert-window_size-explicit-adjustments-on.patch
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu)
 BuildRequires:	openssl-devel
 BuildRequires:	zlib-devel
@@ -80,6 +81,9 @@ sed -i s/4711/47%{?__isa_bits}/ tests/ssh2.{c,sh}
 %patch2 -p1
 %patch3 -p1
 
+# http://thread.gmane.org/gmane.network.ssh.libssh2.devel/6428
+%patch4 -p1
+
 # Make sshd transition appropriately if building in an SELinux environment
 %if !(0%{?fedora} >= 17 || 0%{?rhel} >= 7)
 chcon $(/usr/sbin/matchpathcon -n /etc/rc.d/init.d/sshd) tests/ssh2.sh || :
@@ -146,6 +150,9 @@ rm -rf %{buildroot}
 %{_libdir}/pkgconfig/libssh2.pc
 
 %changelog
+* Wed Aug 14 2013 Kamil Dudka <kdudka at redhat.com> 1.4.3-8
+- fix very slow sftp upload to localhost
+
 * Sat Aug 03 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 1.4.3-7
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
 


More information about the scm-commits mailing list