From: Aditya Srivastava <aditya.ansh182@gmail.com>
To: Carlos Maiolino <cem@kernel.org>, Christoph Hellwig <hch@infradead.org>
Cc: linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org,
Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
Subject: [PATCH v4 0/2] xfs: resolve close() deadlocks on frozen filesystems
Date: Tue, 16 Jun 2026 03:38:18 +0000 [thread overview]
Message-ID: <20260616033821.2238-1-aditya.ansh182@gmail.com> (raw)
From: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
Hi Carlos and Christoph,
Apologies for the mailing list noise in v3; those patches were
accidentally sent as unthreaded emails due to a local Git configuration.
This v4 series is properly threaded under the cover letter standalone,
and has a distinct subject line to prevent mail client threading
collisions.
This is version 4 of the patch series addressing the close() system call
hanging indefinitely on frozen XFS filesystems (Bugzilla #205833).
Based on Christoph's feedback, I have made the following improvements:
- Split the changes into a clean, 2-patch series separating the new
trylock flag implementation from the deadlock fix itself.
- Extracted the case history, reproducer code, and discussion from the
commit logs into this cover letter to keep commit logs surgically
focused.
- Adjusted the parameter name in xfs_free_eofblocks() to trans_flags to
make its usage stand out.
- Implemented a much cleaner, race-free state preservation logic in
xfs_file_release() by omitting pre-setting XFS_EOFBLOCKS_RELEASED
on the inode, setting it only upon successful truncation.
- Simplified the transaction allocation block, renamed the flag to
XFS_TRANS_WRITECOUNT_TRYLOCK, and added the requested mutual-exclusivity
assertion in __xfs_trans_alloc().
- Set up this series to be posted standalone (not threaded as a reply)
per the standard kernel guidelines.
As requested, I have also submitted the corresponding regression test to
the xfstests mailing list (using tests/xfs/842 with a GPLv2-licensed
helper program). The fstests maintainer (Zorro Lang) reviewed the test
and has indicated that he will wait for this kernel patch to make it
through before merging the test suite additions.
THE REAL-WORLD IMPACT (BUGZILLA & DOWNSTREAM CASES)
==================================================
When speculative post-EOF blocks are closed on XFS, the release path
synchronously attempts to free them via xfs_free_eofblocks(). This
allocates a write transaction (xfs_trans_alloc) which blocks
indefinitely on the superblock freeze write lock (sb_start_intwrite)
under fsfreeze.
This behavior has a long history of causing severe system disruption:
- Downstream Red Hat Bugzilla 1474726 (dating back to 2017) details
complete system hangs during system backups when rsync and fsfreeze
are used. Even seemingly harmless read-only commands like
'cat /var/log/messages' would hang on close() in __sb_start_write
via xfs_free_eofblocks, requiring a hard reboot.
- Downstream LeApp integration test scenarios consistently hit this hang.
Hanging on close() frequently triggers container healthcheck failures,
systemd service timeouts, and cluster failover cascades, which is
disruptive to user-space applications that view close() as resource
reclamation. No other major Linux filesystem (ext4, btrfs, etc.)
synchronously allocates write transactions during close() system calls.
THE SOLUTION: NON-BLOCKING SUPERBLOCK TRYLOCK
=============================================
Instead of performing racy pre-checks, this series introduces
XFS_TRANS_WRITECOUNT_TRYLOCK. When specified, __xfs_trans_alloc()
attempts to obtain freeze protection using sb_start_intwrite_trylock().
If that fails, it aborts allocation gracefully and returns -EAGAIN.
We then pass XFS_TRANS_WRITECOUNT_TRYLOCK during xfs_file_release(). If
the truncation fails due to a frozen filesystem (-EAGAIN), we cleanly
bypass setting XFS_EOFBLOCKS_RELEASED on the inode, ensuring subsequent
releases or the background blockgc garbage collector can successfully
clean them up once thawed.
REPRODUCER DETAILS (GPLV2 LICENSED)
===================================
As requested, I have added a GPLv2-compatible license to the C
reproducer provided below, and I have also sent a corresponding patch to
the xfstests mailing list. The fstests maintainer (Zorro Lang) reviewed
the patch and indicated that he will wait for this kernel patch series
to be merged before pulling the test suite additions.
Compile with -pthread:
/*
* GPLv2-compatible XFS freeze close() hang reproducer.
* Copyright (c) 2026 Aditya Prakash Srivastava. All Rights Reserved.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/vfs.h>
#include <linux/fs.h>
#include <libgen.h>
volatile int close_started = 0;
volatile int close_completed = 0;
void *close_thread(void *arg) {
int fd = *(int *)arg;
close_started = 1;
close(fd);
close_completed = 1;
return NULL;
}
int main(int argc, char *argv[]) {
struct statfs sfs;
if (statfs(argv[1], &sfs) < 0) {
char *dir_buf = strdup(argv[1]);
char *parent_dir = dirname(dir_buf);
if (statfs(parent_dir, &sfs) < 0) {
perror("statfs");
free(dir_buf);
return 1;
}
free(dir_buf);
}
if (sfs.f_type != 0x58465342) return 1;
int freeze_fd = open(dirname(strdup(argv[1])), O_RDONLY);
int write_fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
char buf[65536] = {0};
for (int i = 0; i < 320; i++) write(write_fd, buf, sizeof(buf));
ioctl(freeze_fd, FIFREEZE, 0);
pthread_t thread;
pthread_create(&thread, NULL, close_thread, &write_fd);
while (!close_started) usleep(1000);
usleep(1000000); // Wait 1s
if (!close_completed) printf("SUCCESS: close() hung!\n");
ioctl(freeze_fd, FITHAW, 0);
pthread_join(thread, NULL);
unlink(argv[1]);
return 0;
}
Link: https://bugzilla.kernel.org/show_bug.cgi?id=205833
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1474726
Aditya Prakash Srivastava (2):
xfs: add a XFS_TRANS_WRITECOUNT_TRYLOCK flag
xfs: prevent close() from hanging on frozen filesystems
fs/xfs/libxfs/xfs_shared.h | 3 +++
fs/xfs/xfs_bmap_util.c | 9 +++++----
fs/xfs/xfs_bmap_util.h | 2 +-
fs/xfs/xfs_file.c | 8 +++++---
fs/xfs/xfs_icache.c | 2 +-
fs/xfs/xfs_inode.c | 2 +-
fs/xfs/xfs_trans.c | 12 +++++++++++-
7 files changed, 27 insertions(+), 11 deletions(-)
--
2.47.3
next reply other threads:[~2026-06-16 3:38 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 3:38 Aditya Srivastava [this message]
2026-06-16 3:38 ` [PATCH v4 1/2] xfs: add a XFS_TRANS_WRITECOUNT_TRYLOCK flag Aditya Srivastava
2026-06-16 5:20 ` Christoph Hellwig
2026-06-16 3:38 ` [PATCH v4 2/2] xfs: prevent close() from hanging on frozen filesystems Aditya Srivastava
2026-06-16 5:22 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260616033821.2238-1-aditya.ansh182@gmail.com \
--to=aditya.ansh182@gmail.com \
--cc=cem@kernel.org \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®