Parcourir la source

Removed global IoPageCacheTreeLock.

Page cache trees are now protected by the file object lock, which is held
shared for read access to the tree or exclusive for tree modifications.
Evan Green il y a 8 ans
Parent
commit
5aeeeea665
14 fichiers modifiés avec 527 ajouts et 656 suppressions
  1. 2 2
      .gitconfig
  2. 24 0
      inc/minoca/ke.h
  3. 67 19
      kernel/io/cachedio.c
  4. 136 154
      kernel/io/fileobj.c
  5. 1 1
      kernel/io/filesys.c
  6. 21 8
      kernel/io/iobase.c
  7. 41 37
      kernel/io/iop.h
  8. 175 426
      kernel/io/pagecach.c
  9. 3 3
      kernel/io/path.c
  10. 1 1
      kernel/io/pipe.c
  11. 2 2
      kernel/io/pty.c
  12. 2 2
      kernel/io/shmemobj.c
  13. 1 1
      kernel/io/socket.c
  14. 51 0
      kernel/ke/lock.c

+ 2 - 2
.gitconfig

@@ -1,6 +1,6 @@
 ##
-## To activate this configuration (recommended), add the following to your
-## .git/config file, removing the # characters.
+## To activate this configuration (recommended), add the following include
+## section to your .git/config file (without the # characters).
 ##
 ## [include]
 ##     path = ../.gitconfig

+ 24 - 0
inc/minoca/ke.h

@@ -1436,6 +1436,30 @@ Return Value:
 
 --*/
 
+KERNEL_API
+VOID
+KeSharedExclusiveLockConvertToExclusive (
+    PSHARED_EXCLUSIVE_LOCK SharedExclusiveLock
+    );
+
+/*++
+
+Routine Description:
+
+    This routine converts a lock that the caller holds shared into one that
+    the caller holds exclusive. This routine will most likely fully release
+    and reacquire the lock.
+
+Arguments:
+
+    SharedExclusiveLock - Supplies a pointer to the shared-exclusive lock.
+
+Return Value:
+
+    None.
+
+--*/
+
 KERNEL_API
 BOOL
 KeIsSharedExclusiveLockHeld (

+ 67 - 19
kernel/io/cachedio.c

@@ -97,7 +97,8 @@ typedef struct _IO_WRITE_CONTEXT {
 KSTATUS
 IopPerformCachedRead (
     PFILE_OBJECT FileObject,
-    PIO_CONTEXT IoContext
+    PIO_CONTEXT IoContext,
+    PBOOL LockHeldExclusive
     );
 
 KSTATUS
@@ -196,10 +197,12 @@ Return Value:
 
     PFILE_OBJECT FileObject;
     UINTN FlushCount;
-    BOOL Modified;
+    BOOL LockHeldExclusive;
     ULONGLONG OriginalOffset;
     ULONG PageShift;
+    ULONGLONG StartOffset;
     KSTATUS Status;
+    FILE_OBJECT_TIME_TYPE TimeType;
 
     FileObject = Handle->PathPoint.PathEntry->FileObject;
 
@@ -207,13 +210,16 @@ Return Value:
     ASSERT((IoContext->Flags & IO_FLAG_NO_ALLOCATE) == 0);
     ASSERT(IO_IS_CACHEABLE_TYPE(FileObject->Properties.Type) != FALSE);
 
+    OriginalOffset = IoContext->Offset;
+    StartOffset = OriginalOffset;
+
     //
-    // Get the current offset if an offset is not provided.
+    // Assuming this call is going to generate more pages, ask this thread to
+    // do some trimming if things are too big.
     //
 
-    OriginalOffset = IoContext->Offset;
-    if (OriginalOffset == IO_OFFSET_NONE) {
-        IoContext->Offset = RtlAtomicOr64(&(Handle->CurrentOffset), 0);
+    if ((IoContext->Flags & IO_FLAG_FS_DATA) == 0) {
+        IopTrimPageCache();
     }
 
     //
@@ -253,6 +259,11 @@ Return Value:
         }
 
         KeAcquireSharedExclusiveLockExclusive(FileObject->Lock);
+        LockHeldExclusive = TRUE;
+        if (OriginalOffset == IO_OFFSET_NONE) {
+            IoContext->Offset = RtlAtomicOr64(&(Handle->CurrentOffset), 0);
+            StartOffset = IoContext->Offset;
+        }
 
         //
         // In append mode, set the offset to the end of the file.
@@ -272,8 +283,7 @@ Return Value:
                                               TRUE);
         }
 
-        KeReleaseSharedExclusiveLockExclusive(FileObject->Lock);
-        Modified = TRUE;
+        TimeType = FileObjectModifiedTime;
 
     //
     // Read operations acquire the file object's lock in shared mode and then
