Skip to content

Commit 275cd9d

Browse files
committed
lib/nfs/Connection: give up connection after NFS4ERR_EXPIRED
Once a NFS request fails with NFS4ERR_EXPIRED, the whole connection is broken and we need to open a new one. I wish libnfs would report this to us as a connection-level error, but instead only the one request fails; therefore this workaround is an ugly kludge. Closes #2175
1 parent 5b00195 commit 275cd9d

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

src/lib/nfs/Connection.cxx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
extern "C" {
1212
#include <nfsc/libnfs.h>
13+
#include <nfsc/libnfs-raw-nfs4.h>
1314
}
1415

1516
#include <utility>
@@ -20,6 +21,8 @@ extern "C" {
2021
#include <poll.h> /* for POLLIN, POLLOUT */
2122
#endif
2223

24+
#include <string.h> // for strstr()
25+
2326
static constexpr Event::Duration NFS_MOUNT_TIMEOUT =
2427
std::chrono::minutes(1);
2528

@@ -130,11 +133,27 @@ NfsConnection::CancellableCallback::PrepareDestroyContext() noexcept
130133
}
131134
}
132135

136+
/**
137+
* Determine whether this is a fatal error and we need to close the
138+
* connection and reopen a new one.
139+
*/
140+
static constexpr bool
141+
IsFatalNfsConnectionError(int err, const char *msg) noexcept
142+
{
143+
/* nfsstat3_to_errno() translates NFS4ERR_EXPIRED to ERANGE,
144+
so unfortunately we need to search the error message */
145+
return err == -ERANGE && msg != nullptr &&
146+
strstr(msg, "NFS4ERR_EXPIRED") != nullptr;
147+
}
148+
133149
inline void
134150
NfsConnection::CancellableCallback::Callback(int err, void *data) noexcept
135151
{
136152
assert(connection.GetEventLoop().IsInside());
137153

154+
auto &_connection = connection;
155+
const bool is_fatal = IsFatalNfsConnectionError(err, (const char *)data);
156+
138157
if (!IsCancelled()) {
139158
assert(close_fh == nullptr);
140159

@@ -162,6 +181,11 @@ NfsConnection::CancellableCallback::Callback(int err, void *data) noexcept
162181

163182
connection.callbacks.Remove(*this);
164183
}
184+
185+
if (is_fatal)
186+
/* this was a fatal connection error; we need to teat
187+
down the NFS connection */
188+
_connection.BroadcastError(std::make_exception_ptr(NfsClientError(-err, (const char *)data)));
165189
}
166190

167191
void

0 commit comments

Comments
 (0)