return r;
}
+void Client::C_Lock_Client_Finisher::finish(int r)
+{
+ std::scoped_lock lock(clnt->client_lock);
+ onfinish->complete(r);
+}
+
void Client::C_Write_Finisher::finish_io(int r)
{
bool fini;
+ ceph_assert(ceph_mutex_is_locked_by_me(clnt->client_lock));
+
clnt->put_cap_ref(in, CEPH_CAP_FILE_BUFFER);
if (r >= 0) {
bool fini;
client_t const whoami = clnt->whoami; // For the benefit of ldout prefix
+ ceph_assert(ceph_mutex_is_locked_by_me(clnt->client_lock));
+
ldout(clnt->cct, 3) << "finish_fsync r = " << r << dendl;
fsync_finished = true;
std::unique_ptr<Context> iofinish = nullptr;
std::unique_ptr<C_Write_Finisher> cwf = nullptr;
+ std::unique_ptr<Context> filer_iofinish = nullptr;
if (in->inline_version < CEPH_INLINE_NONE) {
if (endoff > cct->_conf->client_max_inline_size ||
if (onfinish == nullptr) {
// We need a safer condition to wait on.
cond_iofinish = new C_SaferCond();
- iofinish.reset(cond_iofinish);
+ filer_iofinish.reset(cond_iofinish);
+ } else {
+ //Register a wrapper callback for the C_Write_Finisher which takes 'client_lock'
+ filer_iofinish.reset(new C_Lock_Client_Finisher(this, iofinish.get()));
}
get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
filer->write_trunc(in->ino, &in->layout, in->snaprealm->get_snap_context(),
offset, size, bl, ceph::real_clock::now(), 0,
in->truncate_size, in->truncate_seq,
- iofinish.get());
+ filer_iofinish.get());
if (onfinish) {
// handle non-blocking caller (onfinish != nullptr), we can now safely
// release all the managed pointers
+ filer_iofinish.release();
iofinish.release();
onuninline.release();
cwf.release();
void finish(int r) override;
};
+ // A wrapper callback which takes the 'client_lock' and finishes the context.
+ // One of the usecase is the filer->write_trunc which doesn't hold client_lock
+ // in the call back passed. So, use this wrapper in such cases.
+ class C_Lock_Client_Finisher : public Context {
+ public:
+ C_Lock_Client_Finisher(Client *clnt, Context *onfinish)
+ : clnt(clnt), onfinish(onfinish) {}
+
+ private:
+ Client *clnt;
+ Context *onfinish;
+
+ void finish(int r) override;
+ };
+
class C_Write_Finisher : public Context {
public:
void finish_io(int r);