@@ -282,8 +292,16 @@ Return Value:
 
     } else {
         KeAcquireSharedExclusiveLockShared(FileObject->Lock);
+        if (OriginalOffset == IO_OFFSET_NONE) {
+            IoContext->Offset = RtlAtomicOr64(&(Handle->CurrentOffset), 0);
+            StartOffset = IoContext->Offset;
+        }
+
+        LockHeldExclusive = FALSE;
         if (IO_IS_FILE_OBJECT_CACHEABLE(FileObject) != FALSE) {
-            Status = IopPerformCachedRead(FileObject, IoContext);
+            Status = IopPerformCachedRead(FileObject,
+                                          IoContext,
+                                          &LockHeldExclusive);
 
         } else {
             Status = IopPerformNonCachedRead(FileObject,
@@ -291,8 +309,16 @@ Return Value:
                                              Handle->DeviceContext);
         }
 
-        KeReleaseSharedExclusiveLockShared(FileObject->Lock);
-        Modified = FALSE;
+        TimeType = FileObjectAccessTime;
+    }
+
+    //
+    // If no offset was provided, update the current offset.
+    //
+
+    if (OriginalOffset == IO_OFFSET_NONE) {
+        RtlAtomicExchange64(&(Handle->CurrentOffset),
+                            StartOffset + IoContext->BytesCompleted);
     }
 
     //
