在 ext4 上覆盖一个小文件是原子的吗?
Is overwriting a small file atomic on ext4?
假设我们有一个 FILE_SIZE
字节的文件,并且:
FILE_SIZE <= min(page_size, physical_block_size)
;
- 文件大小永远不会改变(即永远不会执行
truncate()
或追加 write()
);
文件仅通过使用以下方法完全覆盖其内容来修改:
pwrite(fd, buf, FILE_SIZE, 0);
ext4
是否保证:
- 这样的写入相对于并发读取是原子的?
这样的写入对于系统崩溃是事务性的吗?
(即,崩溃后文件的内容完全来自之前的一些写入,我们永远不会看到部分写入或空文件)
第二个是否为真:
- 与
data=ordered
?
与 data=journal
或为单个文件启用日记功能?
(使用ioctl(fd, EXT4_IOC_SETFLAGS, EXT4_JOURNAL_DATA_FL)
)
何时 physical_block_size < FILE_SIZE <= page_size
?
我发现 related question which links discussion 是 2011 年的。但是:
- 我没有找到我的问题的明确答案
2
。
- 我想知道,如果以上内容属实,是否在某处记录?
我熟悉文件系统的一般理论,但不熟悉 Ext4 的实现。以此作为有根据的猜测。
是的,我相信一个扇区的读写是原子的,因为
- Link you provided 引用 "Currently concurrent reads/writes are atomic only wrt individual pages, however are not on the system call. "
- 磁盘扇区(512 字节)写入对他来说是原子的according to Stephen Tweedie. In private email conversation,他承认这种保证仅与硬件一样好。
- Ext 文件系统就地覆盖数据,写入时不复制。没有分配。
- 有some effort实现内联数据,非常小的文件数据可以放入inode本身。如果您只需要存储几个字节,那可能会产生影响。
不确定一页,但在完整日志记录模式下,在提交之前向日志发送少于一页是没有意义的。
根据我的实验,它不是原子的。
基本上我的实验是有两个过程,一个作家和一个reader。编写器循环写入文件,reader 从文件中读取
编写器进程:
char buf[][18] = {
"xxxxxxxxxxxxxxxx",
"yyyyyyyyyyyyyyyy"
};
i = 0;
while (1) {
pwrite(fd, buf[i], 18, 0);
i = (i + 1) % 2;
}
Reader 进程
while(1) {
pread(fd, readbuf, 18, 0);
//check if readbuf is either buf[0] or buf[1]
}
经过 运行 两个过程一段时间后,我可以看到 readbuf
是 xxxxxxxxxxxxxxxxyy
或 yyyyyyyyyyyyyyyyxx
。
因此它明确表明写入不是原子的。在我的例子中,16 字节写入总是原子的。
答案是:POSIX 不要求 writes/reads 的原子性,管道除外。我看到的 16 字节原子性是内核特定的,may/can 将来会改变。
实际回答详情post:
假设我们有一个 FILE_SIZE
字节的文件,并且:
FILE_SIZE <= min(page_size, physical_block_size)
;- 文件大小永远不会改变(即永远不会执行
truncate()
或追加write()
); 文件仅通过使用以下方法完全覆盖其内容来修改:
pwrite(fd, buf, FILE_SIZE, 0);
ext4
是否保证:
- 这样的写入相对于并发读取是原子的?
这样的写入对于系统崩溃是事务性的吗?
(即,崩溃后文件的内容完全来自之前的一些写入,我们永远不会看到部分写入或空文件)
第二个是否为真:
- 与
data=ordered
? 与
data=journal
或为单个文件启用日记功能?(使用
ioctl(fd, EXT4_IOC_SETFLAGS, EXT4_JOURNAL_DATA_FL)
)何时
physical_block_size < FILE_SIZE <= page_size
?
我发现 related question which links discussion 是 2011 年的。但是:
- 我没有找到我的问题的明确答案
2
。 - 我想知道,如果以上内容属实,是否在某处记录?
我熟悉文件系统的一般理论,但不熟悉 Ext4 的实现。以此作为有根据的猜测。
是的,我相信一个扇区的读写是原子的,因为
- Link you provided 引用 "Currently concurrent reads/writes are atomic only wrt individual pages, however are not on the system call. "
- 磁盘扇区(512 字节)写入对他来说是原子的according to Stephen Tweedie. In private email conversation,他承认这种保证仅与硬件一样好。
- Ext 文件系统就地覆盖数据,写入时不复制。没有分配。
- 有some effort实现内联数据,非常小的文件数据可以放入inode本身。如果您只需要存储几个字节,那可能会产生影响。
不确定一页,但在完整日志记录模式下,在提交之前向日志发送少于一页是没有意义的。
根据我的实验,它不是原子的。
基本上我的实验是有两个过程,一个作家和一个reader。编写器循环写入文件,reader 从文件中读取
编写器进程:
char buf[][18] = {
"xxxxxxxxxxxxxxxx",
"yyyyyyyyyyyyyyyy"
};
i = 0;
while (1) {
pwrite(fd, buf[i], 18, 0);
i = (i + 1) % 2;
}
Reader 进程
while(1) {
pread(fd, readbuf, 18, 0);
//check if readbuf is either buf[0] or buf[1]
}
经过 运行 两个过程一段时间后,我可以看到 readbuf
是 xxxxxxxxxxxxxxxxyy
或 yyyyyyyyyyyyyyyyxx
。
因此它明确表明写入不是原子的。在我的例子中,16 字节写入总是原子的。
答案是:POSIX 不要求 writes/reads 的原子性,管道除外。我看到的 16 字节原子性是内核特定的,may/can 将来会改变。
实际回答详情post: