NTFS 文件系统的 USN 日志可以大于它声明的大小吗?

Posted

技术标签:

【中文标题】NTFS 文件系统的 USN 日志可以大于它声明的大小吗?【英文标题】:Can the USN Journal of the NTFS file system be bigger than it's declared size? 【发布时间】:2013-02-26 12:11:22 【问题描述】:

各位程序员大家好。

我正在尝试使用 WinIoCtl 函数转储 NTFS 分区的 USN 日志的内容。我有 *USN_JOURNAL_DATA* 结构,它告诉我它的最大大小为 512 MB。我已经将它与 fsutil 所说的进行了比较,它的价值相同。

现在我必须将每个条目读入 *USN_RECORD* 结构。我在一个从 0 开始的 for 循环中执行此操作,并以 4096(簇大小)为增量达到日志的最大大小。 我在相同大小的缓冲区中读取每个 4096 字节,并从中读取所有 USN_RECORD 结构。

一切顺利,文件名正确,时间戳也正确,原因,一切,除了我似乎遗漏了一些最近的记录。我在分区上创建了一个新文件,在其中写入了一些内容,然后删除了该文件。我再次运行该应用程序并没有出现记录。我发现只有当我继续阅读超过期刊的最大尺寸时才会出现记录。怎么可能?

目前,我正在从 Journal 的数据开始读取到 最大大小 + 分配增量(两者都是存储在 *USN_JOURNAL_DATA* 结构中的值) 我不认为这是正确的,而且我很难找到与此相关的详尽信息。

有人可以解释一下吗? USN 日志周围是否有类似于 MFT 工作方式的缓冲区(意味着当其他文件需要磁盘空间时,它的大小减半)?

我做错了什么?

【问题讨论】:

【参考方案1】:

这是预期的行为,as documented:

最大尺寸

更改日志的目标最大大小,以字节为单位。 更改日志可能会大于此值,但随后会在下一个 NTFS 文件系统检查点被截断到小于此值。

不要尝试预先确定大小,而是循环直到到达数据的末尾。

如果您使用FSCTL_ENUM_USN_DATA 控制代码,当DeviceIoControl 的错误代码为ERROR_HANDLE_EOF 时,您已到达数据末尾。

如果您使用FSCTL_READ_USN_JOURNAL控制代码,当驱动返回的下一个USN(输出缓冲区开头的DWORDLONG)是您请求的USN(值StartUsn 在输入缓冲区中)。您需要将输入参数BytesToWaitFor 设置为零,否则驱动程序将等待指定数量的新数据添加到日志中。

【讨论】:

谢谢。没想到:) 实际上,DeviceIoControl 不返回 LSTATUS,它返回一个 BOOL 指示它是否失败。但是我一直循环直到 GetLastError() 返回 ERROR_HANDLE_EOF 但它没有返回该代码,它只是不断循环并显示最近对 USN 日志的更改。有点像它会一遍又一遍地读取最后的 X 个字节。所以要最终停止循环,你必须循环直到返回的缓冲区没有改变,但这不能保证我们阅读了整个 USN 日志。循环直到偏移量达到 MaximumSize + AllocationDelta 似乎可行。 你用的是什么IO控制码?我的代码使用FSCTL_ENUM_USN_DATA,在到达 MFT 末尾时肯定会收到 ERROR_HANDLE_EOF。见***.com/a/7459109/886887 (请注意,在处理 Windows API 时,“F 返回错误代码 X”通常是“F 返回 FALSE 并且 GetLastError() 返回错误代码 X”的简写;这只是其中之一被认为是理所当然的。) 我使用了 FSCTL_READ_USN_JOURNAL。谢谢你的更新。我不断更新请求的 USN 以便获得所有 USN 条目,但我使用缓冲区中的 USN 记录号对其进行更新,因此将一次又一次地请求最后一个条目。我也未能区分 FSCTL_READ_USN_JOURNAL 和 FSCTL_ENUM_USN_DATA。谢谢你为我解决这个问题。 :)

以上是关于NTFS 文件系统的 USN 日志可以大于它声明的大小吗?的主要内容,如果未能解决你的问题,请参考以下文章

USN日志是默认禁用的吗?

USN NFTS 更改通知事件中断

why "Everything" is so fast?

NTFS文件系统的简述

JNA 访问 NTFS USN (win32)。如何从内存对象中获取数据?

ntfs格式是啥