@@ -300,19 +326,18 @@ Return Value:
     //
 
     if (IoContext->BytesCompleted != 0) {
-        if ((Modified != FALSE) ||
+        if ((TimeType == FileObjectModifiedTime) ||
             ((Handle->OpenFlags & OPEN_FLAG_NO_ACCESS_TIME) == 0)) {
 
-            IopUpdateFileObjectTime(FileObject, Modified);
+            IopUpdateFileObjectTime(FileObject, TimeType);
         }
     }
 
-    //
-    // If no offset was provided, update the current offset.
-    //
+    if (LockHeldExclusive != FALSE) {
+        KeReleaseSharedExclusiveLockExclusive(FileObject->Lock);
 
-    if (OriginalOffset == IO_OFFSET_NONE) {
-        RtlAtomicAdd64(&(Handle->CurrentOffset), IoContext->BytesCompleted);
+    } else {
+        KeReleaseSharedExclusiveLockShared(FileObject->Lock);
     }
 
     return Status;
@@ -454,7 +479,8 @@ Return Value:
 KSTATUS
 IopPerformCachedRead (
     PFILE_OBJECT FileObject,
-    PIO_CONTEXT IoContext
+    PIO_CONTEXT IoContext,
+    PBOOL LockHeldExclusive
     )
 
 /*++
@@ -471,6 +497,11 @@ Arguments:
 
     IoContext - Supplies a pointer to the I/O context.
 
+    LockHeldExclusive - Supplies a pointer indicating whether the file object
+        lock is held shared (FALSE) or exclusive (TRUE). This routine may
+        convert a shared acquire into an exclusive one if new entries need to
+        be inserted into the page cache.
+
 Return Value:
 
     Status code.
@@ -619,6 +650,16 @@ Return Value:
                 ASSERT(CurrentOffset < FileSize);
                 ASSERT((CurrentOffset - CacheMissOffset) <= MAX_UINTN);
 
+                //
+                // Cache misses are going to modify the page cache tree, so
+                // the lock needs to be held exclusive.
+                //
+
+                if (*LockHeldExclusive == FALSE) {
+                    KeSharedExclusiveLockConvertToExclusive(FileObject->Lock);
+                    *LockHeldExclusive = TRUE;
+                }
+
                 MissContext.IoBuffer = PageAlignedIoBuffer;
                 MissContext.Offset = CacheMissOffset;
                 MissSize = (UINTN)(CurrentOffset - CacheMissOffset);
@@ -690,6 +731,11 @@ Return Value:
         ASSERT(CurrentOffset <= FileSize);
         ASSERT(CurrentOffset == (IoContext->Offset + SizeInBytes));
 
+        if (*LockHeldExclusive == FALSE) {
+            KeSharedExclusiveLockConvertToExclusive(FileObject->Lock);
+            *LockHeldExclusive = TRUE;
+        }
+
         MissContext.IoBuffer = PageAlignedIoBuffer;
         MissContext.Offset = CacheMissOffset;
         MissSize = (UINTN)(CurrentOffset - CacheMissOffset);
@@ -1523,6 +1569,7 @@ Routine Description:
     This routine handles a cache miss. It performs an aligned read on the given
     handle at the miss offset and then caches the read data. It will update the
     given destination I/O buffer with physical pages from the page cache.
+    The file object lock must be held exclusive already.
 
 Arguments:
 
@@ -1553,6 +1600,7 @@ Return Value:
     PageSize = MmPageSize();
     IoContext->BytesCompleted = 0;
 
+    ASSERT(KeIsSharedExclusiveLockHeldExclusive(FileObject->Lock) != FALSE);
     ASSERT(IO_IS_CACHEABLE_TYPE(FileObject->Properties.Type));
     ASSERT(IS_ALIGNED(IoContext->Offset, PageSize) != FALSE);
 

+ 136 - 154
kernel/io/fileobj.c

@@ -42,12 +42,10 @@ Environment:
 // ----------------------------------------------- Internal Function Prototypes
 //
 
-VOID
-IopRemoveFailedFileObjects (
-    PRED_BLACK_TREE Tree,
-    PRED_BLACK_TREE_NODE Node,
-    ULONG Level,
-    PVOID Context
+KSTATUS
+IopFlushFileObjectProperties (
+    PFILE_OBJECT FileObject,
+    ULONG Flags
     );
 
 COMPARISON_RESULT
@@ -498,7 +496,7 @@ Return Value:
 
     KSTATUS Status;
 
-    Status = IopFileObjectReleaseReference(FileObject, FALSE);
+    Status = IopFileObjectReleaseReference(FileObject);
 
     ASSERT(KSUCCESS(Status));
 
@@ -750,7 +748,7 @@ Return Value:
         //
 
         if ((Object->Flags & FILE_OBJECT_FLAG_CLOSING) != 0) {
-            IopFileObjectReleaseReference(Object, FALSE);
+            IopFileObjectReleaseReference(Object);
             Object = NULL;
             continue;
         }
@@ -769,7 +767,7 @@ CreateOrLookupFileObjectEnd:
 
     if (!KSUCCESS(Status)) {
         if (Object != NULL) {
-            IopFileObjectReleaseReference(Object, FALSE);
+            IopFileObjectReleaseReference(Object);
             Object = NULL;
 
             ASSERT(Object != NewObject);
@@ -838,8 +836,7 @@ Return Value:
 
 KSTATUS
 IopFileObjectReleaseReference (
-    PFILE_OBJECT Object,
-    BOOL FailIfLastReference
+    PFILE_OBJECT Object
     )
 
 /*++
@@ -863,9 +860,6 @@ Return Value:
 
     STATUS_SUCCESS on success.
 
-    STATUS_OPERATION_CANCELLED if the caller passed in the fail if last
-    reference flag and this is the final reference on the file object.
-
     Other error codes on failure to write out the file properties to the file
     system or device.
 
@@ -918,20 +912,6 @@ Return Value:
             goto FileObjectReleaseReferenceEnd;
         }
 
-        //
-        // If the caller doesn't want to release the last reference, bump the
-        // reference count back up and cancel the operation. This is done
-        // under the lock to prevent new folks from coming in and finding it.
-        //
-
-        if (FailIfLastReference != FALSE) {
-            RtlAtomicAdd32(&(Object->ReferenceCount), 1);
-            KeReleaseQueuedLock(IoFileObjectsLock);
-            Cancelled = TRUE;
-            Status = STATUS_OPERATION_CANCELLED;
-            goto FileObjectReleaseReferenceEnd;
-        }
-
         //
         // Unsignal the ready event to pause anyone trying to open this file
         // object or delete lingering failed objects.
@@ -1034,10 +1014,7 @@ Return Value:
         //
 
         KeSignalEvent(Object->ReadyEvent, SignalOptionSignalAll);
-
-        ASSERT(FailIfLastReference == FALSE);
-
-        IopFileObjectReleaseReference(Object, FALSE);
+        IopFileObjectReleaseReference(Object);
 
     //
     // If this is the very last reference, then actually destroy the object.
@@ -1272,24 +1249,47 @@ Return Value:
 
 {
 
+    BOOL Exclusive;
     KSTATUS Status;
 
-    Status = IopFlushPageCacheEntries(FileObject,
-                                      Offset,
-                                      Size,
-                                      Flags,
-                                      PageCount);
+    Exclusive = FALSE;
+    KeAcquireSharedExclusiveLockShared(FileObject->Lock);
+    if ((FileObject->Properties.HardLinkCount == 0) &&
+        (FileObject->PathEntryCount == 0)) {
 
-    if (!KSUCCESS(Status)) {
-        goto FlushFileObjectEnd;
-    }
+        KeSharedExclusiveLockConvertToExclusive(FileObject->Lock);
+        Exclusive = TRUE;
+        IopEvictPageCacheEntries(FileObject,
+                                 0,
+                                 PAGE_CACHE_EVICTION_FLAG_REMOVE);
 
-    Status = IopFlushFileObjectProperties(FileObject, Flags);
-    if (!KSUCCESS(Status)) {
-        goto FlushFileObjectEnd;
+    } else {
+        Status = IopFlushPageCacheEntries(FileObject,
+                                          Offset,
+                                          Size,
+                                          Flags,
+                                          PageCount);
+
+        if (!KSUCCESS(Status)) {
+            goto FlushFileObjectEnd;
+        }
+
+        Status = IopFlushFileObjectProperties(FileObject, Flags);
+        if (!KSUCCESS(Status)) {
+            goto FlushFileObjectEnd;
+        }
     }
 
+    Status = STATUS_SUCCESS;
+
 FlushFileObjectEnd:
+    if (Exclusive != FALSE) {
+        KeReleaseSharedExclusiveLockExclusive(FileObject->Lock);
+
+    } else {
+        KeReleaseSharedExclusiveLockShared(FileObject->Lock);
+    }
+
     return Status;
 }
 
@@ -1467,7 +1467,7 @@ Return Value:
                 if (CurrentObject->ListEntry.Next != NULL) {
                     LIST_REMOVE(&(CurrentObject->ListEntry));
                     CurrentObject->ListEntry.Next = NULL;
-                    IopFileObjectReleaseReference(CurrentObject, FALSE);
+                    IopFileObjectReleaseReference(CurrentObject);
                 }
             }
 
@@ -1476,7 +1476,7 @@ Return Value:
             }
 
             KeReleaseQueuedLock(IoFileObjectsDirtyListLock);
-            IopFileObjectReleaseReference(CurrentObject, FALSE);
+            IopFileObjectReleaseReference(CurrentObject);
             CurrentObject = NextObject;
         }
     }
@@ -1557,6 +1557,7 @@ Return Value:
 
         IopFileObjectAddReference(CurrentObject);
         KeReleaseQueuedLock(IoFileObjectsLock);
+        KeAcquireSharedExclusiveLockExclusive(CurrentObject->Lock);
 
         //
         // Call the eviction routine for the current file object.
@@ -1572,10 +1573,11 @@ Return Value:
 
             ASSERT(ReleaseObject->ReferenceCount >= 2);
 
-            IopFileObjectReleaseReference(ReleaseObject, FALSE);
+            IopFileObjectReleaseReference(ReleaseObject);
             ReleaseObject = NULL;
         }
 
+        KeReleaseSharedExclusiveLockExclusive(CurrentObject->Lock);
         KeAcquireQueuedLock(IoFileObjectsLock);
 
         //
@@ -1602,117 +1604,23 @@ Return Value:
 
         ASSERT(ReleaseObject->ReferenceCount >= 2);
 
-        IopFileObjectReleaseReference(ReleaseObject, FALSE);
+        IopFileObjectReleaseReference(ReleaseObject);
     }
 
     if (CurrentObject != NULL) {
 
         ASSERT(ReleaseObject->ReferenceCount >= 2);
 
-        IopFileObjectReleaseReference(CurrentObject, FALSE);
+        IopFileObjectReleaseReference(CurrentObject);
     }
 
     return;
 }
 
-KSTATUS
-IopFlushFileObjectProperties (
-    PFILE_OBJECT FileObject,
-    ULONG Flags
-    )
-
-/*++
-
-Routine Description:
-
-    This routine flushes the file properties for the given file object.
-
-Arguments:
-
-    FileObject - Supplies a pointer to a file object.
-
-    Flags - Supplies a bitmask of I/O flags. See IO_FLAG_* for definitions.
-
-Return Value:
-
-    Status code.
-
---*/
-
-{
-
-    BOOL LockHeld;
-    IRP_MINOR_CODE MinorCode;
-    ULONG OldFlags;
-    KSTATUS Status;
-
-    LockHeld = FALSE;
-
-    //
-    // Write out the file properties if a flush is required. A flush is
-    // required if the file properties are dirty and the hard link count is not
-    // zero.
-    //
-
-    OldFlags = RtlAtomicAnd32(&(FileObject->Flags),
-                              ~FILE_OBJECT_FLAG_DIRTY_PROPERTIES);
-
-    if (((OldFlags & FILE_OBJECT_FLAG_DIRTY_PROPERTIES) != 0) &&
-        (FileObject->Properties.HardLinkCount != 0)) {
-
-        //
-        // Acquire the file's lock shared to synchronize with exclusive changes
-        // to the hard link count.
-        //
-
-        KeAcquireSharedExclusiveLockShared(FileObject->Lock);
-        LockHeld = TRUE;
-
-        //
-        // If the hard link count sneaked down to zero then do not write out
-        // the file properties.
-        //
-
-        if (FileObject->Properties.HardLinkCount == 0) {
-            Status = STATUS_SUCCESS;
-            goto FlushFilePropertiesEnd;
-        }
-
-        //
-        // Write out the file properties. Don't report a failure if the device
-        // got yanked in the middle of this operation. Other failures should
-        // reset the properties as dirty. Something else may have marked them
-        // dirty already and they may already have been cleaned successfully.
-        // But this at least guarantees it will be tried again.
-        //
-
-        MinorCode = IrpMinorSystemControlWriteFileProperties;
-        Status = IopSendFileOperationIrp(MinorCode, FileObject, NULL, Flags);
-        if ((!KSUCCESS(Status)) && (Status != STATUS_DEVICE_NOT_CONNECTED)) {
-            IopMarkFileObjectPropertiesDirty(FileObject);
-            goto FlushFilePropertiesEnd;
-        }
-
-        if (LockHeld != FALSE) {
-            KeReleaseSharedExclusiveLockShared(FileObject->Lock);
-            LockHeld = FALSE;
-        }
-    }
-
-    Status = STATUS_SUCCESS;
-
-FlushFilePropertiesEnd:
-    if (LockHeld != FALSE) {
-        KeReleaseSharedExclusiveLockShared(FileObject->Lock);
-    }
-
-    return Status;
-}
-
 VOID
 IopUpdateFileObjectTime (
     PFILE_OBJECT FileObject,
-    BOOL Modified
+    FILE_OBJECT_TIME_TYPE TimeType
     )
 
 /*++
@@ -1726,8 +1634,8 @@ Arguments:
 
     FileObject - Supplies a pointer to a file object.
 
-    Modified - Supplies a boolean indicating whether or not the modified time
-        needs to be updated.
+    TimeType - Supplies the type of time to update. Updating modified time also
+        updates status change time.
 
 Return Value:
 
@@ -1743,9 +1651,20 @@ Return Value:
 
     KeAcquireSpinLock(&(FileObject->PropertiesLock));
     KeGetSystemTime(&CurrentTime);
-    FileObject->Properties.AccessTime = CurrentTime;
-    if (Modified != FALSE) {
+    if (TimeType == FileObjectAccessTime) {
+        FileObject->Properties.AccessTime = CurrentTime;
+
+    } else if (TimeType == FileObjectModifiedTime) {
         FileObject->Properties.ModifiedTime = CurrentTime;
+        FileObject->Properties.StatusChangeTime = CurrentTime;
+
+    } else if (TimeType == FileObjectStatusTime) {
+        FileObject->Properties.StatusChangeTime = CurrentTime;
+
+    } else {
+
+        ASSERT(FALSE);
+
     }
 
     KeReleaseSpinLock(&(FileObject->PropertiesLock));
@@ -1910,10 +1829,6 @@ Return Value:
     ULONGLONG UnmapOffset;
     ULONGLONG UnmapSize;
 
-    //
-    // If the file object synchronizes I/O, then acquire the lock exclusively.
-    //
-
     KeAcquireSharedExclusiveLockExclusive(FileObject->Lock);
 
     //
@@ -2066,7 +1981,7 @@ Return Value:
     KeAcquireSpinLock(&(FileObject->PropertiesLock));
     FileObject->Properties.HardLinkCount += 1;
     KeReleaseSpinLock(&(FileObject->PropertiesLock));
-    IopMarkFileObjectPropertiesDirty(FileObject);
+    IopUpdateFileObjectTime(FileObject, FileObjectStatusTime);
     return;
 }
 
@@ -2098,7 +2013,7 @@ Return Value:
     KeAcquireSpinLock(&(FileObject->PropertiesLock));
     FileObject->Properties.HardLinkCount -= 1;
     KeReleaseSpinLock(&(FileObject->PropertiesLock));
-    IopMarkFileObjectPropertiesDirty(FileObject);
+    IopUpdateFileObjectTime(FileObject, FileObjectStatusTime);
     return;
 }
 
@@ -2160,7 +2075,7 @@ Return Value:
 
         IopFileObjectAddReference(CurrentObject);
         KeReleaseQueuedLock(IoFileObjectsLock);
-        IopFileObjectReleaseReference(CurrentObject, FALSE);
+        IopFileObjectReleaseReference(CurrentObject);
         KeAcquireQueuedLock(IoFileObjectsLock);
     }
 
@@ -2385,6 +2300,73 @@ Return Value:
 // --------------------------------------------------------- Internal Functions
 //
 
+KSTATUS
+IopFlushFileObjectProperties (
+    PFILE_OBJECT FileObject,
+    ULONG Flags
+    )
+
+/*++
+
+Routine Description:
+
+    This routine flushes the file properties for the given file object. The
+    file object lock must already be held at least shared.
+
+Arguments:
+
+    FileObject - Supplies a pointer to a file object.
+
+    Flags - Supplies a bitmask of I/O flags. See IO_FLAG_* for definitions.
+
+Return Value:
+
+    Status code.
+
+--*/
+
+{
+
+    IRP_MINOR_CODE MinorCode;
+    ULONG OldFlags;
+    KSTATUS Status;
+
+    ASSERT(KeIsSharedExclusiveLockHeld(FileObject->Lock));
+
+    //
+    // Write out the file properties if a flush is required. A flush is
+    // required if the file properties are dirty and the hard link count is not
+    // zero.
+    //
+
+    OldFlags = RtlAtomicAnd32(&(FileObject->Flags),
+                              ~FILE_OBJECT_FLAG_DIRTY_PROPERTIES);
+
+    if (((OldFlags & FILE_OBJECT_FLAG_DIRTY_PROPERTIES) != 0) &&
+        (FileObject->Properties.HardLinkCount != 0)) {
+
+        //
+        // Write out the file properties. Don't report a failure if the device
+        // got yanked in the middle of this operation. Other failures should
+        // reset the properties as dirty. Something else may have marked them
+        // dirty already and they may already have been cleaned successfully.
+        // But this at least guarantees it will be tried again.
+        //
+
+        MinorCode = IrpMinorSystemControlWriteFileProperties;
+        Status = IopSendFileOperationIrp(MinorCode, FileObject, NULL, Flags);
+        if ((!KSUCCESS(Status)) && (Status != STATUS_DEVICE_NOT_CONNECTED)) {
+            IopMarkFileObjectPropertiesDirty(FileObject);
+            goto FlushFilePropertiesEnd;
+        }
+    }
+
+    Status = STATUS_SUCCESS;
+
+FlushFilePropertiesEnd:
+    return Status;
+}
+
 COMPARISON_RESULT
 IopCompareFileObjectNodes (
     PRED_BLACK_TREE Tree,

+ 1 - 1
kernel/io/filesys.c

@@ -1000,7 +1000,7 @@ VolumeArrivalEnd:
     }
 
     if (FileObject != NULL) {
-        IopFileObjectReleaseReference(FileObject, FALSE);
+        IopFileObjectReleaseReference(FileObject);
     }
 
     if (VolumeHandle != NULL) {

+ 21 - 8
kernel/io/iobase.c

@@ -2123,6 +2123,8 @@ Return Value:
 
         if (RenameRequest.SourceFileHardLinkDelta == 1) {
             IopFileObjectIncrementHardLinkCount(SourceFileObject);
+            IopUpdateFileObjectTime(DestinationDirectoryFileObject,
+                                    FileObjectModifiedTime);
 
         //
         // Otherwise, the delta is -1. Decrement the hard link count and unlink
@@ -2136,6 +2138,8 @@ Return Value:
 
             IopFileObjectDecrementHardLinkCount(SourceFileObject);
             IopPathUnlink(SourcePathPoint.PathEntry);
+            IopUpdateFileObjectTime(SourceDirectoryFileObject,
+                                    FileObjectModifiedTime);
         }
 
     //
@@ -2156,8 +2160,16 @@ Return Value:
                                     RenameRequest.DestinationDirectorySize,
                                     TRUE,
                                     TRUE);
+
+        IopUpdateFileObjectTime(DestinationDirectoryFileObject,
+                                FileObjectModifiedTime);
+
+        IopUpdateFileObjectTime(SourceDirectoryFileObject,
+                                FileObjectModifiedTime);
     }
 
+    IopUpdateFileObjectTime(SourceFileObject, FileObjectStatusTime);
+
 RenameEnd:
     if (LocksHeld != FALSE) {
         KeReleaseSharedExclusiveLockExclusive(SourceFileObject->Lock);
@@ -3945,7 +3957,8 @@ Return Value:
 
         if (Unlinked != FALSE) {
             IopFileObjectDecrementHardLinkCount(FileObject);
-            IopUpdateFileObjectTime(DirectoryFileObject, TRUE);
+            IopUpdateFileObjectTime(DirectoryFileObject,
+                                    FileObjectModifiedTime);
         }
     }
 
@@ -4221,7 +4234,7 @@ Return Value:
     //
 
     if (KSUCCESS(Status)) {
-        IopUpdateFileObjectTime(Directory, TRUE);
+        IopUpdateFileObjectTime(Directory, FileObjectModifiedTime);
         IopUpdateFileObjectFileSize(Directory,
                                     Request.DirectorySize,
                                     TRUE,
@@ -4308,7 +4321,7 @@ Return Value:
         // The directory was modified, update its times.
         //
 
-        IopUpdateFileObjectTime(DirectoryObject, TRUE);
+        IopUpdateFileObjectTime(DirectoryObject, FileObjectModifiedTime);
     }
 
     *Unlinked = UnlinkRequest.Unlinked;
@@ -5099,7 +5112,7 @@ CreateAnonymousObjectEnd:
     }
 
     if (FileObject != NULL) {
-        IopFileObjectReleaseReference(FileObject, FALSE);
+        IopFileObjectReleaseReference(FileObject);
     }
 
     PathPoint->PathEntry = PathEntry;
@@ -5447,6 +5460,7 @@ Return Value:
 
     ASSERT(FileObject != NULL);
 
+    KeAcquireSharedExclusiveLockShared(FileObject->Lock);
     if (Context->Offset != IO_OFFSET_NONE) {
         Parameters.IoOffset = Context->Offset;
 
@@ -5503,16 +5517,13 @@ Return Value:
 
     ASSERT(IS_DEVICE_OR_VOLUME(Device));
 
-    KeAcquireSharedExclusiveLockShared(FileObject->Lock);
     Status = IopSendIoIrp(Device, IrpMinorIoRead, &Parameters);
     if (KSUCCESS(Status) || (Status == STATUS_END_OF_FILE)) {
         if ((Handle->OpenFlags & OPEN_FLAG_NO_ACCESS_TIME) == 0) {
-            IopUpdateFileObjectTime(FileObject, FALSE);
+            IopUpdateFileObjectTime(FileObject, FileObjectAccessTime);
         }
     }
 
-    KeReleaseSharedExclusiveLockShared(FileObject->Lock);
-
 PerformDirectoryIoOperationEnd:
 
     //
@@ -5524,6 +5535,8 @@ PerformDirectoryIoOperationEnd:
                             Parameters.NewIoOffset);
     }
 
