I’m in the midst of an HSM project, and I’ve run into an interesting
error. Our filter does restore on Read/Write to a file that has been
archived off to some server. The idea is that the first read or write
gets pended by the read/write preop callback and then it is allowed to
go down to the filesystem and proceed along its merry way. All further
IRPs aren’t pended, because the file is already back.
Currently, I’m testing this with command line copy of a file that has
been released. What I’m seeing puzzles me, and I was hoping somebody
might be able to shed some light on it. From ProcMon:
8186 3:55:39.8833130 PM cmd.exe 1900
FASTIO_NETWORK_QUERY_OPEN E:\test\bike.jpg SUCCESS
CreationTime: 9/12/2007 10:37:12 AM, LastAccessTime: 9/20/2007 3:54:11
PM, LastWriteTime: 9/20/2007 3:54:44 PM, ChangeTime: 9/20/2007 3:54:44
PM, AllocationSize: 0, EndOfFile: 0, FileAttributes: A
8187 3:55:39.8835631 PM cmd.exe 1900 IRP_MJ_CREATE E:\test
SUCCESS Desired Access: Read Data/List Directory, Synchronize,
Disposition: Open, Options: Directory, Synchronous IO Non-Alert,
Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a,
OpenResult: Opened
8188 3:55:39.8836264 PM cmd.exe 1900 IRP_MJ_DIRECTORY_CONTROL
E:\test\bike.jpg SUCCESS Type: QueryDirectory, Filter: bike.jpg,
2: bike.jpg
8189 3:55:39.8840259 PM cmd.exe 1900 IRP_MJ_CREATE
E:\test\bike.jpg SUCCESS Desired Access: Generic Read,
Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert,
Non-Directory File, Attributes: N, ShareMode: Read, Write,
AllocationSize: n/a, OpenResult:
8191 3:55:39.9815103 PM cmd.exe 1900 IRP_MJ_READ
E:test\bike.jpg INVALID DEVICE REQUEST Offset: 0, Length: 512
16017 3:55:53.5808144 PM cmd.exe 1900 IRP_MJ_CLEANUP
E:test\bike.jpg SUCCESS
16018 3:55:53.5808472 PM cmd.exe 1900 IRP_MJ_CLOSE
E:test\bike.jpg SUCCESS
The first strange thing I’m seeing is that somehow the path for the read
is missing a backslash between the drive letter and the first directory.
I don’t know where procmon gets its path from, but this looks fishy to
me. We’re using reparse points to store the data needed to get the file
back from HSM, and when there isn’t a reparse point on the file, the
path is correct. The path in the reparse point data itself is correct.
The second strange thing is that I get STATUS_INVALID_DEVICE_REQUEST
back on the read. If an erroneous path is actually making it all the
way down to NTFS, I suppose I wouldn’t really expect anything sensible
to happen. That said, the paths I’m seeing during creation are all of
the form “\Device\HarddiskVolume2\test\bike.jpg”, and it seems like it
would be a little weird for a path starting e: to make it down that far.
Further pieces of the puzzle:
The file comes back and the reparse point gets stripped off of it
correctly.
A subsequent copy on the file works correctly, I don’t do any reparse
point handling and the file copies successfully.
If I hold the message from userland back to the filter and don’t allow
the read to go down the stack, and open another command window and try
copying the file there, it works, again without any reparse point
handling. This means that the data is on disk, and everything is happy,
except for the handle that originally caused the retrieval.
I’m not yet filtering the IRP_MJ_DIRECTORY_CONTROL to lie about the size
of the file that copy should be expecting. I don’t know if this is a
related problem or not, or if it’s even a problem at all, but it seems
like it’s worth mentioning.
I looked at the FastFat code to see when that error is returned, but I
didn’t see anything obviously relevant to doing a READ. It seems to be
more likely to happen during an IRP_FILE_SYSTEM_CONTROL, which we’re not
doing. I’m assuming that FAT isn’t completely representative of NTFS in
this case.
Given these pieces, would anybody care to suggest where I might start?
The file name thing is the most obviously “wrong” thing going on here,
but I’m wondering if it’s a red herring or if it’s a symptom rather than
a cause. Thoughts?
Thanks,
~Eric