librbd: add an interface to invalidate cached data

This is useful for qemu to guarantee live migration with caching is
safe, by invalidating the cache on the destination before starting it.

Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
Josh Durgin 2014-04-24 14:47:24 -07:00
parent e08b8b66c7
commit 5d340d26dd
7 changed files with 57 additions and 0 deletions

View File

@ -39,6 +39,7 @@ extern "C" {
#define LIBRBD_SUPPORTS_WATCH 0
#define LIBRBD_SUPPORTS_AIO_FLUSH 1
#define LIBRBD_SUPPORTS_INVALIDATE 1
typedef void *rbd_snap_t;
typedef void *rbd_image_t;
@ -376,6 +377,14 @@ int rbd_flush(rbd_image_t image);
*/
int rbd_aio_flush(rbd_image_t image, rbd_completion_t c);
/**
* Drop any cached data for an image
*
* @param image the image to invalidate cached data for
* @returns 0 on success, negative error code on failure
*/
int rbd_invalidate_cache(rbd_image_t image);
#ifdef __cplusplus
}
#endif

View File

@ -216,6 +216,14 @@ public:
*/
int aio_flush(RBD::AioCompletion *c);
/**
* Drop any cached data for an image
*
* @param image the image to invalidate cached data for
* @returns 0 on success, negative error code on failure
*/
int invalidate_cache();
private:
friend class RBD;

View File

@ -2881,6 +2881,19 @@ reprotect_and_return_err:
return r;
}
int invalidate_cache(ImageCtx *ictx)
{
CephContext *cct = ictx->cct;
ldout(cct, 20) << "invalidate_cache " << ictx << dendl;
int r = ictx_check(ictx);
if (r < 0)
return r;
RWLock::WLocker l(ictx->md_lock);
return ictx->invalidate_cache();
}
int aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf,
AioCompletion *c)
{

View File

@ -188,6 +188,7 @@ namespace librbd {
int aio_flush(ImageCtx *ictx, AioCompletion *c);
int flush(ImageCtx *ictx);
int _flush(ImageCtx *ictx);
int invalidate_cache(ImageCtx *ictx);
ssize_t handle_sparse_read(CephContext *cct,
ceph::bufferlist data_bl,

View File

@ -514,6 +514,12 @@ namespace librbd {
return librbd::aio_flush(ictx, (librbd::AioCompletion *)c->pc);
}
int Image::invalidate_cache()
{
ImageCtx *ictx = (ImageCtx *)ctx;
return librbd::invalidate_cache(ictx);
}
} // namespace librbd
extern "C" void rbd_version(int *major, int *minor, int *extra)
@ -1130,6 +1136,12 @@ extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
return librbd::aio_flush(ictx, (librbd::AioCompletion *)comp->pc);
}
extern "C" int rbd_invalidate_cache(rbd_image_t image)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
return librbd::invalidate_cache(ictx);
}
extern "C" int rbd_aio_is_complete(rbd_completion_t c)
{
librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;

View File

@ -750,6 +750,14 @@ written." % (self.name, ret, length))
if ret < 0:
raise make_ex(ret, 'error flushing image')
def invalidate_cache(self):
"""
Drop any cached data for the image.
"""
ret = self.librbd.rbd_invalidate_cache(self.image)
if ret < 0:
raise make_ex(ret, 'error invalidating cache')
def stripe_unit(self):
"""
Returns the stripe unit used for the image.

View File

@ -229,6 +229,12 @@ class TestImage(object):
self.image.close()
remove_image()
def test_invalidate_cache(self):
self.image.write('abc', 0)
eq('abc', self.image.read(0, 3))
self.image.invalidate_cache()
eq('abc', self.image.read(0, 3))
def test_stat(self):
info = self.image.stat()
check_stat(info, IMG_SIZE, IMG_ORDER)