+    KeReleaseSharedExclusiveLockShared(FileObject->Lock);
+
     //
     // Modify the file IDs of any directory entries that are mount points.
     // This needs to happen for any directory entries read from disk.

+ 41 - 37
kernel/io/iop.h

@@ -330,6 +330,12 @@ Author:
 // ------------------------------------------------------ Data Type Definitions
 //
 
+typedef enum _FILE_OBJECT_TIME_TYPE {
+    FileObjectAccessTime,
+    FileObjectModifiedTime,
+    FileObjectStatusTime,
+} FILE_OBJECT_TIME_TYPE, *PFILE_OBJECT_TIME_TYPE;
+
 typedef struct _DEVICE_POWER DEVICE_POWER, *PDEVICE_POWER;
 
 /*++
@@ -2498,8 +2504,7 @@ Return Value:
 
 KSTATUS
 IopFileObjectReleaseReference (
-    PFILE_OBJECT Object,
-    BOOL FailIfLastReference
+    PFILE_OBJECT Object
     );
 
 /*++
@@ -2517,15 +2522,12 @@ Arguments:
         count not to be decremented if this would involve releasing the very
         last reference on the file object. Callers that set this flag must be
         able to take responsibility for the reference they continue to own in
-        the failure case. Most set this to FALSE.
+        the failure case. Set this to FALSE.
 
 Return Value:
 
     STATUS_SUCCESS on success.
 
-    STATUS_OPERATION_CANCELLED if the caller passed in the fail if last
-    reference flag and this is the final reference on the file object.
-
     Other error codes on failure to write out the file properties to the file
     system or device.
 
@@ -2738,34 +2740,10 @@ Return Value:
 
 --*/
 
