librbd: owner_lock should be held during flush request

Flush might result in the cache writing out dirty objects, which
would require that the owner_lock be held.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2015-05-07 14:17:37 -04:00
parent a38f9e5104
commit c9142fe353
2 changed files with 34 additions and 19 deletions

View File

@ -735,7 +735,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type,
ldout(ictx->cct, 20) << "snap_create_helper " << ictx << " " << snap_name
<< dendl;
int r = ictx_check(ictx);
int r = ictx_check(ictx, true);
if (r < 0) {
return r;
}
@ -835,7 +835,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type,
ldout(ictx->cct, 20) << "snap_remove_helper " << ictx << " " << snap_name
<< dendl;
int r = ictx_check(ictx);
int r = ictx_check(ictx, true);
if (r < 0) {
return r;
}
@ -1442,10 +1442,10 @@ reprotect_and_return_err:
}
}
p_imctx->md_lock.get_write();
r = ictx_refresh(p_imctx);
p_imctx->md_lock.put_write();
{
RWLock::RLocker owner_locker(p_imctx->owner_lock);
r = ictx_refresh(p_imctx);
}
if (r == 0) {
p_imctx->snap_lock.get_read();
r = p_imctx->is_snap_protected(p_imctx->snap_id, &snap_protected);
@ -2076,7 +2076,7 @@ reprotect_and_return_err:
<< size << dendl;
ictx->snap_lock.put_read();
int r = ictx_check(ictx);
int r = ictx_check(ictx, true);
if (r < 0) {
return r;
}
@ -2217,7 +2217,7 @@ reprotect_and_return_err:
return 0;
}
int ictx_check(ImageCtx *ictx)
int ictx_check(ImageCtx *ictx, bool owner_locked)
{
CephContext *cct = ictx->cct;
ldout(cct, 20) << "ictx_check " << ictx << dendl;
@ -2227,9 +2227,13 @@ reprotect_and_return_err:
ictx->refresh_lock.Unlock();
if (needs_refresh) {
RWLock::WLocker l(ictx->md_lock);
int r = ictx_refresh(ictx);
int r;
if (owner_locked) {
r = ictx_refresh(ictx);
} else {
RWLock::RLocker owner_lock(ictx->owner_lock);
r = ictx_refresh(ictx);
}
if (r < 0) {
lderr(cct) << "Error re-reading rbd header: " << cpp_strerror(-r)
<< dendl;
@ -2277,6 +2281,9 @@ reprotect_and_return_err:
int ictx_refresh(ImageCtx *ictx)
{
assert(ictx->owner_lock.is_locked());
RWLock::WLocker md_locker(ictx->md_lock);
CephContext *cct = ictx->cct;
bufferlist bl, bl2;
@ -2790,9 +2797,10 @@ reprotect_and_return_err:
}
}
ictx->md_lock.get_write();
r = ictx_refresh(ictx);
ictx->md_lock.put_write();
{
RWLock::RLocker owner_locker(ictx->owner_lock);
r = ictx_refresh(ictx);
}
if (r < 0)
goto err_close;
@ -2908,7 +2916,7 @@ reprotect_and_return_err:
int r;
// ictx_check also updates parent data
if ((r = ictx_check(ictx)) < 0) {
if ((r = ictx_check(ictx, true)) < 0) {
lderr(cct) << "ictx_check failed" << dendl;
return r;
}
@ -2993,7 +3001,7 @@ reprotect_and_return_err:
return -EINVAL;
}
int r = ictx_check(ictx);
int r = ictx_check(ictx, true);
if (r < 0) {
return r;
}
@ -3238,7 +3246,10 @@ reprotect_and_return_err:
<< " len = " << len << dendl;
// ensure previous writes are visible to listsnaps
_flush(ictx);
{
RWLock::RLocker owner_locker(ictx->owner_lock);
_flush(ictx);
}
int r = ictx_check(ictx);
if (r < 0)
@ -3689,13 +3700,17 @@ reprotect_and_return_err:
}
ictx->user_flushed();
r = _flush(ictx);
{
RWLock::RLocker owner_locker(ictx->owner_lock);
r = _flush(ictx);
}
ictx->perfcounter->inc(l_librbd_flush);
return r;
}
int _flush(ImageCtx *ictx)
{
assert(ictx->owner_lock.is_locked());
CephContext *cct = ictx->cct;
int r;
// flush any outstanding writes

View File

@ -117,7 +117,7 @@ namespace librbd {
int add_snap(ImageCtx *ictx, const char *snap_name);
int rm_snap(ImageCtx *ictx, const char *snap_name, uint64_t snap_id);
int refresh_parent(ImageCtx *ictx);
int ictx_check(ImageCtx *ictx);
int ictx_check(ImageCtx *ictx, bool owner_locked=false);
int ictx_refresh(ImageCtx *ictx);
int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname,
ProgressContext &prog_ctx);