The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* Symlink entry is not persisted after rename if system crashes
@ 2025-10-23 15:34 Vyacheslav Kovalevsky
  2025-10-24 11:59 ` Filipe Manana
  0 siblings, 1 reply; 2+ messages in thread
From: Vyacheslav Kovalevsky @ 2025-10-23 15:34 UTC (permalink / raw)
  To: clm, dsterba; +Cc: linux-btrfs, linux-kernel

Under some circumstances, new directory entry of a symbolic link is not 
persisted after rename if the file system crashes.



Detailed description

====================


Hello, we are doing research on testing file system crash consistency. 
During

testing we found this issue with btrfs file system. In short, a symbolic 
link

is created and renamed. Directory entries are synced using `fsync` after 
every

step. However, after a crash, the symbolic link new directory entry is not

persisted (symbolic link has the old name). Read the test below for more

details.



System info

===========


Linux version 6.18.0-rc2 (root@ubuntu) (gcc (Ubuntu 15.2.0-4ubuntu4) 
15.2.0,

GNU ld (GNU Binutils for Ubuntu) 2.45) #2 SMP PREEMPT_DYNAMIC Thu Oct 23

12:32:29 UTC 2025


Also tested on Linux 6.14.11.


Operating System: Ubuntu 25.10

CPU architecture: x86_64


btrfs-progs version: v6.16

-EXPERIMENTAL -INJECT -STATIC +LZO +ZSTD +UDEV +FSVERITY +ZONED 
CRYPTO=builtin


Tested on QEMU emulator version 10.1.1.



How to reproduce

================


```

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <string.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>


int main() {

int status;

int root_fd;

int dir_fd1;

int dir_fd2;


status = mkdir("dir", S_IRWXO);

printf("MKDIR: %d\n", status);


status = open(".", O_RDONLY | O_DIRECTORY);

printf("OPEN: %d\n", status);

root_fd = status;


// persist `dir`

status = fsync(root_fd);

printf("FSYNC: %d\n", status);


status = symlink("foobar", "dir/slink-old");

printf("SYMLINK: %d\n", status);


status = open("dir", O_RDONLY | O_DIRECTORY);

printf("OPEN: %d\n", status);

dir_fd1 = status;


// persist `slink-old`

status = fsync(dir_fd1);

printf("FSYNC: %d\n", status);


status = rename("dir/slink-old", "dir/slink-new");

printf("RENAME: %d\n", status);


status = open("dir", O_RDONLY | O_DIRECTORY);

printf("OPEN: %d\n", status);

dir_fd2 = status;


// persist `slink-new`

status = fsync(dir_fd2);

printf("FSYNC: %d\n", status);

}

```


Short test summary:


1. Directory `dir` is created.

2. Directory `.` is fsynced (`dir` entry should persist).

3. New symbolic link `slink-old` is created in `dir`.

4. Directory `dir` is fsynced using descriptor 1 (`slink-old` entry should

persist).

5. Link is renamed from `slink-old` to `slink-new`.

6. Directory `dir` is fsynced using decriptor 2 (`slink-new` entry should

persist).


Steps:


1. Create and mount new btrfs file system in default configuration.

2. Change directory to root of the file system and run the compiled test.

3. Cause hard system crash (e.g. QEMU `system_reset` command).

4. Remount file system after crash.

5. Observe that `dir` directory contains entry named `slink-old` instead of

`slink-new`.


Notes:


- In other file systems (ext4, xfs, nilfs2) the `dir` will contain new

(`slink-new`) entry, not the old one.

- The problem only affects symlinks, but not regular files.

- The problem only arises if `dir` fsyncs are made using different

descriptors.


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Symlink entry is not persisted after rename if system crashes
  2025-10-23 15:34 Symlink entry is not persisted after rename if system crashes Vyacheslav Kovalevsky
@ 2025-10-24 11:59 ` Filipe Manana
  0 siblings, 0 replies; 2+ messages in thread
From: Filipe Manana @ 2025-10-24 11:59 UTC (permalink / raw)
  To: Vyacheslav Kovalevsky; +Cc: clm, dsterba, linux-btrfs, linux-kernel

On Thu, Oct 23, 2025 at 4:38 PM Vyacheslav Kovalevsky
<slava.kovalevskiy.2014@gmail.com> wrote:
>
> Under some circumstances, new directory entry of a symbolic link is not
> persisted after rename if the file system crashes.
>
>
>
> Detailed description
>
> ====================
>
>
> Hello, we are doing research on testing file system crash consistency.
> During
>
> testing we found this issue with btrfs file system. In short, a symbolic
> link
>
> is created and renamed. Directory entries are synced using `fsync` after
> every
>
> step. However, after a crash, the symbolic link new directory entry is not
>
> persisted (symbolic link has the old name). Read the test below for more
>
> details.

