before this change set, linger_register() returned a raw LingerOp
pointer with an implicit reference for the caller. for librados,
this implicit reference is only dropped when the corresponding
unwatch() calls linger_cancel()
after commit
94f42b648feea77bd09dc3fdb48e6db2b48c7717 introduced
linger_by_cookie(), unwatch() no longer has a safe way to drop this
implicit reference. to prevent LingerOp leaks when unwatch() returns
ENOTCONN, we can't hold this implicit reference count until unwatch()
linger_register() now returns an explicit reference to the caller as
intrusive_ptr<LingerOp>. this helps to guarantee that this reference
count gets dropped before the completion of watch()/aio_watch()
because linger_register() no longer acquires an implicit reference for
the caller, linger_cancel() no longer drops it with info->put()
Reported-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
{
unique_lock wl(rwlock);
_linger_cancel(info);
- info->put();
}
void Objecter::_linger_cancel(LingerOp *info)
linger_ops_set.insert(info);
ceph_assert(linger_ops.size() == linger_ops_set.size());
- info->get(); // for the caller
return info;
}