diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 5be82033390..1e87af9d194 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 697fc6ccc41..caf61a65f70 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 b13ff97cd9a..e56ef0897f4 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 43458886b43..6fb1af46175 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 cad0c5eb172..658f24b85ca 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 bf075769d8b..ab093ce30ab 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 e098805b615..144c4293cc8 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)