阅读:3657回复:24
Lazy write导致的内容丢失问题
各位,我现在在做一个加解密的minifilter驱动,现在遇到一个问题:
我的加密头在文件首部。我在Write、read中,都会跳过这个首部(512B),通常情况下,这种情况都OK。但是发现当system进行延缓写的时候,会出现最后一部分WriteBuffer中的内容丢失,具体如下: 一个Write请求,Offset是0,WriteLength是8KB, 经过我的minifilter时,我修改offset为512,这样就跳过了我的加密头。然后发现写后返回的结果是只写了7.5KB,最后512字节没写进去,这导致文件中的512字节为随机脏数据,破坏了我的文档。 其中FileSize,AllocationSize都是足够大的,出现这个现象的原因不是因为空间不足而被截断。 我想请教各位朋友,这是因为什么,如何解决。 先多谢各位 :) |
|
最新喜欢:snox |
沙发#
发布于:2008-06-24 17:04
引用第23楼qianjunhua于2008-06-24 14:04发表的 : fcb里面直接修改文件的大小? 呵呵 好想法 这样可以吗?你试验过没 如果直接修改FCB的话 ,还不如 自己下发 setfileinformation来修改FCB 这样似乎能更好一些 |
|
|
板凳#
发布于:2008-06-24 14:04
应该是在fcb里面直接修改文件的大小,这样ntfs 在适当的时候会用fbc里面的值来调用ccsetcachefilesize 这个函数,来通知cache 这个时候文件的大小
|
|
地板#
发布于:2008-06-24 10:21
引用第20楼qianjunhua于2008-06-22 12:15发表的 : qianjunhua,你说 当 offset=>明文大小 时就会停止写, 这个确实能够解释,应用报告的 “磁盘已满”或“延迟写失败”的这种错误, 并且你说 “文件大小的时候是在一开始app 写的时候”也就是说要想解决这个问题必须在app的写的时候就改变其大小, 这个改变大小 改如何处理了?是在直接在setimforationfile处理 还是除了setimforationfile 以外的地方也要进行处理? qianjunhua 请你给个详细点的说明 ,谢谢! |
|
|
地下室#
发布于:2008-06-23 13:19
引用第20楼qianjunhua于2008-06-22 12:15发表的 : 是让cache更新fcb里的文件大小,还是更新cache里的文件大小? |
|
5楼#
发布于:2008-06-22 12:15
是的!cache的大小 从他驱动中得到的是明文的大小,也就是,那么cache的 lazy write 就是在写的时候就要比较offset 和得到的明文的大小,所以一旦=>明文大小的时候就停止写了!而且文件驱动规定了lazy write 的写的时候是不能改变文件大小的,也不能在文件尾添加。改变文件大小的时候是在一开始app 写的时候,fsd要检查是不是超过endoffile,如果超过就会setcachefile size 的这个函数来通知,然后明确的让cache 调用setimforationfile 改变大小
|
|
6楼#
发布于:2008-06-02 18:38
让CCmgr感知到文件头?如果让它感知到了,那它不会往下刷脏数据吗?
不会损毁我们自己的加在头部的加密标志吗? |
|
|
7楼#
发布于:2008-05-28 12:39
引用第17楼boxcounter于2008-05-28 11:51发表的 : 如何让CCmgr感知到文件头呢? 对缓冲读写也偏移文件头长度吗? |
|
8楼#
发布于:2008-05-28 11:51
让CCmgr感知到加密头的存在就OK了,当然我调整了整个框架实现这么个功能。
我是在NTFS上做的测试。 |
|
9楼#
发布于:2008-05-27 19:25
引用第15楼boxcounter于2008-05-27 18:41发表的 : 怎么解决的?这个问题是出现在NTFS上,还是FAT32上也会有? |
|
10楼#
发布于:2008-05-27 18:41
我已经解决了,原因是因为CCmgr不知道我的加密头的存在,导致刷脏页的时候出现这个问题。多谢各位 :)
|
|
11楼#
发布于:2008-05-26 12:41
引用第13楼goodone于2008-05-26 08:17发表的 : 一次是应用程序发的,一次是系统发的,具体我也在研究。 磁盘写是0x43,但Set的是0x42,具体flag定义参考微软文档,我也忘啦 |
|
12楼#
发布于:2008-05-26 08:17
为什么会有两次的 set了?写之前有,写完以后还有?
还有就是写磁盘的话 flag应是0x43吧 |
|
|
13楼#
发布于:2008-05-25 14:38
引用第9楼goodone于2008-05-24 11:02发表的 : 磁盘写出现之前的Set标志是A00,标志0x42的Set在磁盘写之后 |
|
14楼#
发布于:2008-05-24 14:54
引用第10楼fly1101于2008-05-24 11:34发表的 : 不是很明白你说的意思, 可以在说详细点吗? 谢谢! |
|
|
15楼#
发布于:2008-05-24 11:34
加密头在文件首部时,考虑了映射文件吗?
应用层用CreateFileMapping、MapViewOfFile 内核层用NtCreateSection、NtMapViewOfSection 这些都要处理的 |
|
16楼#
发布于:2008-05-24 11:02
引用第1楼dionysus77于2008-05-20 12:22发表的 : 通过我的观察 SetInformation的IRP是在磁盘写之前出现的。。。。 所以 应该先在 SetInformation 中修改大小 但是 如果简单的修改大小 还是会有问题 |
|
|
17楼#
发布于:2008-05-24 11:00
这个确实是个问题,帮忙顶下,
期望大牛们给个回应 |
|
|
18楼#
发布于:2008-05-23 12:14
ValidDataLength(11677)<Length: (12288).
|
|
19楼#
发布于:2008-05-23 09:36
回dionysus77兄:
可能是我的日志没说太清楚,我解释一下 :) [TFGF] PreCallback(IRP_MJ_WRITE): IrpFlags: 0x00000043, Offset(0), Length: (12288). [TFGF] PostCallback(IRP_MJ_WRITE): AllocationSize(16384), FileSize(12701), ValidDataLength(11677). [TFGF] PostCallback(IRP_MJ_WRITE): BytesWritten(10653), *Status(00000000). 这里是Paging IO,所以待写长度是页的整数倍大小(实际待写长度可能是没有这么多的),ValidDataLength就是实际上需要写的,但是实际上只写了10653, 比ValidDataLength还少1KB,而从FileSize上来看,文件的确有足够的空间可以写入ValidDataLength这么长的数据。 |
|
上一页
下一页