]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
tail: avoid outputting repeated data with remote files
authorPádraig Brady <P@draigBrady.com>
Wed, 9 Nov 2016 17:23:04 +0000 (17:23 +0000)
committerPádraig Brady <P@draigBrady.com>
Wed, 9 Nov 2016 19:36:42 +0000 (19:36 +0000)
* src/tail.c (tail_forever): Only read up to st_size on network
file systems to avoid the issue with a stale attribute cache
returning a smaller st_size than we have already read().
The was seen with glusterfs at least and caused the complete
file to be repeatedly output due to assuming the file was
truncated in this case.
* NEWS: Mention the fix.

NEWS
src/tail.c

diff --git a/NEWS b/NEWS
index 7780d528820826a9c9f549b24196c815dd3ba06d..c223b562d036558ec7e6bc350837793564a484e8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -55,6 +55,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   to read from stdin.  Previously it behaved as if --retry was specified.
   [This bug was present in "the beginning".]
 
+  tail -f 'remote file' will now avoid outputting repeated data on network
+  file systems that misreport file sizes through stale metadata.
+  [This bug was present in "the beginning" but exacerbated in coreutils-8.24]
+
   yes now handles short writes, rather than assuming all writes complete.
   [bug introduced in coreutils-8.24]
 
index 96982ed5b72e7b5a765596bcb11234a33de8fc2a..b3018d526d0f5d03a533544d25effb1a9addc273 100644 (file)
@@ -1220,9 +1220,19 @@ tail_forever (struct File_spec *f, size_t n_files, double sleep_interval)
                 }
             }
 
-          bytes_read = dump_remainder (name, fd,
-                                       (f[i].blocking
-                                        ? COPY_A_BUFFER : COPY_TO_EOF));
+          /* Don't read more than st_size on networked file systems
+             because it was seen on glusterfs at least, that st_size
+             may be smaller than the data read on a _subsequent_ stat call.  */
+          uintmax_t bytes_to_read;
+          if (f[i].blocking)
+            bytes_to_read = COPY_A_BUFFER;
+          else if (S_ISREG (mode) && f[i].remote)
+            bytes_to_read = stats.st_size - f[i].size;
+          else
+            bytes_to_read = COPY_TO_EOF;
+
+          bytes_read = dump_remainder (name, fd, bytes_to_read);
+
           any_input |= (bytes_read != 0);
           f[i].size += bytes_read;
         }