File permissions are not persisted after creating hard link if system crashes

From: Vyacheslav Kovalevsky

Date: Tue Mar 03 2026 - 11:47:40 EST


Detailed description
====================

Hello, there seems to be an issue with btrfs crash behavior:

1. Create and sync a new file.
2. Open the file and change permissions.
3. Sync the file.
4. Create new hard link to file.
5. Sync the root directory.

After crash the file will have old (original) permissions, though the changes were synced.


System info
===========

Linux version 7.0-rc2, also tested on 6.19.2


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 file_fd0;
  int file_fd1;
  int root_fd;

  status = creat("file1", S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
  printf("CREAT: %d\n", status);
  file_fd0 = status;

  status = close(file_fd0);
  printf("CLOSE: %d\n", status);

  sync();

  status = open("file1", O_RDONLY);
  printf("OPEN: %d\n", status);
  file_fd1 = status;

  status = fchmod(file_fd1, S_IRWXU | S_IRWXG | S_IRWXO);
  printf("FCHMOD: %d\n", status);

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

  status = link("file1", "file2");
  printf("LINK: %d\n", status);

  status = open(".", O_RDONLY);
  printf("OPEN: %d\n", status);
  root_fd = status;

  status = fsync(root_fd);
  printf("FSYNC: %d\n", status);
}
// after crash file `file1` / `file2` has old permissions (0751 instead of 0777)
```

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 file permissions were not persisted.