diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-12 14:26:13 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-12 14:26:13 +0200 |
commit | 1c2e745ff2bd80b14fdf96c28b07ca34e2c16537 (patch) | |
tree | 8d3e1729e7e2d66f8fa7c5f7283fb0968df84faa /lib | |
parent | 195a029b42d34d162053d1096ae093fd3d7efb0c (diff) | |
download | abrt-1c2e745ff2bd80b14fdf96c28b07ca34e2c16537.tar.gz abrt-1c2e745ff2bd80b14fdf96c28b07ca34e2c16537.tar.xz abrt-1c2e745ff2bd80b14fdf96c28b07ca34e2c16537.zip |
fix bug 588945 - sparse core files performance hit
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Utils/copyfd.cpp | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/lib/Utils/copyfd.cpp b/lib/Utils/copyfd.cpp index fad716f2..cbcf7005 100644 --- a/lib/Utils/copyfd.cpp +++ b/lib/Utils/copyfd.cpp @@ -29,10 +29,11 @@ static const char msg_write_error[] = "write error"; static const char msg_read_error[] = "read error"; -static off_t full_fd_action(int src_fd, int dst_fd, off_t size) +static off_t full_fd_action(int src_fd, int dst_fd, off_t size, int flags = 0) { int status = -1; off_t total = 0; + int last_was_seek = 0; #if CONFIG_FEATURE_COPYBUF_KB <= 4 char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; enum { buffer_size = sizeof(buffer) }; @@ -67,6 +68,14 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); if (!rd) { /* eof - all done */ + if (last_was_seek) { + if (lseek(dst_fd, -1, SEEK_CUR) < 0 + || safe_write(dst_fd, "", 1) != 1 + ) { + perror_msg("%s", msg_write_error); + break; + } + } status = 0; break; } @@ -76,10 +85,24 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) } /* dst_fd == -1 is a fake, else... */ if (dst_fd >= 0) { - ssize_t wr = full_write(dst_fd, buffer, rd); - if (wr < rd) { - perror_msg("%s", msg_write_error); - break; + if (flags & COPYFD_SPARSE) { + ssize_t cnt = rd; + while (--cnt >= 0) + if (buffer[cnt] != 0) + goto need2write; + if (lseek(dst_fd, rd, SEEK_CUR) < 0) { + flags &= ~COPYFD_SPARSE; + goto need2write; + } + last_was_seek = 1; + } else { + need2write: + ssize_t wr = full_write(dst_fd, buffer, rd); + if (wr < rd) { + perror_msg("%s", msg_write_error); + break; + } + last_was_seek = 0; } } total += rd; @@ -101,10 +124,10 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) return status ? -1 : total; } -off_t copyfd_size(int fd1, int fd2, off_t size) +off_t copyfd_size(int fd1, int fd2, off_t size, int flags) { if (size) { - return full_fd_action(fd1, fd2, size); + return full_fd_action(fd1, fd2, size, flags); } return 0; } @@ -120,9 +143,9 @@ void copyfd_exact_size(int fd1, int fd2, off_t size) xfunc_die(); } -off_t copyfd_eof(int fd1, int fd2) +off_t copyfd_eof(int fd1, int fd2, int flags) { - return full_fd_action(fd1, fd2, 0); + return full_fd_action(fd1, fd2, 0, flags); } off_t copy_file(const char *src_name, const char *dst_name, int mode) |