pNFS/flexfiles: Treat ENETUNREACH errors as fatal in containers

Propagate the NFS_MOUNT_NETUNREACH_FATAL flag to work with the pNFS
flexfiles client. In these circumstances, the client needs to treat the
ENETDOWN and ENETUNREACH errors as fatal, and should abandon the
attempted I/O.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
pull/1193/head
Trond Myklebust 2025-03-20 08:04:35 -04:00
parent 9827144bfb
commit 8c9f0df7a8
4 changed files with 29 additions and 2 deletions

View File

@ -1154,10 +1154,14 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
rpc_wake_up(&tbl->slot_tbl_waitq); rpc_wake_up(&tbl->slot_tbl_waitq);
goto reset; goto reset;
/* RPC connection errors */ /* RPC connection errors */
case -ENETDOWN:
case -ENETUNREACH:
if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags))
return -NFS4ERR_FATAL_IOERROR;
fallthrough;
case -ECONNREFUSED: case -ECONNREFUSED:
case -EHOSTDOWN: case -EHOSTDOWN:
case -EHOSTUNREACH: case -EHOSTUNREACH:
case -ENETUNREACH:
case -EIO: case -EIO:
case -ETIMEDOUT: case -ETIMEDOUT:
case -EPIPE: case -EPIPE:
@ -1183,6 +1187,7 @@ reset:
/* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */
static int ff_layout_async_handle_error_v3(struct rpc_task *task, static int ff_layout_async_handle_error_v3(struct rpc_task *task,
struct nfs_client *clp,
struct pnfs_layout_segment *lseg, struct pnfs_layout_segment *lseg,
u32 idx) u32 idx)
{ {
@ -1200,6 +1205,11 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
case -EJUKEBOX: case -EJUKEBOX:
nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
goto out_retry; goto out_retry;
case -ENETDOWN:
case -ENETUNREACH:
if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags))
return -NFS4ERR_FATAL_IOERROR;
fallthrough;
default: default:
dprintk("%s DS connection error %d\n", __func__, dprintk("%s DS connection error %d\n", __func__,
task->tk_status); task->tk_status);
@ -1234,7 +1244,7 @@ static int ff_layout_async_handle_error(struct rpc_task *task,
switch (vers) { switch (vers) {
case 3: case 3:
return ff_layout_async_handle_error_v3(task, lseg, idx); return ff_layout_async_handle_error_v3(task, clp, lseg, idx);
case 4: case 4:
return ff_layout_async_handle_error_v4(task, state, clp, return ff_layout_async_handle_error_v4(task, state, clp,
lseg, idx); lseg, idx);
@ -1337,6 +1347,9 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
return task->tk_status; return task->tk_status;
case -EAGAIN: case -EAGAIN:
goto out_eagain; goto out_eagain;
case -NFS4ERR_FATAL_IOERROR:
task->tk_status = -EIO;
return 0;
} }
return 0; return 0;
@ -1507,6 +1520,9 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
return task->tk_status; return task->tk_status;
case -EAGAIN: case -EAGAIN:
return -EAGAIN; return -EAGAIN;
case -NFS4ERR_FATAL_IOERROR:
task->tk_status = -EIO;
return 0;
} }
if (hdr->res.verf->committed == NFS_FILE_SYNC || if (hdr->res.verf->committed == NFS_FILE_SYNC ||
@ -1551,6 +1567,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task,
case -EAGAIN: case -EAGAIN:
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
return -EAGAIN; return -EAGAIN;
case -NFS4ERR_FATAL_IOERROR:
task->tk_status = -EIO;
return 0;
} }
ff_layout_set_layoutcommit(data->inode, data->lseg, data->lwb); ff_layout_set_layoutcommit(data->inode, data->lseg, data->lwb);

View File

@ -120,6 +120,8 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
if (mds_srv->flags & NFS_MOUNT_NORESVPORT) if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
if (test_bit(NFS_CS_NETUNREACH_FATAL, &mds_clp->cl_flags))
__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags);
__set_bit(NFS_CS_DS, &cl_init.init_flags); __set_bit(NFS_CS_DS, &cl_init.init_flags);

View File

@ -939,6 +939,9 @@ static int nfs4_set_client(struct nfs_server *server,
__set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags); __set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);
server->port = rpc_get_port((struct sockaddr *)addr); server->port = rpc_get_port((struct sockaddr *)addr);
if (server->flags & NFS_MOUNT_NETUNREACH_FATAL)
__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags);
/* Allocate or find a client reference we can use */ /* Allocate or find a client reference we can use */
clp = nfs_get_client(&cl_init); clp = nfs_get_client(&cl_init);
if (IS_ERR(clp)) if (IS_ERR(clp))
@ -1013,6 +1016,8 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
if (mds_srv->flags & NFS_MOUNT_NORESVPORT) if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
if (test_bit(NFS_CS_NETUNREACH_FATAL, &mds_clp->cl_flags))
__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags);
__set_bit(NFS_CS_PNFS, &cl_init.init_flags); __set_bit(NFS_CS_PNFS, &cl_init.init_flags);
cl_init.max_connect = NFS_MAX_TRANSPORTS; cl_init.max_connect = NFS_MAX_TRANSPORTS;

View File

@ -300,6 +300,7 @@ enum nfsstat4 {
/* error codes for internal client use */ /* error codes for internal client use */
#define NFS4ERR_RESET_TO_MDS 12001 #define NFS4ERR_RESET_TO_MDS 12001
#define NFS4ERR_RESET_TO_PNFS 12002 #define NFS4ERR_RESET_TO_PNFS 12002
#define NFS4ERR_FATAL_IOERROR 12003
static inline bool seqid_mutating_err(u32 err) static inline bool seqid_mutating_err(u32 err)
{ {