On 05/12/11 05:41, Paul Eggert wrote: > On 05/11/11 01:49, Markus Duft wrote: >> fsync(fd) before setting the timestamp helps, and i have a 1.26 patch >> (attached), >> for now limited to interix only, although i saw it on linux too. > > Can you describe the GNU/Linux scenario? That would be a serious > file system bug. There are known bugs when running glibc compiled > against newer headers but on older Linux kernels, but tar should > work around those bugs; see gnu/futimens.c. Why isn't that > happening for you?
sad enough, i can't; it did happen one or two times since 1.25 on linux when handling large archives when the machine was under high load... i have a colleague @gentoo.org which had problems on NFS. i skimmed through gnulibs fdutimensat.c, and there is a fsync() call for NFS explicitly, which should avoid this problem. was it there with 1.25...? checking ... hm, yes, it was. strange, maybe HAVE_BUGGY_NFS_TIME_STAMPS should have been defined, when it wasnt. > > Which system call is being used in Interix? Is it futimens, > or utimensat, or what? Sorry, I've lost context. uhm ... i start to see the problem here :) on interix, there is no system call to set the modification time on an open handle. it is rather set using utime[s]() (which one doesn't matter for this, i guess - newer interix have utimes(), but don't expose it through headers, and older ones don't have it). hm. i tried to do nearly the same fix as for the NFS timestamps, and i realized that the fd in fdutimensat is 4, whereas in utimens, which is then called from somewhere in there, it is -1, so i can't do a fsync() in there (maybe the reason why NFS sometimes didn't work, too?). i now have a new patch (attached), which syncs in fdutimensat when futimens failed, and the fallback to utimensat is used. this could have possibly been a problem on other filesystems too, right? (provided the system is dump enough to not have any futime* calls, which essestially should boil down to interix, and maybe one or two others ...? ;)). i cc'ed gnulib folks, to hear what they have to say to my patch... hey folks *wink* :) > > The workaround you sent doesn't look quite right. Surely the fix > belongs in the implementation of fdutimensat, not in just one of its > callers. And there must be something faster than calling fsync. > Did you try the fix that Eric Blake suggested in > <http://lists.gnu.org/archive/html/bug-tar/2011-02/msg00004.html>? no, and i actually cant, as there is no system call to set timestamps on open fd's, and i think the problem actually boils down to this fact.. > > Finally, to answer your earlier question, it's clearly a filesystem > bug. I could cite POSIX chapter and verse on this, but I'd rather > use a common sense argument: what's the point of having a system call > like futimens if closing the file erases the work that futimens does? > heh, right, and i don't have futimens, so.... ;) regards, markus
diff -ru tar-1.26.orig/gnu/fdutimensat.c tar-1.26/gnu/fdutimensat.c --- tar-1.26.orig/gnu/fdutimensat.c 2011-04-28 10:03:22 +0200 +++ tar-1.26/gnu/fdutimensat.c 2011-05-12 08:41:47 +0200 @@ -48,8 +48,15 @@ int result = 1; if (0 <= fd) result = futimens (fd, ts); - if (file && (fd < 0 || (result == -1 && errno == ENOSYS))) + if (file && (fd < 0 || (result == -1 && errno == ENOSYS))) { + + /* need to sync here, as changes may not have been flushed to the + * disk, and the fd is lost from here on. */ + if (fd >= 0) + fsync (fd); + result = utimensat (dir, file, ts, atflag); + } if (result == 1) { errno = EBADF;