diff options
Diffstat (limited to 'src/librbd/io/ImageRequest.cc')
-rw-r--r-- | src/librbd/io/ImageRequest.cc | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/src/librbd/io/ImageRequest.cc b/src/librbd/io/ImageRequest.cc index f7964dc0a5c..4da8595cc2e 100644 --- a/src/librbd/io/ImageRequest.cc +++ b/src/librbd/io/ImageRequest.cc @@ -29,6 +29,46 @@ namespace io { using librbd::util::get_image_ctx; +namespace { + +template <typename I> +struct C_UpdateTimestamp : public Context { +public: + I* m_image_ctx; + AioCompletion* m_aio_comp; + bool modify; //if modify set to 'true', modify timestamp is updated, access timestamp otherwise + + C_UpdateTimestamp(I* ictx, AioCompletion *c, bool m) + : m_image_ctx(ictx), m_aio_comp(c), modify(m) { + m_aio_comp->add_request(); + } + + void send() { + librados::ObjectWriteOperation op; + if(modify) + cls_client::set_modify_timestamp(&op); + else + cls_client::set_access_timestamp(&op); + + librados::AioCompletion *comp = librbd::util::create_rados_callback(this); + int r = m_image_ctx->md_ctx.aio_operate(m_image_ctx->header_oid, comp, &op); + assert(r == 0); + comp->release(); + } + + void finish(int r) override { + // ignore errors updating timestamp + m_aio_comp->complete_request(0); + } +}; + +bool should_update_timestamp(const utime_t& now, const utime_t& timestamp, + uint64_t interval) { + return (interval && (static_cast<uint64_t>(now.sec()) >= interval + timestamp)); +} + +} // anonymous namespace + template <typename I> void ImageRequest<I>::aio_read(I *ictx, AioCompletion *c, Extents &&image_extents, @@ -198,7 +238,28 @@ void ImageReadRequest<I>::send_request() { for (auto &object_extent : object_extents) { request_count += object_extent.second.size(); } - aio_comp->set_request_count(request_count); + + utime_t ts = ceph_clock_now(); + + image_ctx.timestamp_lock.get_read(); + if(should_update_timestamp(ts,image_ctx.get_access_timestamp(), + image_ctx.atime_update_interval)) { + image_ctx.timestamp_lock.put_read(); + image_ctx.timestamp_lock.get_write(); + if(should_update_timestamp(ts,image_ctx.get_access_timestamp(), + image_ctx.atime_update_interval)) { + aio_comp->set_request_count(request_count + 1); + auto update_ctx = new C_UpdateTimestamp<I>(&image_ctx, aio_comp, false); + update_ctx->send(); + image_ctx.set_access_timestamp(ts); + } else { + aio_comp->set_request_count(request_count); + } + image_ctx.timestamp_lock.put_write(); + } else { + image_ctx.timestamp_lock.put_read(); + aio_comp->set_request_count(request_count); + } // issue the requests for (auto &object_extent : object_extents) { @@ -285,13 +346,34 @@ void AbstractImageWriteRequest<I>::send_request() { if (!object_extents.empty()) { uint64_t journal_tid = 0; + + utime_t ts = ceph_clock_now(); + image_ctx.timestamp_lock.get_read(); + if(should_update_timestamp(ts,image_ctx.get_modify_timestamp(), + image_ctx.mtime_update_interval)) { + image_ctx.timestamp_lock.put_read(); + image_ctx.timestamp_lock.get_write(); + if(should_update_timestamp(ts,image_ctx.get_modify_timestamp(), + image_ctx.mtime_update_interval)) { + aio_comp->set_request_count(object_extents.size() + 1); + auto update_ctx = new C_UpdateTimestamp<I>(&image_ctx, aio_comp, true); + update_ctx->send(); + image_ctx.set_modify_timestamp(ts); + } else { + aio_comp->set_request_count(object_extents.size()); + } + image_ctx.timestamp_lock.put_write(); + } else { + image_ctx.timestamp_lock.put_read(); + aio_comp->set_request_count(object_extents.size()); + } + if (journaling) { // in-flight ops are flushed prior to closing the journal assert(image_ctx.journal != NULL); journal_tid = append_journal_event(m_synchronous); } - aio_comp->set_request_count(object_extents.size()); send_object_requests(object_extents, snapc, journal_tid); } else { // no IO to perform -- fire completion |