summaryrefslogtreecommitdiff
path: root/src/w32.c
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2010-05-22 22:09:51 +0300
committerEli Zaretskii <eliz@gnu.org>2010-05-22 22:09:51 +0300
commit6e83d8007b844f1d0d68ad235015a154da8050c4 (patch)
tree594d2bbe15616629fbf0336a92df55d3ad4bcdd8 /src/w32.c
parent9d5c6f0e5f80efa974c331c48304e353887c4632 (diff)
downloademacs-6e83d8007b844f1d0d68ad235015a154da8050c4.tar.gz
Fix bug #6237.
w32.c (sys_write): Break writes into chunks smaller than 32MB.
Diffstat (limited to 'src/w32.c')
-rw-r--r--src/w32.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/w32.c b/src/w32.c
index 0f2d8b54e6b..0560ce4a6b8 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -5700,7 +5700,34 @@ sys_write (int fd, const void * buffer, unsigned int count)
}
else
#endif
- nchars = _write (fd, buffer, count);
+ {
+ /* Some networked filesystems don't like too large writes, so
+ break them into smaller chunks. See the Comments section of
+ the MSDN documentation of WriteFile for details behind the
+ choice of the value of CHUNK below. See also the thread
+ http://thread.gmane.org/gmane.comp.version-control.git/145294
+ in the git mailing list. */
+ const unsigned char *p = buffer;
+ const unsigned chunk = 30 * 1024 * 1024;
+
+ nchars = 0;
+ while (count > 0)
+ {
+ unsigned this_chunk = count < chunk ? count : chunk;
+ int n = _write (fd, p, this_chunk);
+
+ nchars += n;
+ if (n < 0)
+ {
+ nchars = n;
+ break;
+ }
+ else if (n < this_chunk)
+ break;
+ count -= n;
+ p += n;
+ }
+ }
return nchars;
}