lib/nfs: initial support for libnfs API 2

Commit
5e8f7ce273
introduced the libnfs API version 2 which may eventually become libnfs
version 6.

This version detection depends on my pull request
https://github.com/sahlberg/libnfs/pull/468
This commit is contained in:
Max Kellermann 2024-05-13 18:11:24 +02:00
parent 0ac24e5a24
commit 31e583e9f8
6 changed files with 82 additions and 7 deletions

1
NEWS
View File

@ -26,6 +26,7 @@ ver 0.24 (not yet released)
* storage
- curl: optimize database update
- nfs: require libnfs 4.0 or later
- nfs: support libnfs 6 (API version 2)
- nfs: support libnfs URL arguments
* input
- alsa: limit ALSA buffer time to 2 seconds

View File

@ -81,11 +81,25 @@ NfsConnection::CancellableCallback::Stat(nfs_context *ctx,
inline void
NfsConnection::CancellableCallback::Read(nfs_context *ctx, struct nfsfh *fh,
uint64_t offset, size_t size)
uint64_t offset,
#ifdef LIBNFS_API_2
std::span<std::byte> dest
#else
std::size_t size
#endif
)
{
assert(connection.GetEventLoop().IsInside());
int result = nfs_pread_async(ctx, fh, offset, size, Callback, this);
int result = nfs_pread_async(ctx, fh,
#ifdef LIBNFS_API_2
dest.data(), dest.size(),
#endif
offset,
#ifndef LIBNFS_API_2
size,
#endif
Callback, this);
if (result < 0)
throw NfsClientError(ctx, "nfs_pread_async() failed");
}
@ -328,7 +342,12 @@ NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback)
}
void
NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size,
NfsConnection::Read(struct nfsfh *fh, uint64_t offset,
#ifdef LIBNFS_API_2
std::span<std::byte> dest,
#else
std::size_t size,
#endif
NfsCallback &callback)
{
assert(GetEventLoop().IsInside());
@ -336,7 +355,13 @@ NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size,
auto &c = callbacks.Add(callback, *this, false);
try {
c.Read(context, fh, offset, size);
c.Read(context, fh, offset,
#ifdef LIBNFS_API_2
dest
#else
size
#endif
);
} catch (...) {
callbacks.Remove(c);
throw;

View File

@ -62,7 +62,13 @@ class NfsConnection {
void Open(nfs_context *context, const char *path, int flags);
void Stat(nfs_context *context, struct nfsfh *fh);
void Read(nfs_context *context, struct nfsfh *fh,
uint64_t offset, size_t size);
uint64_t offset,
#ifdef LIBNFS_API_2
std::span<std::byte> dest
#else
std::size_t size
#endif
);
/**
* Cancel the operation and schedule a call to
@ -210,7 +216,12 @@ public:
/**
* Throws on error.
*/
void Read(struct nfsfh *fh, uint64_t offset, size_t size,
void Read(struct nfsfh *fh, uint64_t offset,
#ifdef LIBNFS_API_2
std::span<std::byte> dest,
#else
std::size_t size,
#endif
NfsCallback &callback);
/**

View File

@ -59,7 +59,13 @@ NfsFileReader::CancelOrClose() noexcept
else if (state > State::OPEN)
/* one async operation in progress: cancel it and
defer the nfs_close_async() call */
connection->CancelAndClose(fh, {}, *this);
connection->CancelAndClose(fh,
#ifdef LIBNFS_API_2
ToDeleteArray(read_buffer.release()),
#else
{},
#endif
*this);
else if (state > State::MOUNT)
/* we don't have a file handle yet - just cancel the
async operation */
@ -116,7 +122,15 @@ NfsFileReader::Read(uint64_t offset, size_t size)
{
assert(state == State::IDLE);
#ifdef LIBNFS_API_2
assert(!read_buffer);
// TOOD read into caller-provided buffer
read_buffer = std::make_unique<std::byte[]>(size);
connection->Read(fh, offset, {read_buffer.get(), size}, *this);
#else
connection->Read(fh, offset, size, *this);
#endif
state = State::READ;
}
@ -200,7 +214,16 @@ NfsFileReader::StatCallback(const struct nfs_stat_64 *st) noexcept
inline void
NfsFileReader::ReadCallback(std::size_t nbytes, const void *data) noexcept
{
#ifdef LIBNFS_API_2
(void)data;
assert(read_buffer);
const auto buffer = std::move(read_buffer);
OnNfsFileRead({buffer.get(), nbytes});
#else
OnNfsFileRead({static_cast<const std::byte *>(data), nbytes});
#endif
}
void

View File

@ -14,6 +14,10 @@
#include <span>
#include <string>
#ifdef LIBNFS_API_2
#include <memory>
#endif
struct nfsfh;
struct nfs_stat_64;
class NfsConnection;
@ -51,6 +55,10 @@ class NfsFileReader : NfsLease, NfsCallback {
*/
InjectEvent defer_open;
#ifdef LIBNFS_API_2
std::unique_ptr<std::byte[]> read_buffer;
#endif
public:
NfsFileReader() noexcept;
~NfsFileReader() noexcept;

View File

@ -4,6 +4,13 @@ if not nfs_dep.found()
subdir_done()
endif
if nfs_dep.version().version_compare('>=6')
# libnfs has no version macro therefore we must detect the API
# version 2 at configure time
nfs_dep = declare_dependency(compile_args: '-DLIBNFS_API_2',
dependencies: nfs_dep)
endif
nfs = static_library(
'nfs',
'Connection.cxx',