Re: Is rename(2) atomic on FAT?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Chris,

[CC'ing fsdevel and Pali]

On Mon, Oct 21, 2019 at 9:59 PM Chris Murphy <lists@xxxxxxxxxxxxxxxxx> wrote:
>
> http://man7.org/linux/man-pages/man2/rename.2.html
>
> Use case is atomically updating bootloader configuration on EFI System
> partitions. Some bootloader implementations have configuration files
> bigger than 512 bytes, which could possibly be torn on write. But I'm
> also not sure what write order FAT uses.
>
> 1.
> FAT32 file system is mounted at /boot/efi
>
> 2.
> # echo "hello" > /boot/efi/tmp/test.txt
> # mv /boot/efi/tmp/test.txt /boot/efi/EFI/fedora/
>
> 3.
> When I strace the above mv command I get these lines:
> ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
> renameat2(AT_FDCWD, "/boot/efi/tmp/test.txt", AT_FDCWD,
> "/boot/efi/EFI/fedora/", RENAME_NOREPLACE) = -1 EEXIST (File exists)
> stat("/boot/efi/EFI/fedora/", {st_mode=S_IFDIR|0700, st_size=1024, ...}) = 0
> renameat2(AT_FDCWD, "/boot/efi/tmp/test.txt", AT_FDCWD,
> "/boot/efi/EFI/fedora/test.txt", RENAME_NOREPLACE) = 0
> lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
> close(0)
>
> I can't tell from documentation if renameat2() with flag
> RENAME_NOREPLACE is atomic, assuming the file doesn't exist at
> destination.
>
> 4.
> Do it again exactly as before, small change
> # echo "hello" > /boot/efi/tmp/test.txt
> # mv /boot/efi/tmp/test.txt /boot/efi/EFI/fedora/
>
> 5.
> The strace shows fallback to rename()
>
> ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
> renameat2(AT_FDCWD, "/boot/efi/tmp/test.txt", AT_FDCWD,
> "/boot/efi/EFI/fedora/", RENAME_NOREPLACE) = -1 EEXIST (File exists)
> stat("/boot/efi/EFI/fedora/", {st_mode=S_IFDIR|0700, st_size=1024, ...}) = 0
> renameat2(AT_FDCWD, "/boot/efi/tmp/test.txt", AT_FDCWD,
> "/boot/efi/EFI/fedora/test.txt", RENAME_NOREPLACE) = -1 EEXIST (File
> exists)
> lstat("/boot/efi/tmp/test.txt", {st_mode=S_IFREG|0700, st_size=7, ...}) = 0
> newfstatat(AT_FDCWD, "/boot/efi/EFI/fedora/test.txt",
> {st_mode=S_IFREG|0700, st_size=6, ...}, AT_SYMLINK_NOFOLLOW) = 0
> geteuid()                               = 0
> rename("/boot/efi/tmp/test.txt", "/boot/efi/EFI/fedora/test.txt") = 0
> lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
> close(0)                                = 0
>
>
> Per documentation that should be atomic. So the questions are, are
> both atomic, or neither atomice, and if not what should be used to
> ensure bootloader updates are atomic.

According of my understanding of FAT rename() is not atomic at all.
It can downgrade to a hardlink. i.e. rename("foo", "bar") can result in having
both "foo" and "bar."
...or worse.

Pali has probably more input to share. :-)

> There are plausibly three kinds:
>
> A. write a new file with file name that doesn't previously exist
> B. write a new file with a new file name, then do a rename stomping on
> the old one
> C. overwrite an existing file
>
> It seems C is risky. It probably isn't atomic and can't be made to be
> atomic on FAT.
>
>
> --
> Chris Murphy

-- 
Thanks,
//richard



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux