[glibc/f18] Resolves: #577950 - Backport of upstream BZ #5298. Don't flush buffer for ftell. Compute offse

Patsy Franklin pfrankli at fedoraproject.org
Wed Nov 28 20:21:06 UTC 2012


commit 1e5f839b46bc25ab78a680e607e9cd966722c0af
Author: Patsy Franklin <pfrankli at redhat.com>
Date:   Wed Nov 28 15:19:48 2012 -0500

    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 deletions(-)
---
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 <pfrankli at redhat.com> - 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 <law at redhat.com> - 2.16-24
   - Add hwcaps for transactional execution on s390[x] (#804768)
 


More information about the scm-commits mailing list