]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/osd: implement CEPH_OSD_OP_CALL.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 31 Jul 2019 17:52:45 +0000 (19:52 +0200)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Fri, 23 Aug 2019 23:27:44 +0000 (01:27 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/osd/exceptions.h
src/crimson/osd/pg.cc
src/crimson/osd/pg_backend.cc
src/crimson/osd/pg_backend.h

index ab20dd248e557e40a1f177f7e34543c00aa3a4fa..563cc4e3f532e8d126f967f997bf7b9f09238b41 100644 (file)
@@ -16,12 +16,17 @@ public:
   using system_error::code;
   using system_error::what;
 
+  friend error make_error(int ret);
+
 private:
   error(const int ret) noexcept
     : system_error(ret, std::system_category()) {
   }
 };
 
+inline error make_error(const int ret) {
+  return error{-ret};
+}
 
 struct object_not_found : public error {
   object_not_found() : error(std::errc::no_such_file_or_directory) {}
@@ -35,4 +40,19 @@ struct invalid_argument : public error {
   invalid_argument() : error(std::errc::invalid_argument) {}
 };
 
+// FIXME: error handling
+struct operation_not_supported : public error {
+  operation_not_supported()
+    : error(std::errc::operation_not_supported) {
+  }
+};
+
+struct permission_denied : public error {
+  permission_denied() : error(std::errc::operation_not_permitted) {}
+};
+
+struct input_output_error : public error {
+  input_output_error() : error(std::errc::io_error) {}
+};
+
 } // namespace ceph::osd
index 3c1082b07d8b9a486509e6eab91bb4f761da0689..dd0edf70512f8eaeb8b03faaa2d533f5f439eb43 100644 (file)
@@ -366,6 +366,8 @@ PG::do_osd_op(ObjectState& os, OSDOp& osd_op, ceph::os::Transaction& txn)
     });
   case CEPH_OSD_OP_DELETE:
     return backend->remove(os, txn);
+  case CEPH_OSD_OP_CALL:
+    return backend->call(os, osd_op, txn);
   default:
     logger().warn("unknown op {}", ceph_osd_op_name(op.op));
     throw std::runtime_error(
index 31d3902f963662f35d8f01a5255812c7417ac12f..4ae3adc760a3d8d5d87852ffee608576686dd170 100644 (file)
@@ -8,6 +8,7 @@
 #include <boost/range/adaptor/transformed.hpp>
 #include <boost/range/algorithm/copy.hpp>
 #include <fmt/ostream.h>
+#include <seastar/core/thread.hh>
 #include <seastar/core/print.hh>
 
 #include "messages/MOSDOp.h"
@@ -19,6 +20,8 @@
 #include "ec_backend.h"
 #include "exceptions.h"
 
+#include "osd/ClassHandler.h"
+
 namespace {
   seastar::logger& logger() {
     return ceph::get_logger(ceph_subsys_osd);
@@ -374,3 +377,86 @@ PGBackend::list_objects(const hobject_t& start, uint64_t limit)
         objects, next.hobj);
     });
 }
+
+seastar::future<> PGBackend::call(
+  ObjectState& os,
+  OSDOp& osd_op,
+  ceph::os::Transaction& txn)
+{
+  if (!os.exists) {
+    throw ::object_not_found();
+  }
+
+  std::string cname, mname;
+  ceph::bufferlist indata;
+  try {
+    auto bp = std::begin(osd_op.indata);
+    bp.copy(osd_op.op.cls.class_len, cname);
+    bp.copy(osd_op.op.cls.method_len, mname);
+    bp.copy(osd_op.op.cls.indata_len, indata);
+  } catch (buffer::error& e) {
+    logger().warn("call unable to decode class + method + indata");
+    throw ::invalid_argument{};
+  }
+
+  // NOTE: opening a class can actually result in dlopen(), and thus
+  // blocking the entire reactor. Thankfully to ClassHandler's cache
+  // this is supposed to be extremely infrequent.
+  ClassHandler::ClassData* cls;
+  int r = ClassHandler::get_instance().open_class(cname, &cls);
+  if (r) {
+    logger().warn("class {} open got {}", cname, cpp_strerror(r));
+    if (r == -ENOENT) {
+      throw ceph::osd::operation_not_supported{};
+    } else if (r == -EPERM) {
+      // propagate permission errors
+      throw ceph::osd::permission_denied{};
+    }
+    throw ceph::osd::input_output_error{};
+  }
+
+  ClassHandler::ClassMethod* method = cls->get_method(mname);
+  if (!method) {
+    logger().warn("call method {}.{} does not exist", cname, mname);
+    throw ceph::osd::operation_not_supported{};
+  }
+
+  const auto flags = method->get_flags();
+#if 0
+  if (flags & CLS_METHOD_WR) {
+    ctx->user_modify = true;
+  }
+#endif
+
+  logger().debug("calling method {}.{}", cname, mname);
+#if 0
+  int prev_rd = ctx->num_read;
+  int prev_wr = ctx->num_write;
+#endif
+
+
+  return seastar::async([&osd_op, method, indata=std::move(indata)]() mutable {
+    ceph::bufferlist outdata;
+    const auto ret = method->exec((cls_method_context_t)&osd_op, indata, outdata);
+    if (ret < 0) {
+      throw ceph::osd::make_error(ret);
+    }
+#if 0
+       if (ctx->num_read > prev_rd && !(flags & CLS_METHOD_RD)) {
+         derr << "method " << cname << "." << mname << " tried to read object but is not marked RD" << dendl;
+         result = -EIO;
+         break;
+       }
+       if (ctx->num_write > prev_wr && !(flags & CLS_METHOD_WR)) {
+         derr << "method " << cname << "." << mname << " tried to update object but is not marked WR" << dendl;
+         result = -EIO;
+         break;
+       }
+#endif
+
+       logger().debug("method called response length={}", outdata.length());
+       osd_op.op.extent.length = outdata.length();
+       osd_op.outdata.claim_append(outdata);
+  });
+
+}
index fbc2653d74c0be50b1e82904f2e34f30ea085cd1..543c9ec84587ac21068521d8fe9eb29b375ed54b 100644 (file)
@@ -69,6 +69,10 @@ public:
   seastar::future<std::vector<hobject_t>, hobject_t> list_objects(
     const hobject_t& start,
     uint64_t limit);
+  seastar::future<> call(
+    ObjectState& os,
+    OSDOp& osd_op,
+    ceph::os::Transaction& txn);
 
   virtual void got_rep_op_reply(const MOSDRepOpReply&) {}