mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* File system corruption after renaming directory and creating a new file with same name if system crashes
@ 2025-11-27 13:53 Vyacheslav Kovalevsky
  2025-11-27 18:22 ` Filipe Manana
  0 siblings, 1 reply; 2+ messages in thread
From: Vyacheslav Kovalevsky @ 2025-11-27 13:53 UTC (permalink / raw)
  To: clm, dsterba; +Cc: linux-btrfs, linux-kernel

File system becomes corrupted after renaming directory, creating and 
syncing a new file with the same name if system crashes.


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

Hello, we have found another issue with btrfs crash behavior.

In short, two directories are created and synced. Then, first directory 
is renamed as subdirectory of the second directory. A new file is 
created with name that was previously associated with the first 
directory. The file is fsync'ed and moved under the renamed directory 
and fsync'ed again. After a crash, file system cannot be mounted, 
reporting block corruption.

It seems that the directory entry becomes corrupted when the `nlink` 
value is erroneously set to 2, somehow.


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

Linux version 6.18.0-rc7, also tested on 6.18.0-rc2 and 6.14.11.


How to reproduce
================

Test:

```
#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_fd;

   status = mkdir("dir1", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
   printf("MKDIR: %d\n", status);

   status = mkdir("dir2", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
   printf("MKDIR: %d\n", status);

   sync();

   status = rename("dir1", "dir2/dir3");
   printf("RENAME: %d\n", status);

   // create regular file with the name directory had before rename
   status = open("dir1", O_RDWR | O_CREAT);
   printf("OPEN: %d\n", status);
   file_fd = status;

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

   status = rename("dir1", "dir2/dir3/not-dir");
   printf("RENAME: %d\n", status);

   status = fsync(file_fd);
   printf("FSYNC: %d\n", status);
}
```

dmesg:

```
[ 17.559361] BTRFS: device fsid 17a75b88-e58e-457d-83db-ea6599920bc7 
devid 1 transid 9 /dev/vdb (253:16) scanned by mount (1095)
[ 17.559676] BTRFS info (device vdb): first mount of filesystem 
17a75b88-e58e-457d-83db-ea6599920bc7
[ 17.559690] BTRFS info (device vdb): using crc32c (crc32c-lib) checksum 
algorithm
[ 17.562785] BTRFS info (device vdb): start tree-log replay
[ 17.563301] page: refcount:2 mapcount:0 mapping:0000000077ae2817 
index:0x1d00 pfn:0x1057ac
[ 17.563305] memcg:ffff89a500340000
[ 17.563307] aops:btree_aops ino:1
[ 17.563311] flags: 
0x17ffffc800402a(uptodate|lru|private|writeback|node=0|zone=2|lastcpupid=0x1fffff)
[ 17.563315] raw: 0017ffffc800402a fffff9aa84135708 fffff9aa84073d88 
ffff89a51cb23a90
[ 17.563318] raw: 0000000000001d00 ffff89a502951b40 00000002ffffffff 
ffff89a500340000
[ 17.563319] page dumped because: eb page dump
[ 17.563320] BTRFS critical (device vdb): corrupt leaf: root=5 
block=30408704 slot=6 ino=257, invalid nlink: has 2 expect no more than 
1 for dir
[ 17.564768] BTRFS info (device vdb): leaf 30408704 gen 10 total ptrs 17 
free space 14869 owner 5
[ 17.564772] item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160
[ 17.564775] inode generation 3 transid 9 size 16 nbytes 16384
[ 17.564776] block group 0 mode 40755 links 1 uid 0 gid 0
[ 17.564778] rdev 0 sequence 2 flags 0x0
[ 17.564779] atime 1764249615.0
[ 17.564781] ctime 1764249645.130028300
[ 17.564782] mtime 1764249645.130028300
[ 17.564784] otime 1764249615.0
[ 17.564785] item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12
[ 17.564787] index 0 name_len 2
[ 17.564789] item 2 key (256 DIR_ITEM 2363071922) itemoff 16077 itemsize 34
[ 17.564791] location key (257 1 0) type 2
[ 17.564792] transid 9 data_len 0 name_len 4
[ 17.564794] item 3 key (256 DIR_ITEM 2676584006) itemoff 16043 itemsize 34
[ 17.564795] location key (258 1 0) type 2
[ 17.564797] transid 9 data_len 0 name_len 4
[ 17.564798] item 4 key (256 DIR_INDEX 2) itemoff 16009 itemsize 34
[ 17.564800] location key (257 1 0) type 2
[ 17.564801] transid 9 data_len 0 name_len 4
[ 17.564803] item 5 key (256 DIR_INDEX 3) itemoff 15975 itemsize 34
[ 17.564805] location key (258 1 0) type 2
[ 17.564806] transid 9 data_len 0 name_len 4
[ 17.564807] item 6 key (257 INODE_ITEM 0) itemoff 15815 itemsize 160
[ 17.564809] inode generation 9 transid 10 size 14 nbytes 0
[ 17.564811] block group 0 mode 40755 links 2 uid 0 gid 0
[ 17.564812] rdev 0 sequence 1 flags 0x0
[ 17.564813] atime 1764249645.130028300
[ 17.564815] ctime 1764249645.130028300
[ 17.564816] mtime 1764249645.130028300
[ 17.564818] otime 1764249645.130028300
[ 17.564819] item 7 key (257 INODE_REF 256) itemoff 15801 itemsize 14
[ 17.564821] index 2 name_len 4
[ 17.564822] item 8 key (257 INODE_REF 258) itemoff 15787 itemsize 14
[ 17.564824] index 2 name_len 4
[ 17.564825] item 9 key (257 DIR_ITEM 3753155587) itemoff 15750 itemsize 37
[ 17.564827] location key (259 1 0) type 1
[ 17.564828] transid 10 data_len 0 name_len 7
[ 17.564830] item 10 key (257 DIR_INDEX 2) itemoff 15713 itemsize 37
[ 17.564831] location key (259 1 0) type 1
[ 17.564833] transid 10 data_len 0 name_len 7
[ 17.564834] item 11 key (258 INODE_ITEM 0) itemoff 15553 itemsize 160
[ 17.564836] inode generation 9 transid 10 size 8 nbytes 0
[ 17.564837] block group 0 mode 40755 links 1 uid 0 gid 0
[ 17.564839] rdev 0 sequence 1 flags 0x0
[ 17.564840] atime 1764249645.130028300
[ 17.564842] ctime 1764249645.130028300
[ 17.564843] mtime 1764249645.130028300
[ 17.564844] otime 1764249645.130028300
[ 17.564846] item 12 key (258 INODE_REF 256) itemoff 15539 itemsize 14
[ 17.564847] index 3 name_len 4
[ 17.564849] item 13 key (258 DIR_ITEM 1843588421) itemoff 15505 itemsize 34
[ 17.564851] location key (257 1 0) type 2
[ 17.564852] transid 10 data_len 0 name_len 4
[ 17.564853] item 14 key (258 DIR_INDEX 2) itemoff 15471 itemsize 34
[ 17.564855] location key (257 1 0) type 2
[ 17.564856] transid 10 data_len 0 name_len 4
[ 17.564858] item 15 key (259 INODE_ITEM 0) itemoff 15311 itemsize 160
[ 17.564860] inode generation 10 transid 10 size 0 nbytes 0
[ 17.564861] block group 0 mode 100000 links 1 uid 0 gid 0
[ 17.564863] rdev 0 sequence 2 flags 0x0
[ 17.564864] atime 1764249645.139028211
[ 17.564865] ctime 1764249645.140028202
[ 17.564867] mtime 1764249645.139028211
[ 17.564868] otime 1764249645.139028211
[ 17.564869] item 16 key (259 INODE_REF 257) itemoff 15294 itemsize 17
[ 17.564870] index 2 name_len 7
[ 17.564872] BTRFS error (device vdb): block=30408704 write time tree 
block corruption detected
[ 17.566147] BTRFS: error (device vdb) in btrfs_commit_transaction:2535: 
errno=-5 IO failure (Error while writing out transaction)
[ 17.567374] BTRFS warning (device vdb state E): Skipping commit of 
aborted transaction.
[ 17.567377] BTRFS error (device vdb state EA): Transaction aborted 
(error -5)
[ 17.568502] BTRFS: error (device vdb state EA) in 
cleanup_transaction:2020: errno=-5 IO failure
[ 17.569956] BTRFS: error (device vdb state EA) in 
btrfs_replay_log:2093: errno=-5 IO failure (Failed to recover log tree)
[ 17.571778] BTRFS error (device vdb state EA): open_ctree failed: -5
```

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 mount fails.

Notes:

- if path in open() is changed to any other name (instead of `dir1`) the 
bug will not manifest.


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

* Re: File system corruption after renaming directory and creating a new file with same name if system crashes
  2025-11-27 13:53 File system corruption after renaming directory and creating a new file with same name if system crashes Vyacheslav Kovalevsky
@ 2025-11-27 18:22 ` Filipe Manana
  0 siblings, 0 replies; 2+ messages in thread
From: Filipe Manana @ 2025-11-27 18:22 UTC (permalink / raw)
  To: Vyacheslav Kovalevsky; +Cc: clm, dsterba, linux-btrfs, linux-kernel

On Thu, Nov 27, 2025 at 1:58 PM Vyacheslav Kovalevsky
<slava.kovalevskiy.2014@gmail.com> wrote:
>
> File system becomes corrupted after renaming directory, creating and
> syncing a new file with the same name if system crashes.
>
>
> Detailed description
> ====================
>
> Hello, we have found another issue with btrfs crash behavior.
>
> In short, two directories are created and synced. Then, first directory
> is renamed as subdirectory of the second directory. A new file is
> created with name that was previously associated with the first
> directory. The file is fsync'ed and moved under the renamed directory
> and fsync'ed again.

It doesn't need to be under the renamed directory, it can be any directory.

> After a crash, file system cannot be mounted,
> reporting block corruption.
>
> It seems that the directory entry becomes corrupted when the `nlink`

Not the directory entry but the directory inode.

Fix sent a few minutes ago:

https://lore.kernel.org/linux-btrfs/973df1035d967979681ed741f074e5db90aa4f70.1764264662.git.fdmanana@suse.com/

Thanks.

> value is erroneously set to 2, somehow.
>
>
> System info
> ===========
>
> Linux version 6.18.0-rc7, also tested on 6.18.0-rc2 and 6.14.11.
>
>
> How to reproduce
> ================
>
> Test:
>
> ```
> #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_fd;
>
>    status = mkdir("dir1", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
>    printf("MKDIR: %d\n", status);
>
>    status = mkdir("dir2", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
>    printf("MKDIR: %d\n", status);
>
>    sync();
>
>    status = rename("dir1", "dir2/dir3");
>    printf("RENAME: %d\n", status);
>
>    // create regular file with the name directory had before rename
>    status = open("dir1", O_RDWR | O_CREAT);
>    printf("OPEN: %d\n", status);
>    file_fd = status;
>
>    status = fsync(file_fd);
>    printf("FSYNC: %d\n", status);
>
>    status = rename("dir1", "dir2/dir3/not-dir");
>    printf("RENAME: %d\n", status);
>
>    status = fsync(file_fd);
>    printf("FSYNC: %d\n", status);
> }
> ```
>
> dmesg:
>
> ```
> [ 17.559361] BTRFS: device fsid 17a75b88-e58e-457d-83db-ea6599920bc7
> devid 1 transid 9 /dev/vdb (253:16) scanned by mount (1095)
> [ 17.559676] BTRFS info (device vdb): first mount of filesystem
> 17a75b88-e58e-457d-83db-ea6599920bc7
> [ 17.559690] BTRFS info (device vdb): using crc32c (crc32c-lib) checksum
> algorithm
> [ 17.562785] BTRFS info (device vdb): start tree-log replay
> [ 17.563301] page: refcount:2 mapcount:0 mapping:0000000077ae2817
> index:0x1d00 pfn:0x1057ac
> [ 17.563305] memcg:ffff89a500340000
> [ 17.563307] aops:btree_aops ino:1
> [ 17.563311] flags:
> 0x17ffffc800402a(uptodate|lru|private|writeback|node=0|zone=2|lastcpupid=0x1fffff)
> [ 17.563315] raw: 0017ffffc800402a fffff9aa84135708 fffff9aa84073d88
> ffff89a51cb23a90
> [ 17.563318] raw: 0000000000001d00 ffff89a502951b40 00000002ffffffff
> ffff89a500340000
> [ 17.563319] page dumped because: eb page dump
> [ 17.563320] BTRFS critical (device vdb): corrupt leaf: root=5
> block=30408704 slot=6 ino=257, invalid nlink: has 2 expect no more than
> 1 for dir
> [ 17.564768] BTRFS info (device vdb): leaf 30408704 gen 10 total ptrs 17
> free space 14869 owner 5
> [ 17.564772] item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160
> [ 17.564775] inode generation 3 transid 9 size 16 nbytes 16384
> [ 17.564776] block group 0 mode 40755 links 1 uid 0 gid 0
> [ 17.564778] rdev 0 sequence 2 flags 0x0
> [ 17.564779] atime 1764249615.0
> [ 17.564781] ctime 1764249645.130028300
> [ 17.564782] mtime 1764249645.130028300
> [ 17.564784] otime 1764249615.0
> [ 17.564785] item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12
> [ 17.564787] index 0 name_len 2
> [ 17.564789] item 2 key (256 DIR_ITEM 2363071922) itemoff 16077 itemsize 34
> [ 17.564791] location key (257 1 0) type 2
> [ 17.564792] transid 9 data_len 0 name_len 4
> [ 17.564794] item 3 key (256 DIR_ITEM 2676584006) itemoff 16043 itemsize 34
> [ 17.564795] location key (258 1 0) type 2
> [ 17.564797] transid 9 data_len 0 name_len 4
> [ 17.564798] item 4 key (256 DIR_INDEX 2) itemoff 16009 itemsize 34
> [ 17.564800] location key (257 1 0) type 2
> [ 17.564801] transid 9 data_len 0 name_len 4
> [ 17.564803] item 5 key (256 DIR_INDEX 3) itemoff 15975 itemsize 34
> [ 17.564805] location key (258 1 0) type 2
> [ 17.564806] transid 9 data_len 0 name_len 4
> [ 17.564807] item 6 key (257 INODE_ITEM 0) itemoff 15815 itemsize 160
> [ 17.564809] inode generation 9 transid 10 size 14 nbytes 0
> [ 17.564811] block group 0 mode 40755 links 2 uid 0 gid 0
> [ 17.564812] rdev 0 sequence 1 flags 0x0
> [ 17.564813] atime 1764249645.130028300
> [ 17.564815] ctime 1764249645.130028300
> [ 17.564816] mtime 1764249645.130028300
> [ 17.564818] otime 1764249645.130028300
> [ 17.564819] item 7 key (257 INODE_REF 256) itemoff 15801 itemsize 14
> [ 17.564821] index 2 name_len 4
> [ 17.564822] item 8 key (257 INODE_REF 258) itemoff 15787 itemsize 14
> [ 17.564824] index 2 name_len 4
> [ 17.564825] item 9 key (257 DIR_ITEM 3753155587) itemoff 15750 itemsize 37
> [ 17.564827] location key (259 1 0) type 1
> [ 17.564828] transid 10 data_len 0 name_len 7
> [ 17.564830] item 10 key (257 DIR_INDEX 2) itemoff 15713 itemsize 37
> [ 17.564831] location key (259 1 0) type 1
> [ 17.564833] transid 10 data_len 0 name_len 7
> [ 17.564834] item 11 key (258 INODE_ITEM 0) itemoff 15553 itemsize 160
> [ 17.564836] inode generation 9 transid 10 size 8 nbytes 0
> [ 17.564837] block group 0 mode 40755 links 1 uid 0 gid 0
> [ 17.564839] rdev 0 sequence 1 flags 0x0
> [ 17.564840] atime 1764249645.130028300
> [ 17.564842] ctime 1764249645.130028300
> [ 17.564843] mtime 1764249645.130028300
> [ 17.564844] otime 1764249645.130028300
> [ 17.564846] item 12 key (258 INODE_REF 256) itemoff 15539 itemsize 14
> [ 17.564847] index 3 name_len 4
> [ 17.564849] item 13 key (258 DIR_ITEM 1843588421) itemoff 15505 itemsize 34
> [ 17.564851] location key (257 1 0) type 2
> [ 17.564852] transid 10 data_len 0 name_len 4
> [ 17.564853] item 14 key (258 DIR_INDEX 2) itemoff 15471 itemsize 34
> [ 17.564855] location key (257 1 0) type 2
> [ 17.564856] transid 10 data_len 0 name_len 4
> [ 17.564858] item 15 key (259 INODE_ITEM 0) itemoff 15311 itemsize 160
> [ 17.564860] inode generation 10 transid 10 size 0 nbytes 0
> [ 17.564861] block group 0 mode 100000 links 1 uid 0 gid 0
> [ 17.564863] rdev 0 sequence 2 flags 0x0
> [ 17.564864] atime 1764249645.139028211
> [ 17.564865] ctime 1764249645.140028202
> [ 17.564867] mtime 1764249645.139028211
> [ 17.564868] otime 1764249645.139028211
> [ 17.564869] item 16 key (259 INODE_REF 257) itemoff 15294 itemsize 17
> [ 17.564870] index 2 name_len 7
> [ 17.564872] BTRFS error (device vdb): block=30408704 write time tree
> block corruption detected
> [ 17.566147] BTRFS: error (device vdb) in btrfs_commit_transaction:2535:
> errno=-5 IO failure (Error while writing out transaction)
> [ 17.567374] BTRFS warning (device vdb state E): Skipping commit of
> aborted transaction.
> [ 17.567377] BTRFS error (device vdb state EA): Transaction aborted
> (error -5)
> [ 17.568502] BTRFS: error (device vdb state EA) in
> cleanup_transaction:2020: errno=-5 IO failure
> [ 17.569956] BTRFS: error (device vdb state EA) in
> btrfs_replay_log:2093: errno=-5 IO failure (Failed to recover log tree)
> [ 17.571778] BTRFS error (device vdb state EA): open_ctree failed: -5
> ```
>
> 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 mount fails.
>
> Notes:
>
> - if path in open() is changed to any other name (instead of `dir1`) the
> bug will not manifest.
>
>

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

end of thread, other threads:[~2025-11-27 18:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-27 13:53 File system corruption after renaming directory and creating a new file with same name if system crashes Vyacheslav Kovalevsky
2025-11-27 18:22 ` Filipe Manana

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

all inboxes | Powered by JetHome®