-KSTATUS
-IopFlushFileObjectProperties (
-    PFILE_OBJECT FileObject,
-    ULONG Flags
-    );
-
-/*++
-
-Routine Description:
-
-    This routine flushes the file properties for the given file object.
-
-Arguments:
-
-    FileObject - Supplies a pointer to a file object.
-
-    Flags - Supplies a bitmask of I/O flags. See IO_FLAG_* for definitions.
-
-Return Value:
-
-    Status code.
-
---*/
-
 VOID
 IopUpdateFileObjectTime (
     PFILE_OBJECT FileObject,
-    BOOL Modified
+    FILE_OBJECT_TIME_TYPE TimeType
     );
 
 /*++
@@ -2779,8 +2757,8 @@ Arguments:
 
     FileObject - Supplies a pointer to a file object.
 
-    Modified - Supplies a boolean indicating whether or not the modified time
-        needs to be updated.
+    TimeType - Supplies the type of time to update. Updating modified time also
+        updates status change time.
 
 Return Value:
 
@@ -4752,7 +4730,8 @@ Routine Description:
 
     This routine creates a page cache entry and inserts it into the cache. Or,
     if a page cache entry already exists for the supplied file object and
-    offset, it returns the existing entry.
+    offset, it returns the existing entry. The file object lock must be held
+    exclusive already.
 
 Arguments:
 
@@ -4845,7 +4824,8 @@ Routine Description:
 
     This routine iterates over the source buffer, caching each page and copying
     the pages to the destination buffer starting at the given copy offsets and
-    up to the given copy size.
+    up to the given copy size. The file object lock must be held exclusive
+    already.
 
 Arguments:
 
@@ -4933,7 +4913,7 @@ Routine Description:
 
     This routine attempts to evict the page cache entries for a given file or
     device, as specified by the file object. The flags specify how aggressive
-    this routine should be.
+    this routine should be. The file object lock must already be held exclusive.
 
 Arguments:
 
@@ -5203,7 +5183,8 @@ Arguments:
     LowerEntry - Supplies a pointer to the lower (disk) level page cache entry
         whose physical address is to be modified. The caller should ensure that
         its reference on this entry does not come from an I/O buffer or else
-        the physical address in the I/O buffer would be invalid.
+        the physical address in the I/O buffer would be invalid. The file
+        object lock for this entry must already be held exclusive.
 
     UpperEntry - Supplies a pointer to the upper (file) page cache entry
         that currently owns the physical page to be shared.
@@ -5216,6 +5197,29 @@ Return Value:
 
 --*/
 
