From: Josh Durgin Date: Tue, 14 Jun 2011 19:38:14 +0000 (-0700) Subject: librbd: fix AioCompletion race condition X-Git-Tag: v0.29.1~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ea3db17697b0d6fadf9bb26af0ed0b61773d530a;p=ceph.git librbd: fix AioCompletion race condition If block completions finished before all of them where scheduled, the pending_count would reach 0, and the AioCompletion would be destroyed since the refcount would also reach 0. To fix this, hold a reference to the AioCompletion while scheduling more block completions. This caused a crash like this when running qemu: 1: ceph::__ceph_assert_fail (assertion=, file=, line=, func=) at common/assert.cc:86 2: Lock (ictx=0x7f83d0001f00, off=5368705024, len=0, buf=0x2fac000 "", c=0x2cebe00) at common/Mutex.h:118 3: add_block_completion (ictx=0x7f83d0001f00, off=5368705024, len=0, buf=0x2fac000 "", c=0x2cebe00) at librbd.cc:159 4: librbd::aio_read (ictx=0x7f83d0001f00, off=5368705024, len=0, buf=0x2fac000 "", c=0x2cebe00) at librbd.cc:1368 5: rbd_aio_rw_vector (bs=, sector_num=10485752, qiov=, nb_sectors=, cb=, opaque=, write=0) at block/rbd.c:626 6: qemu_rbd_aio_readv (bs=, sector_num=, qiov=, nb_sectors=, cb=, opaque=) at block/rbd.c:649 7: bdrv_aio_readv (bs=0x2ce92e0, sector_num=10485752, qiov=0x2de08f0, nb_sectors=8, cb=, opaque=) Fixes: #998 Signed-off-by: Josh Durgin --- diff --git a/src/librbd.cc b/src/librbd.cc index d1dcfafc5e8..30aec97c4d8 100644 --- a/src/librbd.cc +++ b/src/librbd.cc @@ -1303,6 +1303,7 @@ int aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf, if (r < 0) return r; + c->get(); for (uint64_t i = start_block; i <= end_block; i++) { bufferlist bl; string oid = get_block_oid(&ictx->header, i); @@ -1320,8 +1321,9 @@ int aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf, total_write += write_len; left -= write_len; } - return 0; + r = 0; done: + c->put(); /* FIXME: cleanup all the allocated stuff */ return r; } @@ -1355,6 +1357,7 @@ int aio_read(ImageCtx *ictx, uint64_t off, size_t len, uint64_t block_size = get_block_size(&ictx->header); uint64_t left = len; + c->get(); for (uint64_t i = start_block; i <= end_block; i++) { bufferlist bl; string oid = get_block_oid(&ictx->header, i); @@ -1384,6 +1387,7 @@ int aio_read(ImageCtx *ictx, uint64_t off, size_t len, } ret = total_read; done: + c->put(); return ret; }