diff -r ff5437e4337c -r 48e57fb1237e kerneltest/f32test/demandpaging/t_clamp.cpp --- a/kerneltest/f32test/demandpaging/t_clamp.cpp Wed Oct 06 17:13:14 2010 +0100 +++ b/kerneltest/f32test/demandpaging/t_clamp.cpp Mon Oct 11 17:54:41 2010 +0100 @@ -216,6 +216,26 @@ +void RemountFileSystem(TInt aDriveNo, TDesC& aFsName, TDesC& aFsExtName0, TDesC& aFsExtName1) + { + TInt r; + if(aFsExtName0.Length() > 0) + { + r=TheFs.MountFileSystem(aFsName,aFsExtName0,aDriveNo); + test(r==KErrNone); + } + else if(aFsExtName1.Length() > 0) // untested ! + { + r=TheFs.MountFileSystem(aFsName,aFsExtName1,aDriveNo); + test(r==KErrNone); + } + else + { + r=TheFs.MountFileSystem(aFsName,aDriveNo); + test(r==KErrNone); + } + } + LOCAL_C void TestDeferredDismount(TDesC& aRoot, TDesC& aFileName, RFileClamp* handlePtr) { // Open and clamp file, register for dismount notification, then issue @@ -231,26 +251,23 @@ TBuf fsName; TBuf fsExtName_0; TBuf fsExtName_1; - TBool fsExt0Present=EFalse; - TBool fsExt1Present=EFalse; TInt driveNo, r; r=TheFs.CharToDrive(aRoot[0], driveNo); test(r==KErrNone); r=TheFs.FileSystemName(fsName, driveNo); test(r==KErrNone); - r=TheFs.ExtensionName(fsExtName_0,driveNo,0); - if(r==KErrNone) - fsExt0Present=ETrue; - r=TheFs.ExtensionName(fsExtName_1,driveNo,1); - if(r==KErrNone) - fsExt1Present=ETrue; + //******************************************************************************************************* // Create a file & write to it so that we can test whether dismounting works correctly with dirty data + //******************************************************************************************************* + test.Next(_L("T_Clamp - TestDeferredDismount(), testing unmounting with dirty data, registered clients & clamped files")); + TDriveInfo driveInfo; test(TheFs.Drive(driveInfo, driveNo) == KErrNone); TFileName dirtyFileName(_L("dirtyFile.tst")); RFile dirtyFile; - if (!(driveInfo.iMediaAtt & KMediaAttWriteProtected)) + TBool writeProtectedMedia = driveInfo.iMediaAtt & KMediaAttWriteProtected; + if (!writeProtectedMedia) { r=dirtyFile.Replace(TheFs, dirtyFileName, EFileWrite); test(r==KErrNone); @@ -268,9 +285,16 @@ TRequestStatus clientNotify=KErrNone; TRequestStatus clientDismount=KErrNone; - TheFs.NotifyDismount(driveNo, clientNotify); // Register for notification + TheFs.NotifyDismount(driveNo, clientNotify); // Register for dismount notification test(clientNotify == KRequestPending); + + // register for disk change notifcation, so we can detect when dismount has actually taken place + TRequestStatus diskChangeStatus; + TheFs.NotifyChange(ENotifyDisk, diskChangeStatus); + test.Printf(_L("diskChangeStatus %d"), diskChangeStatus.Int()); + test(diskChangeStatus == KRequestPending); // no disk change yet + TheFs.NotifyDismount(driveNo, clientDismount, EFsDismountNotifyClients); test(clientDismount == KRequestPending); User::WaitForRequest(clientNotify); @@ -279,6 +303,7 @@ r=TheFs.AllowDismount(driveNo); // Respond to dismount notification test(r == KErrNone); test(clientDismount == KRequestPending); // Dismount is deferred + test(diskChangeStatus == KRequestPending); // no disk change yet // // Now unclamp the file, and check that the deferred dismount is performed. @@ -287,33 +312,38 @@ User::WaitForRequest(clientDismount); test(clientDismount == KErrNone); + // wait for disk change notification following dismount + User::WaitForRequest(diskChangeStatus); + test(diskChangeStatus == KErrNone); // should have got a disk change notification after dismount + r = TheFs.Drive(driveInfo, driveNo); + test (r==KErrNone); + test (driveInfo.iType == EMediaNotPresent); + + // re-register for disk change notifcation, so we can detect when remount has actually taken place + TheFs.NotifyChange(ENotifyDisk, diskChangeStatus); + test.Printf(_L("diskChangeStatus %d"), diskChangeStatus.Int()); + test(diskChangeStatus == KRequestPending); // no disk change yet + // Try to write to the opened file: this should return KErrNotReady as there is no drive thread - if (!(driveInfo.iMediaAtt & KMediaAttWriteProtected)) + if (!writeProtectedMedia) { r=dirtyFile.Write(_L8("My name isn't really Michael Caine")); test(r==KErrNotReady); } // Re-mount the file system - if(fsExt0Present) - { - r=TheFs.MountFileSystem(fsName,fsExtName_0,driveNo); - test(r==KErrNone); - } - else if(fsExt1Present) // untested ! - { - r=TheFs.MountFileSystem(fsName,fsExtName_1,driveNo); - test(r==KErrNone); - } - else - { - r=TheFs.MountFileSystem(fsName,driveNo); - test_KErrNone(r); - } + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); + + // wait for disk change notification following remount + User::WaitForRequest(diskChangeStatus); + test(diskChangeStatus == KErrNone); // should have got a disk change notification after dismount + r = TheFs.Drive(driveInfo, driveNo); + test (r==KErrNone); + test (driveInfo.iType != EMediaNotPresent); // create some more dirty data to verify that the file server can cope with the drive thread // having gone & come back again - if (!(driveInfo.iMediaAtt & KMediaAttWriteProtected)) + if (!writeProtectedMedia) { r=dirtyFile.Write(_L8("My name is Michael Phelps and I'm a fish.")); test(r==KErrDisMounted); @@ -323,8 +353,12 @@ test(r == KErrNone); } + //******************************************************************************************************* // Issue a EFsDismountNotifyClients with no clients but with files clamped // & verify that the dismount request completes when clamps are removed + //******************************************************************************************************* + test.Next(_L("T_Clamp - TestDeferredDismount(), testing unmounting with no registered clients & clamped files")); + r=testFile.Open(TheFs,aFileName,EFileRead); test(r==KErrNone); r=handlePtr->Clamp(testFile); @@ -338,21 +372,7 @@ User::WaitForRequest(clientDismount); test(clientDismount == KErrNone); // Re-mount the file system again - if(fsExt0Present) - { - r=TheFs.MountFileSystem(fsName,fsExtName_0,driveNo); - test(r==KErrNone); - } - else if(fsExt1Present) // untested ! - { - r=TheFs.MountFileSystem(fsName,fsExtName_1,driveNo); - test(r==KErrNone); - } - else - { - r=TheFs.MountFileSystem(fsName,driveNo); - test_KErrNone(r); - } + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); // Issue a EFsDismountForceDismount with no clients but with files clamped @@ -369,23 +389,239 @@ test(r==KErrNone); User::WaitForRequest(clientDismount); test(clientDismount == KErrNone); + + // Re-mount the file system again - if(fsExt0Present) + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); + + + const TInt KNumClients = 5; + RFs clientFs[KNumClients]; + TRequestStatus clientNotifies[KNumClients]; + TRequestStatus clientDiskChanges[KNumClients]; + TRequestStatus clientComplete; + + #define LOG_AND_TEST(a, e) {if (a!=e) {test.Printf(_L("lvalue %d, rvalue%d\n\r"), a,e); test(EFalse);}} + + //******************************************************************************************************* + // Test unmounting with multiple registered clients which do not respond & close their sessions + //******************************************************************************************************* + test.Next(_L("T_Clamp - TestDeferredDismount(), testing unmounting with multiple registered clients which do not respond & close their sessions")); + + TheFs.NotifyChange(ENotifyDisk, diskChangeStatus); + test.Printf(_L("diskChangeStatus %d"), diskChangeStatus.Int()); + + TInt i; + for (i=0; i< KNumClients; i++) { - r=TheFs.MountFileSystem(fsName,fsExtName_0,driveNo); + LOG_AND_TEST(KErrNone, clientFs[i].Connect()); + clientFs[i].NotifyDismount(driveNo, clientNotifies[i]); + test(clientNotifies[i] == KRequestPending); + } + + test.Next(_L("Close all but one client sessions with outstanding notifiers")); + for (i=0; i< KNumClients-1; i++) + clientFs[i].Close(); + + // Since all clients have NOT been closed, the next stage should not yet complete + test.Next(_L("Notify clients of pending media removal and check status - should not complete")); + TheFs.NotifyDismount(driveNo, clientComplete, EFsDismountNotifyClients); + test(clientComplete == KRequestPending); + + + test.Next(_L("Close the remaining sessions with an outstanding notifier")); + clientFs[KNumClients-1].Close(); + + // Check that the dismount completes now that all session have been closed + test.Next(_L("Check that the dismount completes")); + User::WaitForRequest(clientComplete); + test_KErrNone(clientComplete.Int()); + + // wait for disk change notification following dismount + User::WaitForRequest(diskChangeStatus); + test(diskChangeStatus == KErrNone); // should have got a disk change notification after dismount + r = TheFs.Drive(driveInfo, driveNo); + test (r==KErrNone); + test (driveInfo.iType == EMediaNotPresent); + + // re-register for disk change notifcation, so we can detect when remount has actually taken place + TheFs.NotifyChange(ENotifyDisk, diskChangeStatus); + test.Printf(_L("diskChangeStatus %d"), diskChangeStatus.Int()); + test(diskChangeStatus == KRequestPending); // no disk change yet + + + // Re-mount the file system again + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); + + // wait for disk change notification following remount + User::WaitForRequest(diskChangeStatus); + test(diskChangeStatus == KErrNone); // should have got a disk change notification after dismount + r = TheFs.Drive(driveInfo, driveNo); + test (r==KErrNone); + test (driveInfo.iType != EMediaNotPresent); + + + + //******************************************************************************************************* + // Issue a EFsDismountNotifyClients with multiple clients + // Verify that the dismount completes if a client re-registers for dismount notifications BEFORE calling AllowDismount + //******************************************************************************************************* + + test.Next(_L("T_Clamp - TestDeferredDismount(), testing unmounting with multiple registered clients & a re-registration")); + + for(i=0; i< KNumClients; i++) + { + r=clientFs[i].Connect(); + test(r==KErrNone); + } + // Cancel any deferred dismount in preparation for the next test + TheFs.NotifyDismountCancel(); + + // All clients register for dismount notification + for(i=0; i< KNumClients; i++) + { + clientNotifies[i] = KErrNone; + clientFs[i].NotifyDismount(driveNo, clientNotifies[i]); + test(clientNotifies[i] == KRequestPending); + } + + // Issue a EFsDismountNotifyClients & wait for clients to respond + clientDismount = KErrNone; + TheFs.NotifyDismount(driveNo, clientDismount, EFsDismountNotifyClients); + test(clientDismount == KRequestPending); + + // Check all clients have received the notification + for(i=0; i< KNumClients; i++) + { + User::WaitForRequest(clientNotifies[i]); + test(clientNotifies[i] == KErrNone); + } + // All clients - except first one - invoke AllowDismount + for(i=1; i< KNumClients; i++) + { + r=clientFs[i].AllowDismount(driveNo); test(r==KErrNone); } - else if(fsExt1Present) // untested ! + + + // verify dismount has not yet completed + test(clientDismount == KRequestPending); + + + // first client re-registers for dismount notifications + clientFs[0].NotifyDismount(driveNo, clientNotifies[0]); + test(clientNotifies[0] == KRequestPending); + + // first client allows dismount + clientFs[0].AllowDismount(driveNo); + test(r==KErrNone); + + // Wait for dismount + User::WaitForRequest(clientDismount); + test(clientDismount == KErrNone); + + + // verify the first client's re-issued dismount notification is still pending + test(clientNotifies[0] == KRequestPending); + + + // Re-mount the file system again + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); + + + // Issue a EFsDismountNotifyClients again & check previously re-registered notification completes + test(clientNotifies[0] == KRequestPending); + clientDismount = KErrNone; + TheFs.NotifyDismount(driveNo, clientDismount, EFsDismountNotifyClients); + test(clientDismount == KRequestPending); + + // wait for notification + User::WaitForRequest(clientNotifies[0]); + + // first client allows dismount + clientFs[0].AllowDismount(driveNo); + test(r==KErrNone); + + // Wait for dismount + User::WaitForRequest(clientDismount); + test(clientDismount == KErrNone); + + + + // Re-mount the file system again + RemountFileSystem(driveNo, fsName, fsExtName_0, fsExtName_1); + + + + //******************************************************************************************************* + // Issue a EFsDismountNotifyClients again with a multiple clients & then call RFs::NotifyDismountCancel() + // Verify that all clients receive a disk change notification + //******************************************************************************************************* + test.Next(_L("T_Clamp - TestDeferredDismount(), testing unmounting with registered clients, a re-registration & a cancel")); + + // All clients register for dismount notification & disk change notification + for(i=0; i< KNumClients; i++) { - r=TheFs.MountFileSystem(fsName,fsExtName_1,driveNo); + clientNotifies[i] = KErrNone; + clientFs[i].NotifyDismount(driveNo, clientNotifies[i], EFsDismountRegisterClient); + test(clientNotifies[i] == KRequestPending); + + clientFs[i].NotifyChange(ENotifyDisk, clientDiskChanges[i]); + test.Printf(_L("diskChangeStatus %d"), clientDiskChanges[i].Int()); + test(clientDiskChanges[i] == KRequestPending); + } + + + // Issue a EFsDismountNotifyClients + TheFs.NotifyDismount(driveNo, clientComplete, EFsDismountNotifyClients); + test(clientComplete == KRequestPending); + + + // Check all clients have received the notification + for(i=0; i< KNumClients; i++) + { + User::WaitForRequest(clientNotifies[i]); + test(clientNotifies[i] == KErrNone); + + test.Printf(_L("diskChangeStatus %d"), clientDiskChanges[i].Int()); + test(clientDiskChanges[i] == KRequestPending); + } + + // verify dismount has not yet completed + test(clientComplete == KRequestPending); + + + // first client re-registers for dismount notifications + clientFs[0].NotifyDismount(driveNo, clientNotifies[0]); + test(clientNotifies[0] == KRequestPending); + + // first client acknowledges the dismount request + r = clientFs[0].AllowDismount(driveNo); + test(r == KErrNone); + + + // cancel dismount +// TheFs.NotifyDismountCancel(clientComplete); + TheFs.NotifyDismountCancel(); + test(clientComplete == KErrCancel); + User::WaitForRequest(clientComplete); + + // Check all clients have received a disk change notification - + // the file server should send a disk change notification when RFs::NotifyDismountCancel() is called + for(i=0; i< KNumClients; i++) + { + User::WaitForRequest(clientDiskChanges[i]); + test.Printf(_L("diskChangeStatus %d"), clientDiskChanges[i].Int()); + test(clientDiskChanges[i] == KErrNone); + } + + + // cleanup + for(i=0; i< KNumClients; i++) + { + clientFs[i].Close(); test(r==KErrNone); } - else - { - r=TheFs.MountFileSystem(fsName,driveNo); - test_KErrNone(r); - } - }