+VOID
+IopTrimPageCache (
+    VOID
+    );
+
+/*++
+
+Routine Description:
+
+    This routine removes as many clean page cache entries as is necessary to
+    bring the size of the page cache back down to a reasonable level. It evicts
+    the page cache entries in LRU order.
+
+Arguments:
+
+    None.
+
+Return Value:
+
+    None.
+
+--*/
+
 BOOL
 IopIsPageCacheTooDirty (
     VOID

Fichier diff supprimé car celui-ci est trop grand
+ 175 - 426
kernel/io/pagecach.c


+ 3 - 3
kernel/io/path.c

@@ -513,7 +513,7 @@ InitializePathSupportEnd:
         }
 
         if (FileObject != NULL) {
-            IopFileObjectReleaseReference(FileObject, FALSE);
+            IopFileObjectReleaseReference(FileObject);
         }
     }
 
@@ -2948,7 +2948,7 @@ PathLookupThroughFileSystemEnd:
     }
 
     if (FileObject != NULL) {
-        IopFileObjectReleaseReference(FileObject, FALSE);
+        IopFileObjectReleaseReference(FileObject);
     }
 
     return Status;
@@ -3579,7 +3579,7 @@ Return Value:
 
     if (Entry->Negative == FALSE) {
         IopFileObjectReleasePathEntryReference(Entry->FileObject);
-        IopFileObjectReleaseReference(Entry->FileObject, FALSE);
+        IopFileObjectReleaseReference(Entry->FileObject);
     }
 
     MmFreePagedPool(Entry);

