From: Samuel Just Date: Tue, 15 Oct 2019 22:35:52 +0000 (-0700) Subject: osd/: factor OSD::init_op_flags into seperate class X-Git-Tag: v15.1.0~687^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=83eba36c2cff12dab0e7202dc12f92de796d1cd8;p=ceph.git osd/: factor OSD::init_op_flags into seperate class We'll want to reuse this in crimson, extract the logic for setting flags from MOSDOp into osd_types.h. Signed-off-by: Samuel Just --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 53546d5a75f3..83cb101da774 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -349,6 +349,8 @@ set(libcommon_files osd/osd_types.cc osd/PGPeeringEvent.cc osd/OpRequest.cc + osd/ClassHandler.cc + osd/osd_op_util.cc osdc/Striper.cc osdc/Objecter.cc librbd/Features.cc diff --git a/src/osd/CMakeLists.txt b/src/osd/CMakeLists.txt index 22e76538f7b4..f5368319e0c6 100644 --- a/src/osd/CMakeLists.txt +++ b/src/osd/CMakeLists.txt @@ -22,7 +22,6 @@ set(osd_srcs PGBackend.cc OSDCap.cc Watch.cc - ClassHandler.cc Session.cc SnapMapper.cc ScrubStore.cc diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index a02ee6f36d13..5b4c8b3c26b6 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -9906,195 +9906,6 @@ void OSD::get_latest_osdmap() // -------------------------------- -int OSD::init_op_flags(OpRequestRef& op) -{ - auto m = op->get_req(); - vector::const_iterator iter; - - // client flags have no bearing on whether an op is a read, write, etc. - op->rmw_flags = 0; - - if (m->has_flag(CEPH_OSD_FLAG_RWORDERED)) { - op->set_force_rwordered(); - } - if (m->has_flag(CEPH_OSD_FLAG_RETURNVEC)) { - op->set_returnvec(); - } - - // set bits based on op codes, called methods. - for (iter = m->ops.begin(); iter != m->ops.end(); ++iter) { - if ((iter->op.op == CEPH_OSD_OP_WATCH && - iter->op.watch.op == CEPH_OSD_WATCH_OP_PING)) { - /* This a bit odd. PING isn't actually a write. It can't - * result in an update to the object_info. PINGs also aren't - * resent, so there's no reason to write out a log entry. - * - * However, we pipeline them behind writes, so let's force - * the write_ordered flag. - */ - op->set_force_rwordered(); - } else { - if (ceph_osd_op_mode_modify(iter->op.op)) - op->set_write(); - } - if (ceph_osd_op_mode_read(iter->op.op)) - op->set_read(); - - // set READ flag if there are src_oids - if (iter->soid.oid.name.length()) - op->set_read(); - - // set PGOP flag if there are PG ops - if (ceph_osd_op_type_pg(iter->op.op)) - op->set_pg_op(); - - if (ceph_osd_op_mode_cache(iter->op.op)) - op->set_cache(); - - // check for ec base pool - int64_t poolid = m->get_pg().pool(); - const pg_pool_t *pool = osdmap->get_pg_pool(poolid); - if (pool && pool->is_tier()) { - const pg_pool_t *base_pool = osdmap->get_pg_pool(pool->tier_of); - if (base_pool && base_pool->require_rollback()) { - if ((iter->op.op != CEPH_OSD_OP_READ) && - (iter->op.op != CEPH_OSD_OP_CHECKSUM) && - (iter->op.op != CEPH_OSD_OP_CMPEXT) && - (iter->op.op != CEPH_OSD_OP_STAT) && - (iter->op.op != CEPH_OSD_OP_ISDIRTY) && - (iter->op.op != CEPH_OSD_OP_UNDIRTY) && - (iter->op.op != CEPH_OSD_OP_GETXATTR) && - (iter->op.op != CEPH_OSD_OP_GETXATTRS) && - (iter->op.op != CEPH_OSD_OP_CMPXATTR) && - (iter->op.op != CEPH_OSD_OP_ASSERT_VER) && - (iter->op.op != CEPH_OSD_OP_LIST_WATCHERS) && - (iter->op.op != CEPH_OSD_OP_LIST_SNAPS) && - (iter->op.op != CEPH_OSD_OP_SETALLOCHINT) && - (iter->op.op != CEPH_OSD_OP_WRITEFULL) && - (iter->op.op != CEPH_OSD_OP_ROLLBACK) && - (iter->op.op != CEPH_OSD_OP_CREATE) && - (iter->op.op != CEPH_OSD_OP_DELETE) && - (iter->op.op != CEPH_OSD_OP_SETXATTR) && - (iter->op.op != CEPH_OSD_OP_RMXATTR) && - (iter->op.op != CEPH_OSD_OP_STARTSYNC) && - (iter->op.op != CEPH_OSD_OP_COPY_GET) && - (iter->op.op != CEPH_OSD_OP_COPY_FROM)) { - op->set_promote(); - } - } - } - - switch (iter->op.op) { - case CEPH_OSD_OP_CALL: - { - bufferlist::iterator bp = const_cast(iter->indata).begin(); - int is_write, is_read; - string cname, mname; - bp.copy(iter->op.cls.class_len, cname); - bp.copy(iter->op.cls.method_len, mname); - - ClassHandler::ClassData *cls; - int r = ClassHandler::get_instance().open_class(cname, &cls); - if (r) { - derr << "class " << cname << " open got " << cpp_strerror(r) << dendl; - if (r == -ENOENT) - r = -EOPNOTSUPP; - else if (r != -EPERM) // propagate permission errors - r = -EIO; - return r; - } - int flags = cls->get_method_flags(mname); - if (flags < 0) { - if (flags == -ENOENT) - r = -EOPNOTSUPP; - else - r = flags; - return r; - } - is_read = flags & CLS_METHOD_RD; - is_write = flags & CLS_METHOD_WR; - bool is_promote = flags & CLS_METHOD_PROMOTE; - - dout(10) << "class " << cname << " method " << mname << " " - << "flags=" << (is_read ? "r" : "") - << (is_write ? "w" : "") - << (is_promote ? "p" : "") - << dendl; - if (is_read) - op->set_class_read(); - if (is_write) - op->set_class_write(); - if (is_promote) - op->set_promote(); - op->add_class(std::move(cname), std::move(mname), is_read, is_write, - cls->whitelisted); - break; - } - - case CEPH_OSD_OP_WATCH: - // force the read bit for watch since it is depends on previous - // watch state (and may return early if the watch exists) or, in - // the case of ping, is simply a read op. - op->set_read(); - // fall through - case CEPH_OSD_OP_NOTIFY: - case CEPH_OSD_OP_NOTIFY_ACK: - { - op->set_promote(); - break; - } - - case CEPH_OSD_OP_DELETE: - // if we get a delete with FAILOK we can skip handle cache. without - // FAILOK we still need to promote (or do something smarter) to - // determine whether to return ENOENT or 0. - if (iter == m->ops.begin() && - iter->op.flags == CEPH_OSD_OP_FLAG_FAILOK) { - op->set_skip_handle_cache(); - } - // skip promotion when proxying a delete op - if (m->ops.size() == 1) { - op->set_skip_promote(); - } - break; - - case CEPH_OSD_OP_CACHE_TRY_FLUSH: - case CEPH_OSD_OP_CACHE_FLUSH: - case CEPH_OSD_OP_CACHE_EVICT: - // If try_flush/flush/evict is the only op, can skip handle cache. - if (m->ops.size() == 1) { - op->set_skip_handle_cache(); - } - break; - - case CEPH_OSD_OP_READ: - case CEPH_OSD_OP_SYNC_READ: - case CEPH_OSD_OP_SPARSE_READ: - case CEPH_OSD_OP_CHECKSUM: - case CEPH_OSD_OP_WRITEFULL: - if (m->ops.size() == 1 && - (iter->op.flags & CEPH_OSD_OP_FLAG_FADVISE_NOCACHE || - iter->op.flags & CEPH_OSD_OP_FLAG_FADVISE_DONTNEED)) { - op->set_skip_promote(); - } - break; - - // force promotion when pin an object in cache tier - case CEPH_OSD_OP_CACHE_PIN: - op->set_promote(); - break; - - default: - break; - } - } - - if (op->rmw_flags == 0) - return -EINVAL; - - return 0; -} - void OSD::set_perf_queries( const std::map &queries) { dout(10) << "setting " << queries.size() << " queries" << dendl; diff --git a/src/osd/OSD.h b/src/osd/OSD.h index 353164118a44..58ef72b73436 100644 --- a/src/osd/OSD.h +++ b/src/osd/OSD.h @@ -2037,8 +2037,6 @@ private: void handle_fast_scrub(struct MOSDScrub2 *m); void handle_osd_ping(class MOSDPing *m); - int init_op_flags(OpRequestRef& op); - size_t get_num_cache_shards(); int get_num_op_shards(); int get_num_op_threads(); diff --git a/src/osd/OSDCap.cc b/src/osd/OSDCap.cc index b6df192c31ea..dfc7eae9ec37 100644 --- a/src/osd/OSDCap.cc +++ b/src/osd/OSDCap.cc @@ -249,7 +249,7 @@ bool OSDCapGrant::is_capable( const string& object, bool op_may_read, bool op_may_write, - const std::vector& classes, + const std::vector& classes, const entity_addr_t& addr, std::vector* class_allowed) const { @@ -377,7 +377,7 @@ bool OSDCap::is_capable(const string& pool_name, const string& ns, const OSDCapPoolTag::app_map_t& application_metadata, const string& object, bool op_may_read, bool op_may_write, - const std::vector& classes, + const std::vector& classes, const entity_addr_t& addr) const { std::vector class_allowed(classes.size(), false); diff --git a/src/osd/OSDCap.h b/src/osd/OSDCap.h index 2bb4e21ca1a4..d6a29b159459 100644 --- a/src/osd/OSDCap.h +++ b/src/osd/OSDCap.h @@ -211,7 +211,7 @@ struct OSDCapGrant { bool is_capable(const string& pool_name, const string& ns, const OSDCapPoolTag::app_map_t& application_metadata, const string& object, bool op_may_read, bool op_may_write, - const std::vector& classes, + const std::vector& classes, const entity_addr_t& addr, std::vector* class_allowed) const; @@ -249,7 +249,7 @@ struct OSDCap { bool is_capable(const string& pool_name, const string& ns, const OSDCapPoolTag::app_map_t& application_metadata, const string& object, bool op_may_read, bool op_may_write, - const std::vector& classes, + const std::vector& classes, const entity_addr_t& addr) const; }; diff --git a/src/osd/OpRequest.cc b/src/osd/OpRequest.cc index f37e1d7839c0..0eb92c23a6a3 100644 --- a/src/osd/OpRequest.cc +++ b/src/osd/OpRequest.cc @@ -32,7 +32,6 @@ using ceph::Formatter; OpRequest::OpRequest(Message* req, OpTracker* tracker) : TrackedOp(tracker, req->get_throttle_stamp()), - rmw_flags(0), request(req), hit_flag_points(0), latest_flag_point(0), @@ -101,66 +100,22 @@ void OpRequest::_unregistered() { request->set_connection(nullptr); } -bool OpRequest::check_rmw(int flag) const { - ceph_assert(rmw_flags != 0); - return rmw_flags & flag; -} -bool OpRequest::may_read() const { - return need_read_cap() || check_rmw(CEPH_OSD_RMW_FLAG_CLASS_READ); -} -bool OpRequest::may_write() const { - return need_write_cap() || check_rmw(CEPH_OSD_RMW_FLAG_CLASS_WRITE); -} -bool OpRequest::may_cache() const { return check_rmw(CEPH_OSD_RMW_FLAG_CACHE); } -bool OpRequest::rwordered_forced() const { - return check_rmw(CEPH_OSD_RMW_FLAG_RWORDERED); -} -bool OpRequest::rwordered() const { - return may_write() || may_cache() || rwordered_forced(); -} +int OpRequest::maybe_init_op_info(const OSDMap &osdmap) { + if (op_info.get_flags()) + return 0; -bool OpRequest::includes_pg_op() { return check_rmw(CEPH_OSD_RMW_FLAG_PGOP); } -bool OpRequest::need_read_cap() const { - return check_rmw(CEPH_OSD_RMW_FLAG_READ); -} -bool OpRequest::need_write_cap() const { - return check_rmw(CEPH_OSD_RMW_FLAG_WRITE); -} -bool OpRequest::need_promote() { - return check_rmw(CEPH_OSD_RMW_FLAG_FORCE_PROMOTE); -} -bool OpRequest::need_skip_handle_cache() { - return check_rmw(CEPH_OSD_RMW_FLAG_SKIP_HANDLE_CACHE); -} -bool OpRequest::need_skip_promote() { - return check_rmw(CEPH_OSD_RMW_FLAG_SKIP_PROMOTE); -} -bool OpRequest::allows_returnvec() const { - return check_rmw(CEPH_OSD_RMW_FLAG_RETURNVEC); -} + auto m = get_req(); -void OpRequest::set_rmw_flags(int flags) { #ifdef WITH_LTTNG - int old_rmw_flags = rmw_flags; + auto old_rmw_flags = op_info.get_flags(); #endif - rmw_flags |= flags; + auto ret = op_info.set_from_op(m, osdmap); tracepoint(oprequest, set_rmw_flags, reqid.name._type, reqid.name._num, reqid.tid, reqid.inc, - flags, old_rmw_flags, rmw_flags); + op_info.get_flags(), old_rmw_flags, op_info.get_flags()); + return ret; } -void OpRequest::set_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_READ); } -void OpRequest::set_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_WRITE); } -void OpRequest::set_class_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_READ); } -void OpRequest::set_class_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_WRITE); } -void OpRequest::set_pg_op() { set_rmw_flags(CEPH_OSD_RMW_FLAG_PGOP); } -void OpRequest::set_cache() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CACHE); } -void OpRequest::set_promote() { set_rmw_flags(CEPH_OSD_RMW_FLAG_FORCE_PROMOTE); } -void OpRequest::set_skip_handle_cache() { set_rmw_flags(CEPH_OSD_RMW_FLAG_SKIP_HANDLE_CACHE); } -void OpRequest::set_skip_promote() { set_rmw_flags(CEPH_OSD_RMW_FLAG_SKIP_PROMOTE); } -void OpRequest::set_force_rwordered() { set_rmw_flags(CEPH_OSD_RMW_FLAG_RWORDERED); } -void OpRequest::set_returnvec() { set_rmw_flags(CEPH_OSD_RMW_FLAG_RETURNVEC); } - void OpRequest::mark_flag_point(uint8_t flag, const char *s) { #ifdef WITH_LTTNG uint8_t old_flags = hit_flag_points; @@ -169,7 +124,7 @@ void OpRequest::mark_flag_point(uint8_t flag, const char *s) { hit_flag_points |= flag; latest_flag_point = flag; tracepoint(oprequest, mark_flag_point, reqid.name._type, - reqid.name._num, reqid.tid, reqid.inc, rmw_flags, + reqid.name._num, reqid.tid, reqid.inc, op_info.get_flags(), flag, s, old_flags, hit_flag_points); } @@ -181,7 +136,7 @@ void OpRequest::mark_flag_point_string(uint8_t flag, const string& s) { hit_flag_points |= flag; latest_flag_point = flag; tracepoint(oprequest, mark_flag_point, reqid.name._type, - reqid.name._num, reqid.tid, reqid.inc, rmw_flags, + reqid.name._num, reqid.tid, reqid.inc, op_info.get_flags(), flag, s.c_str(), old_flags, hit_flag_points); } @@ -213,9 +168,3 @@ bool OpRequest::filter_out(const set& filters) return false; } -ostream& operator<<(ostream& out, const OpRequest::ClassInfo& i) -{ - out << "class " << i.class_name << " method " << i.method_name - << " rd " << i.read << " wr " << i.write << " wl " << i.whitelisted; - return out; -} diff --git a/src/osd/OpRequest.h b/src/osd/OpRequest.h index 565ecb8969b2..dc5b5e34b1f2 100644 --- a/src/osd/OpRequest.h +++ b/src/osd/OpRequest.h @@ -14,6 +14,7 @@ #ifndef OPREQUEST_H_ #define OPREQUEST_H_ +#include "osd/osd_op_util.h" #include "osd/osd_types.h" #include "common/TrackedOp.h" @@ -24,53 +25,30 @@ struct OpRequest : public TrackedOp { friend class OpTracker; - // rmw flags - int rmw_flags; - - bool check_rmw(int flag) const ; - bool may_read() const; - bool may_write() const; - bool may_cache() const; - bool rwordered_forced() const; - bool rwordered() const; - bool includes_pg_op(); - bool need_read_cap() const; - bool need_write_cap() const; - bool need_promote(); - bool need_skip_handle_cache(); - bool need_skip_promote(); - bool allows_returnvec() const; - void set_read(); - void set_write(); - void set_cache(); - void set_class_read(); - void set_class_write(); - void set_pg_op(); - void set_promote(); - void set_skip_handle_cache(); - void set_skip_promote(); - void set_force_rwordered(); - void set_returnvec(); - - struct ClassInfo { - ClassInfo(std::string&& class_name, std::string&& method_name, - bool read, bool write, bool whitelisted) : - class_name(std::move(class_name)), method_name(std::move(method_name)), - read(read), write(write), whitelisted(whitelisted) - {} - const std::string class_name; - const std::string method_name; - const bool read, write, whitelisted; - }; - - void add_class(std::string&& class_name, std::string&& method_name, - bool read, bool write, bool whitelisted) { - classes_.emplace_back(std::move(class_name), std::move(method_name), - read, write, whitelisted); - } +private: + OpInfo op_info; - std::vector classes() const { - return classes_; +public: + int maybe_init_op_info(const OSDMap &osdmap); + + auto get_flags() const { return op_info.get_flags(); } + bool op_info_needs_init() const { return op_info.get_flags() == 0; } + bool check_rmw(int flag) const { return op_info.check_rmw(flag); } + bool may_read() const { return op_info.may_read(); } + bool may_write() const { return op_info.may_write(); } + bool may_cache() const { return op_info.may_cache(); } + bool rwordered_forced() const { return op_info.rwordered_forced(); } + bool rwordered() const { return op_info.rwordered(); } + bool includes_pg_op() const { return op_info.includes_pg_op(); } + bool need_read_cap() const { return op_info.need_read_cap(); } + bool need_write_cap() const { return op_info.need_write_cap(); } + bool need_promote() const { return op_info.need_promote(); } + bool need_skip_handle_cache() const { return op_info.need_skip_handle_cache(); } + bool need_skip_promote() const { return op_info.need_skip_promote(); } + bool allows_returnvec() const { return op_info.allows_returnvec(); } + + std::vector classes() const { + return op_info.get_classes(); } void _dump(ceph::Formatter *f) const override; @@ -93,8 +71,6 @@ private: static const uint8_t flag_sub_op_sent = 1 << 4; static const uint8_t flag_commit_sent = 1 << 5; - std::vector classes_; - OpRequest(Message *req, OpTracker *tracker); protected: @@ -173,13 +149,10 @@ public: typedef boost::intrusive_ptr Ref; private: - void set_rmw_flags(int flags); void mark_flag_point(uint8_t flag, const char *s); void mark_flag_point_string(uint8_t flag, const std::string& s); }; typedef OpRequest::Ref OpRequestRef; -std::ostream& operator<<(std::ostream& out, const OpRequest::ClassInfo& i); - #endif /* OPREQUEST_H_ */ diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index e06fa6c8c558..3cd06d5d2da3 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -1849,8 +1849,8 @@ void PrimaryLogPG::do_op(OpRequestRef& op) return; } - if (op->rmw_flags == 0) { - int r = osd->osd->init_op_flags(op); + { + int r = op->maybe_init_op_info(*get_osdmap()); if (r) { osd->reply_op_error(op, r); return; diff --git a/src/osd/osd_op_util.cc b/src/osd/osd_op_util.cc new file mode 100644 index 000000000000..f1aaf61e7103 --- /dev/null +++ b/src/osd/osd_op_util.cc @@ -0,0 +1,256 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "osd/osd_op_util.h" + +#include "osd/ClassHandler.h" +#include "messages/MOSDOp.h" + +bool OpInfo::check_rmw(int flag) const { + ceph_assert(rmw_flags != 0); + return rmw_flags & flag; +} +bool OpInfo::may_read() const { + return need_read_cap() || check_rmw(CEPH_OSD_RMW_FLAG_CLASS_READ); +} +bool OpInfo::may_write() const { + return need_write_cap() || check_rmw(CEPH_OSD_RMW_FLAG_CLASS_WRITE); +} +bool OpInfo::may_cache() const { return check_rmw(CEPH_OSD_RMW_FLAG_CACHE); } +bool OpInfo::rwordered_forced() const { + return check_rmw(CEPH_OSD_RMW_FLAG_RWORDERED); +} +bool OpInfo::rwordered() const { + return may_write() || may_cache() || rwordered_forced(); +} + +bool OpInfo::includes_pg_op() const { + return check_rmw(CEPH_OSD_RMW_FLAG_PGOP); +} +bool OpInfo::need_read_cap() const { + return check_rmw(CEPH_OSD_RMW_FLAG_READ); +} +bool OpInfo::need_write_cap() const { + return check_rmw(CEPH_OSD_RMW_FLAG_WRITE); +} +bool OpInfo::need_promote() const { + return check_rmw(CEPH_OSD_RMW_FLAG_FORCE_PROMOTE); +} +bool OpInfo::need_skip_handle_cache() const { + return check_rmw(CEPH_OSD_RMW_FLAG_SKIP_HANDLE_CACHE); +} +bool OpInfo::need_skip_promote() const { + return check_rmw(CEPH_OSD_RMW_FLAG_SKIP_PROMOTE); +} +bool OpInfo::allows_returnvec() const { + return check_rmw(CEPH_OSD_RMW_FLAG_RETURNVEC); +} + +void OpInfo::set_rmw_flags(int flags) { + rmw_flags |= flags; +} + +void OpInfo::set_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_READ); } +void OpInfo::set_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_WRITE); } +void OpInfo::set_class_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_READ); } +void OpInfo::set_class_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_WRITE); } +void OpInfo::set_pg_op() { set_rmw_flags(CEPH_OSD_RMW_FLAG_PGOP); } +void OpInfo::set_cache() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CACHE); } +void OpInfo::set_promote() { set_rmw_flags(CEPH_OSD_RMW_FLAG_FORCE_PROMOTE); } +void OpInfo::set_skip_handle_cache() { set_rmw_flags(CEPH_OSD_RMW_FLAG_SKIP_HANDLE_CACHE); } +void OpInfo::set_skip_promote() { set_rmw_flags(CEPH_OSD_RMW_FLAG_SKIP_PROMOTE); } +void OpInfo::set_force_rwordered() { set_rmw_flags(CEPH_OSD_RMW_FLAG_RWORDERED); } +void OpInfo::set_returnvec() { set_rmw_flags(CEPH_OSD_RMW_FLAG_RETURNVEC); } + + +int OpInfo::set_from_op( + const MOSDOp *m, + const OSDMap &osdmap) +{ + vector::const_iterator iter; + + // client flags have no bearing on whether an op is a read, write, etc. + clear(); + + if (m->has_flag(CEPH_OSD_FLAG_RWORDERED)) { + set_force_rwordered(); + } + if (m->has_flag(CEPH_OSD_FLAG_RETURNVEC)) { + set_returnvec(); + } + + // set bits based on op codes, called methods. + for (iter = m->ops.begin(); iter != m->ops.end(); ++iter) { + if ((iter->op.op == CEPH_OSD_OP_WATCH && + iter->op.watch.op == CEPH_OSD_WATCH_OP_PING)) { + /* This a bit odd. PING isn't actually a write. It can't + * result in an update to the object_info. PINGs also aren't + * resent, so there's no reason to write out a log entry. + * + * However, we pipeline them behind writes, so let's force + * the write_ordered flag. + */ + set_force_rwordered(); + } else { + if (ceph_osd_op_mode_modify(iter->op.op)) + set_write(); + } + if (ceph_osd_op_mode_read(iter->op.op)) + set_read(); + + // set READ flag if there are src_oids + if (iter->soid.oid.name.length()) + set_read(); + + // set PGOP flag if there are PG ops + if (ceph_osd_op_type_pg(iter->op.op)) + set_pg_op(); + + if (ceph_osd_op_mode_cache(iter->op.op)) + set_cache(); + + // check for ec base pool + int64_t poolid = m->get_pg().pool(); + const pg_pool_t *pool = osdmap.get_pg_pool(poolid); + if (pool && pool->is_tier()) { + const pg_pool_t *base_pool = osdmap.get_pg_pool(pool->tier_of); + if (base_pool && base_pool->require_rollback()) { + if ((iter->op.op != CEPH_OSD_OP_READ) && + (iter->op.op != CEPH_OSD_OP_CHECKSUM) && + (iter->op.op != CEPH_OSD_OP_CMPEXT) && + (iter->op.op != CEPH_OSD_OP_STAT) && + (iter->op.op != CEPH_OSD_OP_ISDIRTY) && + (iter->op.op != CEPH_OSD_OP_UNDIRTY) && + (iter->op.op != CEPH_OSD_OP_GETXATTR) && + (iter->op.op != CEPH_OSD_OP_GETXATTRS) && + (iter->op.op != CEPH_OSD_OP_CMPXATTR) && + (iter->op.op != CEPH_OSD_OP_ASSERT_VER) && + (iter->op.op != CEPH_OSD_OP_LIST_WATCHERS) && + (iter->op.op != CEPH_OSD_OP_LIST_SNAPS) && + (iter->op.op != CEPH_OSD_OP_SETALLOCHINT) && + (iter->op.op != CEPH_OSD_OP_WRITEFULL) && + (iter->op.op != CEPH_OSD_OP_ROLLBACK) && + (iter->op.op != CEPH_OSD_OP_CREATE) && + (iter->op.op != CEPH_OSD_OP_DELETE) && + (iter->op.op != CEPH_OSD_OP_SETXATTR) && + (iter->op.op != CEPH_OSD_OP_RMXATTR) && + (iter->op.op != CEPH_OSD_OP_STARTSYNC) && + (iter->op.op != CEPH_OSD_OP_COPY_GET) && + (iter->op.op != CEPH_OSD_OP_COPY_FROM)) { + set_promote(); + } + } + } + + switch (iter->op.op) { + case CEPH_OSD_OP_CALL: + { + bufferlist::iterator bp = const_cast(iter->indata).begin(); + int is_write, is_read; + string cname, mname; + bp.copy(iter->op.cls.class_len, cname); + bp.copy(iter->op.cls.method_len, mname); + + ClassHandler::ClassData *cls; + int r = ClassHandler::get_instance().open_class(cname, &cls); + if (r) { + if (r == -ENOENT) + r = -EOPNOTSUPP; + else if (r != -EPERM) // propagate permission errors + r = -EIO; + return r; + } + int flags = cls->get_method_flags(mname); + if (flags < 0) { + if (flags == -ENOENT) + r = -EOPNOTSUPP; + else + r = flags; + return r; + } + is_read = flags & CLS_METHOD_RD; + is_write = flags & CLS_METHOD_WR; + bool is_promote = flags & CLS_METHOD_PROMOTE; + + if (is_read) + set_class_read(); + if (is_write) + set_class_write(); + if (is_promote) + set_promote(); + add_class(std::move(cname), std::move(mname), is_read, is_write, + cls->whitelisted); + break; + } + + case CEPH_OSD_OP_WATCH: + // force the read bit for watch since it is depends on previous + // watch state (and may return early if the watch exists) or, in + // the case of ping, is simply a read op. + set_read(); + // fall through + case CEPH_OSD_OP_NOTIFY: + case CEPH_OSD_OP_NOTIFY_ACK: + { + set_promote(); + break; + } + + case CEPH_OSD_OP_DELETE: + // if we get a delete with FAILOK we can skip handle cache. without + // FAILOK we still need to promote (or do something smarter) to + // determine whether to return ENOENT or 0. + if (iter == m->ops.begin() && + iter->op.flags == CEPH_OSD_OP_FLAG_FAILOK) { + set_skip_handle_cache(); + } + // skip promotion when proxying a delete op + if (m->ops.size() == 1) { + set_skip_promote(); + } + break; + + case CEPH_OSD_OP_CACHE_TRY_FLUSH: + case CEPH_OSD_OP_CACHE_FLUSH: + case CEPH_OSD_OP_CACHE_EVICT: + // If try_flush/flush/evict is the only op, can skip handle cache. + if (m->ops.size() == 1) { + set_skip_handle_cache(); + } + break; + + case CEPH_OSD_OP_READ: + case CEPH_OSD_OP_SYNC_READ: + case CEPH_OSD_OP_SPARSE_READ: + case CEPH_OSD_OP_CHECKSUM: + case CEPH_OSD_OP_WRITEFULL: + if (m->ops.size() == 1 && + (iter->op.flags & CEPH_OSD_OP_FLAG_FADVISE_NOCACHE || + iter->op.flags & CEPH_OSD_OP_FLAG_FADVISE_DONTNEED)) { + set_skip_promote(); + } + break; + + // force promotion when pin an object in cache tier + case CEPH_OSD_OP_CACHE_PIN: + set_promote(); + break; + + default: + break; + } + } + + if (rmw_flags == 0) + return -EINVAL; + + return 0; + +} + +ostream& operator<<(ostream& out, const OpInfo::ClassInfo& i) +{ + out << "class " << i.class_name << " method " << i.method_name + << " rd " << i.read << " wr " << i.write << " wl " << i.whitelisted; + return out; +} diff --git a/src/osd/osd_op_util.h b/src/osd/osd_op_util.h new file mode 100644 index 000000000000..92dac0f5cd32 --- /dev/null +++ b/src/osd/osd_op_util.h @@ -0,0 +1,82 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include +#include + +#include "osd/OSDMap.h" + +class MOSDOp; +class OpInfo { +public: + struct ClassInfo { + ClassInfo(std::string&& class_name, std::string&& method_name, + bool read, bool write, bool whitelisted) : + class_name(std::move(class_name)), method_name(std::move(method_name)), + read(read), write(write), whitelisted(whitelisted) + {} + const std::string class_name; + const std::string method_name; + const bool read, write, whitelisted; + }; + +private: + uint64_t rmw_flags = 0; + std::vector classes; + + void set_rmw_flags(int flags); + + void add_class(std::string&& class_name, std::string&& method_name, + bool read, bool write, bool whitelisted) { + classes.emplace_back(std::move(class_name), std::move(method_name), + read, write, whitelisted); + } + +public: + + void clear() { + rmw_flags = 0; + } + + uint64_t get_flags() const { + return rmw_flags; + } + + bool check_rmw(int flag) const ; + bool may_read() const; + bool may_write() const; + bool may_cache() const; + bool rwordered_forced() const; + bool rwordered() const; + bool includes_pg_op() const; + bool need_read_cap() const; + bool need_write_cap() const; + bool need_promote() const; + bool need_skip_handle_cache() const; + bool need_skip_promote() const; + bool allows_returnvec() const; + + void set_read(); + void set_write(); + void set_cache(); + void set_class_read(); + void set_class_write(); + void set_pg_op(); + void set_promote(); + void set_skip_handle_cache(); + void set_skip_promote(); + void set_force_rwordered(); + void set_returnvec(); + + int set_from_op( + const MOSDOp *m, + const OSDMap &osdmap); + + std::vector get_classes() const { + return classes; + } +}; + +std::ostream& operator<<(std::ostream& out, const OpInfo::ClassInfo& i);