Skip to content

Commit

Permalink
lib/nfs/Connection: give up connection after NFS4ERR_EXPIRED
Browse files Browse the repository at this point in the history
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
  • Loading branch information
MaxKellermann committed Jan 30, 2025
1 parent 5b00195 commit 275cd9d
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/lib/nfs/Connection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

extern "C" {
#include <nfsc/libnfs.h>
#include <nfsc/libnfs-raw-nfs4.h>
}

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

#include <string.h> // for strstr()

static constexpr Event::Duration NFS_MOUNT_TIMEOUT =
std::chrono::minutes(1);

Expand Down Expand Up @@ -130,11 +133,27 @@ NfsConnection::CancellableCallback::PrepareDestroyContext() noexcept
}
}

/**
* Determine whether this is a fatal error and we need to close the
* connection and reopen a new one.
*/
static constexpr bool
IsFatalNfsConnectionError(int err, const char *msg) noexcept
{
/* nfsstat3_to_errno() translates NFS4ERR_EXPIRED to ERANGE,
so unfortunately we need to search the error message */
return err == -ERANGE && msg != nullptr &&
strstr(msg, "NFS4ERR_EXPIRED") != nullptr;
}

inline void
NfsConnection::CancellableCallback::Callback(int err, void *data) noexcept
{
assert(connection.GetEventLoop().IsInside());

auto &_connection = connection;
const bool is_fatal = IsFatalNfsConnectionError(err, (const char *)data);

if (!IsCancelled()) {
assert(close_fh == nullptr);

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

connection.callbacks.Remove(*this);
}

if (is_fatal)
/* this was a fatal connection error; we need to teat
down the NFS connection */
_connection.BroadcastError(std::make_exception_ptr(NfsClientError(-err, (const char *)data)));
}

void
Expand Down

0 comments on commit 275cd9d

Please sign in to comment.