summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTigran Mkrtchyan <tigran.mkrtchyan@desy.de>2026-10-11 00:18:38 +0200
committerAnna Schumaker <anna.schumaker@hammerspace.com>2026-10-19 11:45:00 -0400
commitfde27289503beabe7e0856dac164a5ced4be0342 (patch)
treeee3eab929004eb33d4c3098fe7a51b58ed33bbab
parent4b27670ea25b955b710021151471cb252240b1e0 (diff)
pNFS/flexfiles: make pg_init retry loops killable
When a task is killed while the pNFS client connects to a data server, nfs4_pnfs_ds_connect() fails with -ERESTARTSYS. If the layout has FF_FLAGS_NO_IO_THRU_MDS set, ff_layout_pg_init_read() cannot fall back to the MDS and retries after an uninterruptible ssleep. As the fatal signal stays pending, every new connect attempt is aborted the same way and the task loops forever without returning to user space: # grep -E 'SigPnd|ShdPnd' /proc/156021/status SigPnd: 0000000000000100 ShdPnd: 0000000000000100 # cat /proc/156021/stack msleep+0x2e/0x50 ff_layout_pg_init_read+0x267/0x310 [nfs_layout_flexfiles] __nfs_pageio_add_request+0x1c1/0x480 [nfs] nfs_pageio_add_request+0x21d/0x2c0 [nfs] nfs_read_add_folio+0x143/0x200 [nfs] nfs_readahead+0x204/0x290 [nfs] read_pages+0x62/0x230 page_cache_ra_unbounded+0x136/0x180 filemap_get_pages+0xf2/0x350 filemap_read+0xd5/0x320 nfs_file_read+0x6d/0xc0 [nfs] vfs_read+0x24f/0x3a0 __x64_sys_pread64+0x90/0xc0 do_syscall_64+0x5f/0xe0 Previous attempt propagates the error from nfs4_ff_layout_prepare_ds(), but only ff_layout_{read,write}_pagelist() look at it. The pg_init functions test IS_ERR() and retry on any error. Check for a fatal signal or an exiting task before sleeping in ff_layout_pg_init_read() and ff_layout_pg_init_write() and fail the I/O instead of retrying. Fixes: f06bedfa62d5 ("pNFS/flexfiles: don't attempt pnfs on fatal DS errors") Signed-off-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index d4f2b57e9d5b..ce3bb5f7a60a 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -960,6 +960,20 @@ ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio,
offset, dss_id);
}
+/*
+ * Wait before retrying pg_init. Returns false, with pgio->pg_error set,
+ * if the task was killed or is exiting and must not retry.
+ */
+static bool ff_layout_pg_retry_wait(struct nfs_pageio_descriptor *pgio)
+{
+ if (fatal_signal_pending(current) || nfs_current_task_exiting()) {
+ pgio->pg_error = -ERESTARTSYS;
+ return false;
+ }
+ ssleep(1);
+ return true;
+}
+
static void
ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req,
@@ -1059,7 +1073,8 @@ retry:
goto out_mds;
pnfs_generic_pg_cleanup(pgio);
/* Sleep for 1 second before retrying */
- ssleep(1);
+ if (!ff_layout_pg_retry_wait(pgio))
+ return;
goto retry;
}
@@ -1098,7 +1113,8 @@ retry_nolseg:
}
pgio->pg_error = 0;
/* Sleep for 1 second before retrying */
- ssleep(1);
+ if (!ff_layout_pg_retry_wait(pgio))
+ return;
goto retry;
out_mds:
trace_pnfs_mds_fallback_pg_init_read(pgio->pg_inode,
@@ -1156,7 +1172,8 @@ retry:
goto out_mds;
pnfs_generic_pg_cleanup(pgio);
/* Sleep for 1 second before retrying */
- ssleep(1);
+ if (!ff_layout_pg_retry_wait(pgio))
+ return;
goto retry;
}
pgm = &pgio->pg_mirrors[i];