From 1e5f839b46bc25ab78a680e607e9cd966722c0af Mon Sep 17 00:00:00 2001 From: Patsy Franklin Date: Wed, 28 Nov 2012 15:19:48 -0500 Subject: [PATCH] Resolves: #577950 - Backport of upstream BZ #5298. Don't flush buffer for ftell. Compute offsets from write pointers instead. (#577950) --- glibc-rh577950.patch | 194 +++++++++++++++++++++++++++++++++++++++++++ glibc.spec | 10 ++- 2 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 glibc-rh577950.patch diff --git a/glibc-rh577950.patch b/glibc-rh577950.patch new file mode 100644 index 0000000..7bd6e78 --- /dev/null +++ b/glibc-rh577950.patch @@ -0,0 +1,194 @@ +diff -Nrup a/libio/fileops.c b/libio/fileops.c +--- a/libio/fileops.c 2012-06-30 15:12:34.000000000 -0400 ++++ b/libio/fileops.c 2012-11-28 12:27:00.297009479 -0500 +@@ -978,6 +978,9 @@ _IO_new_file_seekoff (fp, offset, dir, m + int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end + && fp->_IO_write_base == fp->_IO_write_ptr); + ++ bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base ++ || _IO_in_put_mode (fp)); ++ + if (mode == 0) + dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + +@@ -988,10 +991,8 @@ _IO_new_file_seekoff (fp, offset, dir, m + which assumes file_ptr() is eGptr. Anyway, since we probably + end up flushing when we close(), it doesn't make much difference.) + FIXME: simulate mem-papped files. */ +- +- if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp)) +- if (_IO_switch_to_get_mode (fp)) +- return EOF; ++ else if (was_writing && _IO_switch_to_get_mode (fp)) ++ return EOF; + + if (fp->_IO_buf_base == NULL) + { +@@ -1010,7 +1011,17 @@ _IO_new_file_seekoff (fp, offset, dir, m + { + case _IO_seek_cur: + /* Adjust for read-ahead (bytes is buffer). */ +- offset -= fp->_IO_read_end - fp->_IO_read_ptr; ++ if (mode != 0 || !was_writing) ++ offset -= fp->_IO_read_end - fp->_IO_read_ptr; ++ else ++ { ++ /* _IO_read_end coincides with fp._offset, so the actual file position ++ is fp._offset - (_IO_read_end - new_write_ptr). This is fine ++ even if fp._offset is not set, since fp->_IO_read_end is then at ++ _IO_buf_base and this adjustment is for unbuffered output. */ ++ offset -= fp->_IO_read_end - fp->_IO_write_ptr; ++ } ++ + if (fp->_offset == _IO_pos_BAD) + { + if (mode != 0) +diff -Nrup a/libio/wfileops.c b/libio/wfileops.c +--- a/libio/wfileops.c 2012-11-28 10:47:08.906188748 -0500 ++++ b/libio/wfileops.c 2012-11-28 12:34:06.285439028 -0500 +@@ -611,6 +611,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode + && (fp->_wide_data->_IO_write_base + == fp->_wide_data->_IO_write_ptr)); + ++ bool was_writing = ((fp->_wide_data->_IO_write_ptr ++ > fp->_wide_data->_IO_write_base) ++ || _IO_in_put_mode (fp)); ++ + if (mode == 0) + { + /* XXX For wide stream with backup store it is not very +@@ -642,11 +646,8 @@ _IO_wfile_seekoff (fp, offset, dir, mode + which assumes file_ptr() is eGptr. Anyway, since we probably + end up flushing when we close(), it doesn't make much difference.) + FIXME: simulate mem-mapped files. */ +- +- if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base +- || _IO_in_put_mode (fp)) +- if (_IO_switch_to_wget_mode (fp)) +- return WEOF; ++ else if (was_writing && _IO_switch_to_wget_mode (fp)) ++ return WEOF; + + if (fp->_wide_data->_IO_buf_base == NULL) + { +@@ -677,29 +678,104 @@ _IO_wfile_seekoff (fp, offset, dir, mode + cv = fp->_codecvt; + clen = (*cv->__codecvt_do_encoding) (cv); + +- if (clen > 0) ++ if (mode != 0 || !was_writing) + { +- offset -= (fp->_wide_data->_IO_read_end +- - fp->_wide_data->_IO_read_ptr) * clen; +- /* Adjust by readahead in external buffer. */ +- offset -= fp->_IO_read_end - fp->_IO_read_ptr; ++ if (clen > 0) ++ { ++ offset -= (fp->_wide_data->_IO_read_end ++ - fp->_wide_data->_IO_read_ptr) * clen; ++ /* Adjust by readahead in external buffer. */ ++ offset -= fp->_IO_read_end - fp->_IO_read_ptr; ++ } ++ else ++ { ++ int nread; ++ ++ flushed: ++ delta = (fp->_wide_data->_IO_read_ptr ++ - fp->_wide_data->_IO_read_base); ++ fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; ++ nread = (*cv->__codecvt_do_length) (cv, ++ &fp->_wide_data->_IO_state, ++ fp->_IO_read_base, ++ fp->_IO_read_end, delta); ++ fp->_IO_read_ptr = fp->_IO_read_base + nread; ++ fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; ++ offset -= fp->_IO_read_end - fp->_IO_read_base - nread; ++ } + } + else + { +- int nread; ++ char *new_write_ptr = fp->_IO_write_ptr; + +- delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base; +- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; +- nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, +- fp->_IO_read_base, +- fp->_IO_read_end, delta); +- fp->_IO_read_ptr = fp->_IO_read_base + nread; +- fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; +- offset -= fp->_IO_read_end - fp->_IO_read_base - nread; ++ if (clen > 0) ++ offset += (fp->_wide_data->_IO_write_ptr ++ - fp->_wide_data->_IO_write_base) / clen; ++ else ++ { ++ enum __codecvt_result status; ++ delta = (fp->_wide_data->_IO_write_ptr ++ - fp->_wide_data->_IO_write_base); ++ const wchar_t *write_base = fp->_wide_data->_IO_write_base; ++ ++ /* FIXME: This actually ends up in two iterations of conversion, ++ one here and the next when the buffer actually gets flushed. ++ It may be possible to optimize this in future so that ++ wdo_write identifies already converted content and does not ++ redo it. In any case, this is much better than having to ++ flush buffers for every ftell. */ ++ do ++ { ++ /* Ugh, no point trying to avoid the flush. Just do it ++ and go back to how it was with the read mode. */ ++ if (delta > 0 && new_write_ptr == fp->_IO_buf_end) ++ { ++ if (_IO_switch_to_wget_mode (fp)) ++ return WEOF; ++ goto flushed; ++ } ++ ++ const wchar_t *new_wbase = fp->_wide_data->_IO_write_base; ++ fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; ++ status = (*cv->__codecvt_do_out) (cv, ++ &fp->_wide_data->_IO_state, ++ write_base, ++ write_base + delta, ++ &new_wbase, ++ new_write_ptr, ++ fp->_IO_buf_end, ++ &new_write_ptr); ++ ++ delta -= new_wbase - write_base; ++ ++ /* If there was an error, then return WEOF. ++ TODO: set buffer state. */ ++ if (__builtin_expect (status == __codecvt_error, 0)) ++ return WEOF; ++ } ++ while (delta > 0); ++ } ++ ++ /* _IO_read_end coincides with fp._offset, so the actual file position ++ is fp._offset - (_IO_read_end - new_write_ptr). This is fine ++ even if fp._offset is not set, since fp->_IO_read_end is then at ++ _IO_buf_base and this adjustment is for unbuffered output. */ ++ offset -= fp->_IO_read_end - new_write_ptr; + } + + if (fp->_offset == _IO_pos_BAD) +- goto dumb; ++ { ++ if (mode != 0) ++ goto dumb; ++ else ++ { ++ result = _IO_SYSSEEK (fp, 0, dir); ++ if (result == EOF) ++ return result; ++ fp->_offset = result; ++ } ++ } ++ + /* Make offset absolute, assuming current pointer is file_ptr(). */ + offset += fp->_offset; + +Binary files a/libio/.wfileops.c.swp and b/libio/.wfileops.c.swp differ diff --git a/glibc.spec b/glibc.spec index 2a443fb..cda5676 100644 --- a/glibc.spec +++ b/glibc.spec @@ -28,7 +28,7 @@ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 24%{?dist} +Release: 25%{?dist} # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -188,6 +188,9 @@ Patch2039: %{name}-rh854337.patch # Upstream BZ 14583 Patch2040: %{name}-rh857236.patch +# Upstream BZ 5298 +Patch2041: %{name}-rh577950.patch + Patch2042: %{name}-rh864820.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -454,6 +457,7 @@ rm -rf %{glibcportsdir} %patch1038 -p1 %patch2039 -p1 %patch2040 -p1 +%patch2041 -p1 %patch1041 -p1 %patch2042 -p1 %patch1042 -p1 @@ -1269,6 +1273,10 @@ rm -f *.filelist* %endif %changelog +* Wed Nov 28 2012 Patsy Franklin - 2.16-25 + - Backport of upstream BZ #5298. Don't flush buffer for ftell. + Compute offsets from write pointers instead. (#577950) + * Thu Nov 8 2012 Jeff Law - 2.16-24 - Add hwcaps for transactional execution on s390[x] (#804768)