This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: MVFS results


Corinna Vinschen <corinna-cygwin <at> cygwin.com> writes:

> > Or maybe this is a case where we need a FlushFileBuffer call during the 
> > utimens_fs after all, in addition to closing the duplicate descriptor, so 
that 
> > the original handle no longer has any state that needs flushing which might 
> > inadvertently change timestamps.
> 
> That should be handled by the filesystem, in theory.

Indeed, procmon shows that the MVFS system is calling FlushFileBuffers to the 
backing store already, so that makes no difference.

> The easiest solution is probably not to use fchmod on MVFS, but to do
> the same trick in fchmod as in utimens:

SUCCESS!  The following patch works for both read-only and writeable files.  
Doing the work on the original handle is not enough - it has to be flushed to 
disk so as not to be lost by later state changes.  And doing the work on the 
duplicate is not enough, since based on the procmon output, it looks like MVFS 
caches information per handle, and with no reason to invalidate that cache, it 
will just overwrite the disk state on close.  But the combination of working on 
the duplicate handle to flush the change to disk, followed by repeating the 
action on the original handle, is enough to force MVFS to realize that we meant 
business.  And BOTH utimens and fchmod need this treatment (utimens alone fixed 
the writable file case, but not the read-only case).

No ChangeLog entry from me, and remember that you did the bulk of the work (I 
just did the testing).  And it still needs a good comment why we go to all the 
trouble on MVFS of doing the work on a duplicate handle first, only to repeat 
it on the original handle.


diff --git a/winsup/cygwin/fhandler_disk_file.cc 
b/winsup/cygwin/fhandler_disk_file.cc
index f2dd1ea..9ebf97f 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -779,7 +779,7 @@ fhandler_disk_file::fchmod (mode_t mode)
   extern int chmod_device (path_conv& pc, mode_t mode);
   int res = -1;
   int oret = 0;
-  NTSTATUS status;
+  NTSTATUS status = STATUS_SUCCESS;
   IO_STATUS_BLOCK io;

   if (pc.is_fs_special ())
@@ -845,7 +845,23 @@ fhandler_disk_file::fchmod (mode_t mode)
   if (S_ISSOCK (mode))
     pc |= (DWORD) FILE_ATTRIBUTE_SYSTEM;

-  status = NtSetAttributesFile (get_handle (), pc.file_attributes ());
+  if (pc.fs_is_mvfs () && !oret)
+    {
+      OBJECT_ATTRIBUTES attr;
+      HANDLE fh;
+
+      InitializeObjectAttributes (&attr, &ro_u_empty, pc.objcaseinsensitive (),
+				  get_handle (), NULL);
+      status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES, &attr, &io,
+			   FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
+      if (NT_SUCCESS (status))
+	{
+	  NtSetAttributesFile (fh, pc.file_attributes ());
+	  NtClose (fh);
+	}
+    }
+  if (NT_SUCCESS (status))
+    status = NtSetAttributesFile (get_handle (), pc.file_attributes ());
   /* Correct NTFS security attributes have higher priority */
   if (!pc.has_acls ())
     {
@@ -1306,13 +1322,31 @@ fhandler_base::utimens_fs (const struct timespec *tvp)

   IO_STATUS_BLOCK io;
   FILE_BASIC_INFORMATION fbi;
+  NTSTATUS status = STATUS_SUCCESS;
   fbi.CreationTime.QuadPart = 0LL;
   fbi.LastAccessTime = lastaccess;
   fbi.LastWriteTime = lastwrite;
   fbi.ChangeTime.QuadPart = 0LL;
   fbi.FileAttributes = 0;
-  NTSTATUS status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi,
-					  FileBasicInformation);
+  if (pc.fs_is_mvfs () && !closeit)
+    {
+      OBJECT_ATTRIBUTES attr;
+      HANDLE fh;
+
+      InitializeObjectAttributes (&attr, &ro_u_empty, pc.objcaseinsensitive (),
+				  get_handle (), NULL);
+      status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES, &attr, &io,
+			   FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
+      if (NT_SUCCESS (status))
+	{
+	  NtSetInformationFile (fh, &io, &fbi, sizeof fbi,
+				FileBasicInformation);
+	  NtClose (fh);
+	}
+    }
+  if (NT_SUCCESS (status))
+    status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi,
+				   FileBasicInformation);
   if (closeit)
     close_fs ();
   /* Opening a directory on a 9x share from a NT machine works(!), but
-- 
1.6.1.2





--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]