I call DeviceIoControl several times. FSCTL_LOCK_VOLUME,
FSCTL_DISMOUNT_VOLUME, IOCTL_VOLUME_OFFLINE, IOCTL_VOLUME_ONLINE, and
FSCTL_UNLOCK_VOLUME. All of these succeed. WinIoCtl.h doesn't define
IOCTL_VOLUME_OFFLINE and IOCTL_VOLUME_ONLINE, but MSDN implies that these
are supposed to be available to user mode applications, so I define them
myself and DeviceIoControl reports success.
After that, I have found two ways to do manual operations to force Windows
to abandon its cached contents. One is to use Computer Administrator - Disk
Administrator, remove the drive letter from the partition, and reassign the
drive letter to the partition. The other way is to open a command prompt
and run CHKDSK /F, which finds no errors but which somehow persuades Windows
XP to discard its cache. If I omit the /F then the obsolete contents remain
in the cache, after which Windows proceeds to corrupt the partition and then
the next CHKDSK /F adjusts errors (but lost data remain lost).
Now I want to do this programmatically. I wonder why obsolete contents
remain in the cache after IOCTL_VOLUME_OFFLINE and IOCTL_VOLUME_ONLINE, but
continue trying anyway. I added calls to BroadcastSystemMessage with
DBT_DEVICEREMOVECOMPLETE and DBT_DEVICEARRIVAL. These report success.
Furthermore if Windows Explorer was displaying the partition before these
operations, I can see Windows Explorer respond by removing that partition
from its display, displaying the contents of another partition, and then
restoring the drive letter and icon in the left hand pane though the right
hand pane continues displaying the other partition that it had switched to.
So I think that DBT_DEVICEREMOVECOMPLETE and DBT_DEVICEARRIVAL have some
amount of effect. But when I click on that drive letter in Windows
Explorer, it still displays obsolete cached information, and creating a new
file causes corruption in the partition.
What does it take to force Windows to discard obsolete cached data?
The format program I wrote uses the physical drive <number> to open the
entire drive and only puts on partition on the media. There is also a
format utility from linux that has been ported to windows as a command line
utility that also works. I have used it on a compact flash that is used to
load RTL code into a FPGA because the loader is really picky about the file.
I don't know if it is because it requires the file be sequentially allocated
or it requires the subdirectories be located in the first entry.
"Norman Diamond" <ndia...@newsgroup.nospam> wrote in message
news:%23gybGd8...@TK2MSFTNGP06.phx.gbl...
You might want to, before beginning the format sequence, obtain an exclusive
lock on the physical drive where the volume is located. Do, the format with
that handle, and then unlock to get the cache discarded. The open will
force any dirty cache blocks to disk before it grants you a handle.
"David Craig" <dri...@nowhere.us> wrote in message
news:ORJoVv85...@TK2MSFTNGP06.phx.gbl...
If I were doing a format then I'd include a call to
IOCTL_DISK_UPDATE_PROPERTIES. As a temporary experiment I did include a
call to IOCTL_DISK_UPDATE_PROPERTIES but it didn't help. According to MSDN
this call is necessary when doing something like changing a FAT32 partition
to NTFS, but my recent experiments make me wonder if Windows would still
corrupt the resulting partition anyway.
I'll try to find your other postings.
"David Craig" <dri...@nowhere.us> wrote in message
news:OyLrsz8...@TK2MSFTNGP04.phx.gbl...
These are not necessary. LOCK/DISMOUNT/UNLOCK is the sequence.
> to abandon its cached contents. One is to use Computer Administrator - Disk
> Administrator, remove the drive letter from the partition, and reassign the
> drive letter to the partition.
Correct. This is remount.
>The other way is to open a command prompt
> and run CHKDSK /F, which finds no errors but which somehow persuades
>Windows
Correct. This is also remount.
> Now I want to do this programmatically.
LOCK/DISMOUNT/UNLOCK. If LOCK fails - then you can do the forced dismount and
just call DISMOUNT without LOCK and UNLOCK.
This is what diskmgmt and chkdsk do.
--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
ma...@storagecraft.com
http://www.storagecraft.com
LOCK returns a success value, so my program doesn't know that Windows is
preserving its obsolete cached data. Also I as a human, watching it while
debugging, don't know yet that Windows is preserving its obsolete cached
data. As a human I discover the problem after all of this is finished,
because Windows Explorer displays contents which are no longer accurate, and
if I use Windows Explorer to create a text file then the partition gets
corrupted.
So LOCK/DISMOUNT/UNLOCK is not enough. diskmgmt and chkdsk do something
else in addition, to persuade Windows to discard its obsolete cache. I want
to do the same, programmatically. What do they do?
Correct. This means that no other thread can do any CreateFile on the volume,
and there are no other existing file handles on it.
Graceful DISMOUNT requires LOCK to be called before. DISMOUNT without LOCK is
the forced dismount - it tears away all existing file objects.
>so my program doesn't know that Windows is
> preserving its obsolete cached data.
LOCK does not mean that the cached data is wiped. LOCK only forces all
CreateFile from other threads to fail, and ensures that there are no existing
user-visible (before MJ_CLEANUP) file objects.
Then DISMOUNT disassociates the FSD's volume device object and volume
structures from the disk stack. From this on, any file operation on already
opened handle (possible only in forced dismount case) will fail, but the new
CreateFile will succeed, _performing a new mount_ and building all FSD's
structures from scratch using the disk reads.
At this point, the cache maps are still alive, but all existing file objects
referencing them (possible only in forced dismount case) are marked as "dead"
due to dismount. So, these cache maps are just in-memory junk not participating
in actual operations.
UNLOCK undoes the lock.
Then CloseHandle actually destroys the stale FSD's structures, including the
cache maps.
> So LOCK/DISMOUNT/UNLOCK is not enough.
It is enough.
>diskmgmt and chkdsk do something else in addition,
CHKDSK /F and FORMAT do exactly this, actually:
- LOCK
- their own writes (new FS creation for FORMAT)
- DISMOUNT
- UNLOCK
If LOCK fails, then CHKDSK asks for "forced dismount" - DISMOUNT without
preceding LOCK.
You should have some other issue in your code.
Yes, which means that your other advice 'If LOCK fails, then CHKDSK asks for
"forced dismount" - DISMOUNT without preceding LOCK' is irrelevant. I do
not need to ask for "forced dismount" because LOCK returns success and the
ordinary DISMOUNT returns success.
>> so my program doesn't know that Windows is preserving its obsolete cached
>> data.
>
> LOCK does not mean that the cached data is wiped. LOCK only forces all
> CreateFile from other threads to fail, and ensures that there are no
> existing user-visible (before MJ_CLEANUP) file objects.
>
> Then DISMOUNT disassociates the FSD's volume device object and volume
> structures from the disk stack. From this on, any file operation on
> already opened handle (possible only in forced dismount case) will fail,
> but the new CreateFile will succeed, _performing a new mount_ and building
> all FSD's structures from scratch using the disk reads.
So my successful LOCK and successful DISMOUNT have no useful effect? Some
other part of Windows can just proceed to do a new CreateFile and corrupt my
partition?
> At this point, the cache maps are still alive, but all existing file
> objects referencing them (possible only in forced dismount case) are
> marked as "dead" due to dismount. So, these cache maps are just in-memory
> junk not participating in actual operations.
OK, so my problem is not due to Windows preserving obsolete invalid cached
contents, my problem is because Windows does some new CreateFile and simply
writes garbage without caring what the partition actually contains now.
> UNLOCK undoes the lock.
Yes, but again it's rather useless because Windows already did its new
CreateFile and already destroyed my work.
> Then CloseHandle actually destroys the stale FSD's structures, including
> the cache maps.
Well I don't know if you mean my CloseHandle destroys my structures which
became stale when Windows did its new CreateFile, or if you mean that
Windows might do some other Close Handle, but it doesn't matter which you
mean. The damage is already done.
>> So LOCK/DISMOUNT/UNLOCK is not enough.
>
> It is enough.
It is not. I saw by experience that it isn't enough, and you proved in your
message here that it isn't enough.
>> diskmgmt and chkdsk do something else in addition,
>
> CHKDSK /F and FORMAT do exactly this, actually:
> - LOCK
> - their own writes (new FS creation for FORMAT)
> - DISMOUNT
> - UNLOCK
>
> If LOCK fails,
IRRELEVANT. LOCK SUCCEEDS.
> You should have some other issue in your code.
I do not believe you. The reason is that if I use Disk Manager to remove
the drive letter and then reassign the drive letter then there is no
corruption, and if I run CHKDSK /F then it reports that there are no
problems and then there is no corruption. The result of my program seem
perfectly fine. The problem only occurs when Windows does its own writing
when I skip these manual steps.
I suppose a programmatic solution is to do LOCK/DISMOUNT/UNLOCK as before
and then create a subprocess running CHKDSK /F ?
And this does the same remount - DISMOUNT on drive letter revocation and then
remount when Windows accesses the new drive letter (diskmgmt itself can do this
to read the volume label, for instance).
Playing with IOCTL_ON/OFFLINE_VOLUME will give you a good chance fo having the
"Lost Delayed Write Data" message for $Mft or $BitMap.
> I suppose a programmatic solution is to do LOCK/DISMOUNT/UNLOCK as
>before
I have monitored what CHKDSK /F does using an FS filter.
LOCK/DISMOUNT/UNLOCK, all from the same handle. Then the handle is closed,
which causes the FSD (I saw this in kernel debugger) to tear away all of the
old volume's structures.
The correcting writes from CHKDSK /F are done _from the same handle_ after LOCK
and before DISMOUNT.
FORMAT does the same: CreateFile for 1 handle, LOCK, write an empty new FS from
the same handle, DISMOUNT, UNLOCK, close the handle.
Well, I'm reassigning the same old drive letter not really a new letter.
Somehow it's still enough to persuade Windows to look at the actual contents
of the partition instead of relying on invalid obsolete cached contents.
This is still what I want to do programmatically.
> (diskmgmt itself can do this to read the volume label, for instance).
I don't understand the connection between that and the rest of our
discussion.
> Playing with IOCTL_ON/OFFLINE_VOLUME will give you a good chance fo having
> the "Lost Delayed Write Data" message for $Mft or $BitMap.
In all of these experiments I have not had a "Lost Delayed Write Data"
message and have not tried an NTFS partition.
>> I suppose a programmatic solution is to do LOCK/DISMOUNT/UNLOCK as before
>
> I have monitored what CHKDSK /F does using an FS filter.
>
> LOCK/DISMOUNT/UNLOCK, all from the same handle. Then the handle is closed,
> which causes the FSD (I saw this in kernel debugger) to tear away all of
> the old volume's structures.
Then LOCK/DISMOUNT/UNLOCK tore away SOME of the old volume's structures.
Some additional operation, performed by CHKDSK /F but performed by some
operation other than LOCK/DISMOUNT/UNLOCK, tears away the rest. I need to
know how to invoke that.
> The correcting writes from CHKDSK /F are done _from the same handle_ after
> LOCK and before DISMOUNT.
Sure. And if no correcting writes are needed then the same handle is still
the same handle, and yet there is some secret operation that persuades
Windows to stop using its invalid obsolete cached data.
> FORMAT does the same: CreateFile for 1 handle, LOCK, write an empty new FS
> from the same handle, DISMOUNT, UNLOCK, close the handle.
I haven't experimented with FORMAT (yet). Anyway FORMAT would not do what I
want. I don't want the partition to become corrupted, and I don't want to
lose 100% of its contents either.