+ 1 - 1
kernel/io/pipe.c

@@ -414,7 +414,7 @@ CreatePipeEnd:
     if (!KSUCCESS(Status)) {
         if (NewFileObject != NULL) {
             *FileObject = NULL;
-            IopFileObjectReleaseReference(NewFileObject, FALSE);
+            IopFileObjectReleaseReference(NewFileObject);
         }
 
         if (NewPipe != NULL) {

+ 2 - 2
kernel/io/pty.c

@@ -1133,7 +1133,7 @@ Return Value:
         //
 
         if (Terminal->SlaveFileObject != NULL) {
-            IopFileObjectReleaseReference(Terminal->SlaveFileObject, FALSE);
+            IopFileObjectReleaseReference(Terminal->SlaveFileObject);
         }
     }
 
@@ -1388,7 +1388,7 @@ Return Value:
     //
 
     ObReleaseReference(Slave->Master);
-    IopFileObjectReleaseReference(Slave->Master->MasterFileObject, FALSE);
+    IopFileObjectReleaseReference(Slave->Master->MasterFileObject);
     return STATUS_SUCCESS;
 }
 

+ 2 - 2
kernel/io/shmemobj.c

@@ -591,7 +591,7 @@ CreateSharedMemoryObjectEnd:
 
     if (!KSUCCESS(Status)) {
         if (NewFileObject != NULL) {
-            IopFileObjectReleaseReference(NewFileObject, FALSE);
+            IopFileObjectReleaseReference(NewFileObject);
             NewFileObject = NULL;
             *FileObject = NULL;
         }
@@ -716,7 +716,7 @@ Return Value:
 
         ASSERT(SharedMemoryObject->FileObject == FileObject);
 
-        IopFileObjectReleaseReference(SharedMemoryObject->FileObject, FALSE);
+        IopFileObjectReleaseReference(SharedMemoryObject->FileObject);
         SharedMemoryObject->FileObject = NULL;
         *Unlinked = TRUE;
     }

