有没有办法在 eMMC 上以原子方式将文件和目录从 tempfs 移动到 ext4 分区

ART*_*ART 3 linux embedded ext4 rename tmpfs

我们有基于 beaglebone 黑色的定制板,具有 256MB RAM 和 4GB eMMC。主板运行 Linux 内核 4.9

我们遇到了一种情况,我们在其中创建了一个文件tempfs,然后在验证之后,我们必须将它移动到 eMMC 的 ext4 分区。只归档一个certificate

在某些情况下,我们在一个目录中有多个证书,因此我们必须将整个目录从 tempfs 移动到 eMMC 上的 ext4 分区。

所以,我们所担心的问题之一是atomicitymv(移动)操作。

根据rename系统调用 Linux 手册页重命名文件是一个原子操作。 http://man7.org/linux/man-pages/man2/rename.2.html

但是我们不确定重命名操作是否涉及在两个文件系统之间移动文件,原子性仍然可用。所以问题是将文件从原子移动tmpfsext4原子吗?

显然,一种可能的解决方案是将文件保存在同一分区上的不同文件夹中(显然在同一文件系统上)并使用mv. 对于使用以下重命名方法的目录

SRC_dir  --> TMP_DEST_dir
DEST_dir --> BAK_DEST_dir
TMP_DEST_dir --> DEST_dir
delete BAK_DEST_dir
Run Code Online (Sandbox Code Playgroud)

对替代品的任何建议?

编辑
在我得到回复后,我尝试在板上遵循测试代码,

#include <stdio.h>
#include <errno.h>

int main()
{
    int retcode = 0;

    system("touch /tmp/rename_test");

    retcode = rename("/tmp/rename_test", "/home/fs_rename_test");

    if ( retcode < 0) {
        printf("errno : %d\n",errno );
        perror("Error occurred while renaming file");
        return 1;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

返回以下输出。并确认重命名不适用于跨文件系统。

errno : 18
Error occurred while renaming file: Invalid cross-device link
Run Code Online (Sandbox Code Playgroud)

ilk*_*chu 5

从移动文件tmpfsext4原子?

不可以。重命名只能在文件系统中使用。手册页rename(2)明确提到了尝试跨挂载点重命名时返回的错误:

EXDEV oldpathnewpath不在同一个挂载的文件系统上。

跨文件系统的移动需要结合复制和删除来完成。mv如果rename()不起作用,它将为您执行此操作,但在这种情况下它不会是原子的。

解决这个问题的简单方法确实是首先将文件复制到同一文件系统上的临时位置。通常,将临时文件放在与最终目标相同的目录中是最简单的,因为这是唯一保证位于同一文件系统上的位置。当然,这要求处理文件的任何进程都有一些逻辑来根据其名称忽略临时文件。

粗略地说,这样的事情应该适用于一个文件:

cp /src/filename /dst/filename.tmp &&
mv /dst/filename.tmp /dst/filename &&
rm /src/filename
Run Code Online (Sandbox Code Playgroud)

请注意,您为目录描述的过程本质上是这样的:

cp -r /src/dir /dst/dir.tmp && 
mv /dst/dir /dst/dir.bak    &&
mv /dst/dir.tmp /dst/dir    &&
rm -r /dst/dir.bak
Run Code Online (Sandbox Code Playgroud)

这还不错,但不是原子的。两次运行mv(或调用rename())之间有一段时间,当/dst/dir不存在时。这可以通过通过符号链接访问目录来解决,因为可以用重命名原子地替换链接。