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