Btw, the message is somewhat oddly formatted with phrases being
interrupted in the middle with blank lines.

>
>
>
> System info
>
> ===========
>
>
> Linux version 6.18.0-rc2 (root@ubuntu) (gcc (Ubuntu 15.2.0-4ubuntu4)
> 15.2.0,
>
> GNU ld (GNU Binutils for Ubuntu) 2.45) #2 SMP PREEMPT_DYNAMIC Thu Oct 23

Irrelevant information :)

>
> 12:32:29 UTC 2025
>
>
> Also tested on Linux 6.14.11.
>
>
> Operating System: Ubuntu 25.10
>
> CPU architecture: x86_64
>
>
> btrfs-progs version: v6.16
>
> -EXPERIMENTAL -INJECT -STATIC +LZO +ZSTD +UDEV +FSVERITY +ZONED
> CRYPTO=builtin
>
>
> Tested on QEMU emulator version 10.1.1.

Irrelevant too.

>
>
>
> How to reproduce
>
> ================
>
>
> ```
>
> #include <errno.h>
>
> #include <fcntl.h>
>
> #include <stdio.h>
>
> #include <string.h>
>
> #include <sys/stat.h>
>
> #include <sys/types.h>
>
> #include <unistd.h>
>
>
> int main() {
>
> int status;
>
> int root_fd;
>
> int dir_fd1;
>
> int dir_fd2;
>
>
> status = mkdir("dir", S_IRWXO);
>
> printf("MKDIR: %d\n", status);
>
>
> status = open(".", O_RDONLY | O_DIRECTORY);
>
> printf("OPEN: %d\n", status);
>
> root_fd = status;
>
>
> // persist `dir`
>
> status = fsync(root_fd);
>
> printf("FSYNC: %d\n", status);
>
>
> status = symlink("foobar", "dir/slink-old");
>
> printf("SYMLINK: %d\n", status);
>
>
> status = open("dir", O_RDONLY | O_DIRECTORY);
>
> printf("OPEN: %d\n", status);
>
> dir_fd1 = status;
>
>
> // persist `slink-old`
>
> status = fsync(dir_fd1);
>
> printf("FSYNC: %d\n", status);
>
>
> status = rename("dir/slink-old", "dir/slink-new");
>
> printf("RENAME: %d\n", status);
>
>
> status = open("dir", O_RDONLY | O_DIRECTORY);
>
> printf("OPEN: %d\n", status);
>
> dir_fd2 = status;
>
>
> // persist `slink-new`
>
> status = fsync(dir_fd2);
>
> printf("FSYNC: %d\n", status);
>
> }
>
> ```
>
>
> Short test summary:
>
>
> 1. Directory `dir` is created.
>
> 2. Directory `.` is fsynced (`dir` entry should persist).
>
> 3. New symbolic link `slink-old` is created in `dir`.
>
> 4. Directory `dir` is fsynced using descriptor 1 (`slink-old` entry should
>
> persist).
>
> 5. Link is renamed from `slink-old` to `slink-new`.
>
> 6. Directory `dir` is fsynced using decriptor 2 (`slink-new` entry should
>
> persist).
>
>
> Steps:
>
>
> 1. Create and mount new btrfs file system in default configuration.
>
> 2. Change directory to root of the file system and run the compiled test.
>
> 3. Cause hard system crash (e.g. QEMU `system_reset` command).

Btw, you can test things in a much easier way by using the dm flakey target.
No need to reboot qemu, etc. That's how we do it with fstests, and we
can even use simple shell scripting and the xfs_io utility most of the
time, no need to write C programs.

Fix sent here:

https://lore.kernel.org/linux-btrfs/cf3df42390ff83be421dcdc375d072716a67d561.1761306236.git.fdmanana@suse.com/

Thanks.

>
> 4. Remount file system after crash.
>
> 5. Observe that `dir` directory contains entry named `slink-old` instead of
>
> `slink-new`.
>
>
> Notes:
>
>
> - In other file systems (ext4, xfs, nilfs2) the `dir` will contain new
>
> (`slink-new`) entry, not the old one.
>
> - The problem only affects symlinks, but not regular files.
>
> - The problem only arises if `dir` fsyncs are made using different
>
> descriptors.
>
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-10-24 11:59 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-23 15:34 Symlink entry is not persisted after rename if system crashes Vyacheslav Kovalevsky
2025-10-24 11:59 ` Filipe Manana

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox