From b48215aae095e45a366c9630045076c9b37a03c1 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 21 Jul 2009 08:10:36 +0000 Subject: [PATCH] * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Add special case for MVFS. Explain why. (fhandler_disk_file::utimens): Drop local variables lastaccess and lastwrite. Copy timestamps right into FILE_BASIC_INFORMATION structure to avoid copying them twice. --- winsup/cygwin/ChangeLog | 9 ++++++ winsup/cygwin/fhandler_disk_file.cc | 46 +++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ebe1f7275..c9696593d 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2009-07-21 Corinna Vinschen + Eric Blake + + * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Add special case + for MVFS. Explain why. + (fhandler_disk_file::utimens): Drop local variables lastaccess and + lastwrite. Copy timestamps right into FILE_BASIC_INFORMATION structure + to avoid copying them twice. + 2009-07-20 Corinna Vinschen * wincap.h (wincaps::has_always_all_codepages): New element. diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index f2dd1ea81..2baabaef3 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -846,6 +846,25 @@ fhandler_disk_file::fchmod (mode_t mode) pc |= (DWORD) FILE_ATTRIBUTE_SYSTEM; status = NtSetAttributesFile (get_handle (), pc.file_attributes ()); + /* MVFS needs a good amount of kicking to be convinced that it has to write + back metadata changes and to invalidate the cached metadata information + stored for the given handle. This method to open a second handle to + the file and write the same metadata information twice has been found + experimentally: http://cygwin.com/ml/cygwin/2009-07/msg00533.html */ + if (pc.fs_is_mvfs () && NT_SUCCESS (status) && !oret) + { + OBJECT_ATTRIBUTES attr; + HANDLE fh; + + InitializeObjectAttributes (&attr, &ro_u_empty, 0, get_handle (), NULL); + if (NT_SUCCESS (NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES, &attr, &io, + FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT))) + { + NtSetAttributesFile (fh, pc.file_attributes ()); + NtClose (fh); + } + } /* Correct NTFS security attributes have higher priority */ if (!pc.has_acls ()) { @@ -1260,7 +1279,6 @@ fhandler_disk_file::utimens (const struct timespec *tvp) int fhandler_base::utimens_fs (const struct timespec *tvp) { - LARGE_INTEGER lastaccess, lastwrite; struct timespec timeofday; struct timespec tmp[2]; bool closeit = false; @@ -1299,20 +1317,36 @@ fhandler_base::utimens_fs (const struct timespec *tvp) tmp[0] = (tvp[0].tv_nsec == UTIME_NOW) ? timeofday : tvp[0]; tmp[1] = (tvp[1].tv_nsec == UTIME_NOW) ? timeofday : tvp[1]; } - /* UTIME_OMIT is handled in timespec_to_filetime by setting FILETIME to 0. */ - timespec_to_filetime (&tmp[0], (FILETIME *) &lastaccess); - timespec_to_filetime (&tmp[1], (FILETIME *) &lastwrite); debug_printf ("incoming lastaccess %08x %08x", tmp[0].tv_sec, tmp[0].tv_nsec); IO_STATUS_BLOCK io; FILE_BASIC_INFORMATION fbi; + fbi.CreationTime.QuadPart = 0LL; - fbi.LastAccessTime = lastaccess; - fbi.LastWriteTime = lastwrite; + /* UTIME_OMIT is handled in timespec_to_filetime by setting FILETIME to 0. */ + timespec_to_filetime (&tmp[0], (LPFILETIME) &fbi.LastAccessTime); + timespec_to_filetime (&tmp[1], (LPFILETIME) &fbi.LastWriteTime); fbi.ChangeTime.QuadPart = 0LL; fbi.FileAttributes = 0; NTSTATUS status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi, FileBasicInformation); + /* For this special case for MVFS see the comment in + fhandler_disk_file::fchmod. */ + if (pc.fs_is_mvfs () && NT_SUCCESS (status) && !closeit) + { + OBJECT_ATTRIBUTES attr; + HANDLE fh; + + InitializeObjectAttributes (&attr, &ro_u_empty, 0, get_handle (), NULL); + if (NT_SUCCESS (NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES, &attr, &io, + FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT))) + { + NtSetInformationFile (fh, &io, &fbi, sizeof fbi, + FileBasicInformation); + NtClose (fh); + } + } if (closeit) close_fs (); /* Opening a directory on a 9x share from a NT machine works(!), but