[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAL3q7H5ggWXdptoGH9Bmk-hc2CMBLz-YmC1A8U-hx9q=ZZ0BHw@mail.gmail.com>
Date: Fri, 24 Oct 2025 17:17:15 +0100
From: Filipe Manana <fdmanana@...nel.org>
To: Vyacheslav Kovalevsky <slava.kovalevskiy.2014@...il.com>
Cc: clm@...com, dsterba@...e.com, linux-btrfs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: Directory is not persisted after writing to the file within
directory if system crashes
On Fri, Oct 24, 2025 at 4:21 PM Vyacheslav Kovalevsky
<slava.kovalevskiy.2014@...il.com> wrote:
>
> Under some circumstances, directory entry is not persisted after writing
> to the file inside the directory that was opened with `O_SYNC` flag if
> system crashes.
>
>
> Detailed description
> ====================
>
> Hello, we have found another issue with btrfs crash behavior.
>
> In short, empty file is created and synced. Then, a new directory is
> created, old file is opened with `O_SYNC` flag and some data is written.
> After this, a new hard link is created inside the directory and the root
> is `fsync`ed (directory should persist). However, after a crash, the
> directory entry is missing even though data written to the old file was
> persisted.
>
>
> System info
> ===========
>
> Linux version 6.18.0-rc2, also tested on 6.14.11.
>
>
> 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_fd;
> int root_fd;
>
> status = creat("file1", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
> printf("CREAT: %d\n", status);
>
> // persist `file1`
> sync();
>
> status = mkdir("dir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
> printf("MKDIR: %d\n", status);
>
> status = open("file1", O_WRONLY | O_SYNC);
> printf("OPEN: %d\n", status);
> file_fd = status;
>
> status = write(file_fd, "Test data!", 10);
> printf("WRITE: %d\n", status);
>
> status = link("file1", "dir/file2");
> printf("LINK: %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);
> }
> ```
>
> 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 is missing.
I converted that to a test case for fstests and couldn't reproduce,
"dir", "file1" and "dir/file2" exist after the power failure.
The conversion for fstests:
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2025 SUSE S.A. All Rights Reserved.
#
# FS QA Test 780
#
# what am I here for?
#
. ./common/preamble
_begin_fstest auto quick log
_cleanup()
{
_cleanup_flakey
cd /
rm -r -f $tmp.*
}
. ./common/filter
. ./common/dmflakey
_require_scratch
_require_dm_target flakey
rm -f $seqres.full
_scratch_mkfs >>$seqres.full 2>&1 || _fail "mkfs failed"
_require_metadata_journaling $SCRATCH_DEV
_init_flakey
_mount_flakey
touch $SCRATCH_MNT/file1
_scratch_sync
mkdir $SCRATCH_MNT/dir
echo -n "hello world" > $SCRATCH_MNT/file1
ln $SCRATCH_MNT/file1 $SCRATCH_MNT/dir/file2
$XFS_IO_PROG -c "fsync" $SCRATCH_MNT/
# Simulate a power failure and then mount again the filesystem to replay the
# journal/log.
_flakey_drop_and_remount
ls -R $SCRATCH_MNT/ | _filter_scratch
_unmount_flakey
# success, all done
_exit 0
>
> Notes:
>
> - ext4 does persist `dir` and `dir/file2` even though it was not synced.
> - xfs does persist `dir` but does not persist `dir/file2`.
>
>
> P.S. Want to apologize for formatting in previous report, first time
> using Thunderbird and plain text.
>
>
>
>
Powered by blists - more mailing lists