From 5d340d26dd70192eb0e4f3f240e3433fb9a24154 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Thu, 24 Apr 2014 14:47:24 -0700 Subject: [PATCH] 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 --- src/include/rbd/librbd.h | 9 +++++++++ src/include/rbd/librbd.hpp | 8 ++++++++ src/librbd/internal.cc | 13 +++++++++++++ src/librbd/internal.h | 1 + src/librbd/librbd.cc | 12 ++++++++++++ src/pybind/rbd.py | 8 ++++++++ src/test/pybind/test_rbd.py | 6 ++++++ 7 files changed, 57 insertions(+) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 5be82033390e8..1e87af9d1944f 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -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 diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 697fc6ccc41e9..caf61a65f7069 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -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; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index b13ff97cd9aeb..e56ef0897f48c 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -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) { diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 43458886b430b..6fb1af4617573 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -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, diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index cad0c5eb17294..658f24b85ca79 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -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; diff --git a/src/pybind/rbd.py b/src/pybind/rbd.py index bf075769d8be0..ab093ce30abd7 100644 --- a/src/pybind/rbd.py +++ b/src/pybind/rbd.py @@ -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. diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index e098805b61571..144c4293cc8bd 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -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) -- 2.39.5