Skip to content

Commit

Permalink
Client: Fix nonblocking-io zero by read
Browse files Browse the repository at this point in the history
Since a return of 0 indicates a blocking read, if the length is 0, we
must make an async completion call back and then return 0 indicating
an async return rather than 0 bytes.

Signed-off-by: Frank S. Filz <[email protected]>
  • Loading branch information
ffilz committed Sep 13, 2023
1 parent 4a78079 commit e60edcf
Showing 1 changed file with 28 additions and 9 deletions.
37 changes: 28 additions & 9 deletions src/client/Client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10901,7 +10901,9 @@ void Client::C_Read_Async_Finisher::finish(int r)
{
clnt->client_lock.lock();

clnt->do_readahead(f, in, off, len);
// Do read ahead as long as we aren't completing with 0 bytes
if (r != 0)
clnt->do_readahead(f, in, off, len);

onfinish->complete(r);

Expand All @@ -10915,14 +10917,36 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl,

const auto& conf = cct->_conf;
Inode *in = f->inode.get();
std::unique_ptr<Context> io_finish = nullptr;
C_SaferCond *io_finish_cond = nullptr;

ldout(cct, 10) << __func__ << " " << *in << " " << off << "~" << len << dendl;

if (onfinish != nullptr) {
io_finish.reset(new C_Read_Async_Finisher(this, onfinish, f, in,
f->pos, off, len));
}

// trim read based on file size?
if (off >= in->size)
return 0;
if (len == 0)
if ((off >= in->size) || (len == 0)) {
// If not async, immediate return of 0 bytes
if (onfinish == nullptr)
return 0;

// Release C_Read_Async_Finisher from managed pointer, we need to complete
// immediately. The C_Read_Async_Finisher is safely handled and won't be
// abandoned.
Context *crf = io_finish.release();

// Complete the crf immediately with 0 bytes
client_lock.unlock();
crf->complete(0);
client_lock.lock();

// Signal async completion
return 0;
}

if (off + len > in->size) {
len = in->size - off;
}
Expand All @@ -10933,14 +10957,9 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl,

// read (and possibly block)
int r = 0;
std::unique_ptr<Context> io_finish = nullptr;
C_SaferCond *io_finish_cond = nullptr;
if (onfinish == nullptr) {
io_finish_cond = new C_SaferCond("Client::_read_async flock");
io_finish.reset(io_finish_cond);
} else {
io_finish.reset(new C_Read_Async_Finisher(this, onfinish, f, in,
f->pos, off, len));
}

r = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
Expand Down

0 comments on commit e60edcf

Please sign in to comment.