From 7fc7206b03a7f54b23904373ad397f693a5fae2a Mon Sep 17 00:00:00 2001 From: Pádraig Brady
Date: Wed, 9 Nov 2016 17:23:04 +0000 Subject: tail: avoid outputting repeated data with remote files * 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 | 4 ++++ src/tail.c | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 7780d5288..c223b562d 100644 --- 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] diff --git a/src/tail.c b/src/tail.c index 96982ed5b..b3018d526 100644 --- a/src/tail.c +++ b/src/tail.c @@ -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; } -- cgit v1.2.3-70-g09d2