+ 1 - 1
kernel/io/socket.c

@@ -2257,7 +2257,7 @@ CreateSocketEnd:
         }
 
         if (NewFileObject != NULL) {
-            IopFileObjectReleaseReference(NewFileObject, FALSE);
+            IopFileObjectReleaseReference(NewFileObject);
             *FileObject = NULL;
         }
     }

+ 51 - 0
kernel/ke/lock.c

@@ -915,6 +915,57 @@ Return Value:
     return;
 }
 
+KERNEL_API
+VOID
+KeSharedExclusiveLockConvertToExclusive (
+    PSHARED_EXCLUSIVE_LOCK SharedExclusiveLock
+    )
+
+/*++
+
+Routine Description:
+
+    This routine converts a lock that the caller holds shared into one that
+    the caller holds exclusive. This routine will most likely fully release
+    and reacquire the lock.
+
+Arguments:
+
+    SharedExclusiveLock - Supplies a pointer to the shared-exclusive lock.
+
+Return Value:
+
+    None.
+
+--*/
+
+{
+
+    ULONG State;
+
+    //
+    // Try a shortcut in the case that this caller is the only one that has it
+    // shared.
+    //
+
+    State = RtlAtomicCompareExchange32(&(SharedExclusiveLock->State),
+                                       SHARED_EXCLUSIVE_LOCK_EXCLUSIVE,
+                                       1);
+
+    ASSERT((State >= 1) && (State < SHARED_EXCLUSIVE_LOCK_EXCLUSIVE));
+
+    //
+    // If the fast conversion failed, get in line like everybody else.
+    //
+
+    if (State != 1) {
+        KeReleaseSharedExclusiveLockShared(SharedExclusiveLock);
+        KeAcquireSharedExclusiveLockExclusive(SharedExclusiveLock);
+    }
+
+    return;
+}
+
 KERNEL_API
 BOOL
 KeIsSharedExclusiveLockHeld (

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff