阅读:4890回复:4
这大概就是double fcbs吧
copy from OSR list, copyrights belong to author.
Once again, we've come across one of those complex situations where trying to use file objects within a filter (or layered file system - the difference is pretty much semantic) is creating problems. In thinking about this issue, I've concluded that I can do at least one thing to identify this class of problem and suggest how filters can ensure they "play nice" in such situations. We've used the term "shadow file object" for at least the past dozen years (ever since the first time we used it to build a filter that allowed dismounting an NTFS file system while it was still active. By the way, that's one way to ensure you can flush the NTFS cache because the on-disk state has changed. I don't recommend it for the faint of heart, but for that specific customer it provided the functionality they required so they could share NTFS disks between multiple machines simultaneously.) I'll use that terminology now, and I hear folks in Redmond using it as well. In a "shadow file object" model the filter/layered-FSD obtains the original I/O Manager created file object in its IRP_MJ_CREATE dispatch handler. It creates a second file object and sends that second file object down to the underlying FSD. The first file object then points to the filter/layered-FSD device. This gives the filter the ability to do several things: - Control the FsContext/FsContext2 fields. After all, the file object now belongs to the filter/layered-FSD. - Control the cache. We can set up the SOP structures to point to things we (in the filter/layered-FSD) control. Indeed, it is this "we can control the cache" that leads to the very idea of thinking of this as more a layered FSD than a filter. The mechanics are mostly the same. - Point to our control device. This is actually where a filter splits from a layered FSD. When we first started doing this, we did it in a filter model. We ran into interesting issues with the DeviceObject and Vpb fields of the file object. These point to the FSD, not to the filter. There is no OS supported way to change these in a safe fashion, and changing these pointers around to point to the "right place" requires adjusting reference counts (and not adjusting reference counts leads to other nasty problems.) That's why we now use STATUS_REPARSE - it's the only documented way to get the I/O Manager to point to the right device (although it means filters above us see STATUS_REPARSE all the time and some don't like that, although it's really no different than what one can see on a server with SIS installed.) The # 1 problem we've had over the years is that, try as we might, people will send our file objects (the one that points to our filter/layered-FSD) to NTFS. NTFS will blow up in a function called NtfsDecodeFileObject. The usual proof here is that when I look at the device object in the IRP, it's NTFS and when I look at the device object in the file object, it's our filter/layered-FSD. Naturally, it MUST be our fault (although we didn't write the code to send the file object to the wrong file system - and there's not much we can DO to "fix that." At least not much I'm willing to put in a commercial product.) Of course, if you use just our filter/layered-FSD it works fine. If you use just the other filter, it works fine. Only when you combine the two does it not work properly. The issue here is "how do I obtain the right target for my request in a file system filter driver". The correct function to use is IoGetRelatedDeviceObject - it takes the file object in question. If the filter/layered-FSD has done its job right, the file object is set up properly. It might not have a Vpb (ah, but SR will dereference the Vpb anyway, as we found out on XP.) Some OS components insist that it point to the media volume (e.g., Win32k.sys in Vista will do this for the keyboard DLL. Nothing like having a system crash during boot all because someone decided that what they got back MUST point to exactly the device they started with in the first place.) IoGetRelatedDeviceObject does this translation right. It's not horribly expensive (it's just following pointers.) So, my admonishment to filter driver writers: don't traverse the FO pointers directly. In the case I looked at this morning, it appears they followed FO->DeviceObject->Vpb->DeviceObject. That won't work if the volume has been formatted and/or dismounted, since FO->Vpb won't be FO->DeviceObject->Vpb. It's a lurking bug in that filter anyway, but one they probably won't see very often. Of course, since we cause this situation to arise "all the time" the system blows up. Use IoGetRelatedDeviceObject. My second suggestion is to those writing file system drivers - rather than blindly assume the components above you are "doing the right thing", when you decode a file object, make sure it points to the right device object. If it doesn't, you can return an error. This isn't so hard - we get two arguments in the create entry point and all of us go through some variation of "NtfsDecodeFileObject". Just add a check to make sure it points to the device object we were passed. ONLY file systems can do this. Filters cannot, since this check will only work for the "owner" of the file object. But if FO->DeviceObject != DeviceObject (from the passed in parameter) something's broken. You can bug check (but could make it obvious) or you can return an error (I'm a proponent of the error path, but that's because when I bug check, I field the support call.) Maybe this can be turned into a verifier check, or perhaps it belongs in the checked build or something, but I stumble across this frequently enough I know that it's still a common issue. Shadow file objects are very powerful, particularly when you want to control the presentation of data in a layered approach. However, using them turns out to be much more complicated than anyone first approaching the field would believe. While I'm a proponent of the STATUS_REPARSE technique of adjusting reference counts, I know there are some who would prefer if we did it a different way (although I've yet to see one that works robustly - although it's often easy to make them work in isolation and with limited testing.) Oh, and just wait until you learn how much fun shadow file objects are when you combine them with transactions. I'll get down off the soapbox now. Tony OSR |
|
最新喜欢:tc8911... |
沙发#
发布于:2009-07-13 19:51
I prefer the layered file system approach. I've done this four times
now. The first time was a filter that used shadow file objects and it turned out to be amazingly complicated because no matter what we did, we found other components would pass our file objects to the native file system - which then died. The second time we did this, we tried to do it by "taking over" the symbolic link for the drive, pointing to our separate file system and then talking to the native file system. That solved the "but my file object goes to the wrong place" issue but made a number of things MUCH more complicated (like files we didn't want to track.) The third time, we did it JUST for NTFS with ADS; that approach worked very well. The fourth time is our toolkit - it uses a filter to redirect to a separate stack (so we have a layered file system) the files of interest. We use shadow file objects and we implement in the file structure a log-structure so that we can add the ADS abstraction independent of what the underlying FSD actually supports. |
|
板凳#
发布于:2009-07-13 22:14
Tony was actually talking about a real layered file system, OSR's DMK.
|
|
地板#
发布于:2009-07-15 10:13
I see, I see the price also.....
|
|
地下室#
发布于:2009-07-16 11:13
学习学习。顶起。。。
|
|