onfinish->complete(r);
delete this;
}
+void Client::C_Read_Sync_NonBlocking::start()
+{
+ clnt->fscrypt->prepare_data_read(in->fscrypt_ctx,
+ &in->fscrypt_key_validator,
+ off, len, in->size,
+ &read_start, &read_len,
+ &fscrypt_denc);
+ pos = read_start;
+ left = read_len;
+ retry();
+}
void Client::C_Read_Sync_NonBlocking::retry()
{
filer->read_trunc(in->ino, &in->layout, in->snapid, pos, left, &tbl, 0,
{
clnt->client_lock.lock();
+ auto effective_size = in->effective_size();
+
+ auto target_len = std::min(len, effective_size - off);
+
+ bufferlist encbl;
+ bufferlist *pbl = (fscrypt_denc ? &encbl : bl);
+
if (r == -ENOENT) {
// if we get ENOENT from OSD, assume 0 bytes returned
goto success;
read += r;
pos += r;
left -= r;
- bl->claim_append(tbl);
+ pbl->claim_append(tbl);
}
// short read?
if (r >= 0 && r < wanted) {
- if (pos < in->effective_size()) {
+ if (pos < effective_size) {
// zero up to known EOF
- int64_t some = in->effective_size() - pos;
+ int64_t some = effective_size - pos;
if (some > left)
some = left;
auto z = buffer::ptr_node::create(some);
z->zero();
- bl->push_back(std::move(z));
+ pbl->push_back(std::move(z));
read += some;
pos += some;
left -= some;
}
// eof? short read.
- if ((uint64_t)pos >= in->effective_size())
+ if ((uint64_t)pos >= effective_size)
goto success;
wanted = left;
}
success:
+ if (r >= 0) {
+ if (fscrypt_denc) {
+ std::vector<ObjectCacher::ObjHole> holes;
+ r = fscrypt_denc->decrypt_bl(off, target_len, read_start, holes, pbl);
+ if (r < 0) {
+ ldout(clnt->cct, 20) << __func__ << "(): failed to decrypt buffer: r=" << r << dendl;
+ }
+ bl->claim_append(*pbl);
+ }
+
+ // r is expected to hold value of effective bytes read.
+ // in the case of fscrypt, this will be the logical size. So if all bytes read
+ // is equal to read_len, then display logical size.
+ if (read_len == read) {
+ r = len;
+ } else {
+ r = read;
+ }
- r = read;
- clnt->subvolume_tracker->add_metric(in->ino, SimpleIOMetric(false, mono_clock_now() - start_time, r));
+ clnt->subvolume_tracker->add_metric(in->ino, SimpleIOMetric(false, mono_clock_now() - start_time, r));
+ }
error:
onfinish->complete(r);
crf.release();
// Now make first attempt at performing _read_sync
- crsa->retry();
+ crsa->start();
// Now the C_Read_Sync_NonBlocking is going to handle EVERYTHING else
// Allow caller to wait on onfinish...
if (r < 0) {
ldout(cct, 20) << __func__ << "(): failed to decrypt buffer: r=" << r << dendl;
}
+
+ read = pbl->length();
bl->claim_append(*pbl);
+ } else {
+ read = pbl->length();
}
-
- read = pbl->length();
}
return read;
}
// each step, with complete only releasing this object once all is finally
// complete.
public:
+ client_t const whoami;
C_Read_Sync_NonBlocking(Client *clnt, Context *onfinish, Fh *f, Inode *in,
uint64_t fpos, uint64_t off, uint64_t len,
bufferlist *bl, Filer *filer, int have_caps)
fini = false;
}
- void retry();
+ void start();
+ FSCryptFDataDencRef fscrypt_denc;
private:
Client *clnt;
Inode *in;
uint64_t off;
uint64_t len;
+ uint64_t read_start;
+ uint64_t read_len;
int left;
int wanted;
bufferlist *bl;
uint64_t pos;
bool fini;
+ void retry();
void finish(int r) override;
void complete(int r) override