]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/osd: add support for CEPH_OSD_OP_TRUNCATE. 36442/head
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 3 Aug 2020 19:50:33 +0000 (21:50 +0200)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 3 Aug 2020 19:51:05 +0000 (21:51 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/common/errorator.h
src/crimson/osd/ops_executer.cc
src/crimson/osd/ops_executer.h
src/crimson/osd/pg_backend.cc
src/crimson/osd/pg_backend.h

index 95454ca424cfa6bf4de1b97b53a86ab70a89e47c..52ade2dde1fccca8eb7e34ed3a71fc1b1032902e 100644 (file)
@@ -964,6 +964,8 @@ namespace ct_error {
   using value_too_large = ct_error_code<std::errc::value_too_large>;
   using eagain =
     ct_error_code<std::errc::resource_unavailable_try_again>;
+  using file_too_large =
+    ct_error_code<std::errc::file_too_large>;
 
   struct pass_further_all {
     template <class ErrorT>
index 739b7c65e330f441b0f7416f3c34304a0d18ea24..a313beaf34849d6e975b262fa2a45028ac0bf891 100644 (file)
@@ -709,6 +709,13 @@ OpsExecuter::execute_osd_op(OSDOp& osd_op)
       osd_op_params = osd_op_params_t();
       return backend.writefull(os, osd_op, txn, *osd_op_params);
     }, true);
+  case CEPH_OSD_OP_TRUNCATE:
+    return do_write_op([this, &osd_op] (auto& backend, auto& os, auto& txn) {
+      // FIXME: rework needed. Move this out to do_write_op(), introduce
+      // do_write_op_no_user_modify()...
+      osd_op_params = osd_op_params_t();
+      return backend.truncate(os, osd_op, txn, *osd_op_params);
+    }, true);
   case CEPH_OSD_OP_SETALLOCHINT:
     return osd_op_errorator::now();
   case CEPH_OSD_OP_SETXATTR:
index 8c5168dc8bb645b8138b4fb463c23b620ecdbfd0..036c02632c02368d54f6fb54c89bbbcd72216386 100644 (file)
@@ -45,6 +45,7 @@ class OpsExecuter {
     crimson::ct_error::input_output_error,
     crimson::ct_error::value_too_large>;
   using read_errorator = PGBackend::read_errorator;
+  using write_ertr = PGBackend::write_ertr;
   using get_attr_errorator = PGBackend::get_attr_errorator;
   using watch_errorator = crimson::errorator<
     crimson::ct_error::enoent,
@@ -62,6 +63,7 @@ public:
   using osd_op_errorator = crimson::compound_errorator_t<
     call_errorator,
     read_errorator,
+    write_ertr,
     get_attr_errorator,
     watch_errorator,
     PGBackend::stat_errorator>;
index 2daecc49acbd55f095bef50fe726a17fef5dc6c9..bb1e36c7684867aca716795bc640229274fcb995 100644 (file)
@@ -250,6 +250,21 @@ bool PGBackend::maybe_create_new_object(
   return true;
 }
 
+static bool is_offset_and_length_valid(
+  const std::uint64_t offset,
+  const std::uint64_t length)
+{
+  if (const std::uint64_t max = local_conf()->osd_max_object_size;
+      offset >= max || length > max || offset + length > max) {
+    logger().debug("{} osd_max_object_size: {}, offset: {}, len: {}; "
+                   "Hard limit of object size is 4GB",
+                   __func__, max, offset, length);
+    return false;
+  } else {
+    return true;
+  }
+}
+
 seastar::future<> PGBackend::write(
     ObjectState& os,
     const OSDOp& osd_op,
@@ -340,6 +355,52 @@ seastar::future<> PGBackend::writefull(
   return seastar::now();
 }
 
+PGBackend::write_ertr::future<> PGBackend::truncate(
+  ObjectState& os,
+  const OSDOp& osd_op,
+  ceph::os::Transaction& txn,
+  osd_op_params_t& osd_op_params)
+{
+  if (!os.exists || os.oi.is_whiteout()) {
+    logger().debug("{} object dne, truncate is a no-op", __func__);
+    return write_ertr::now();
+  }
+  const ceph_osd_op& op = osd_op.op;
+  if (!is_offset_and_length_valid(op.extent.offset, op.extent.length)) {
+    return crimson::ct_error::file_too_large::make();
+  }
+  if (op.extent.truncate_seq) {
+    assert(op.extent.offset == op.extent.truncate_size);
+    if (op.extent.truncate_seq <= os.oi.truncate_seq) {
+      logger().debug("{} truncate seq {} <= current {}, no-op",
+                     __func__, op.extent.truncate_seq, os.oi.truncate_seq);
+      return write_ertr::make_ready_future<>();
+    } else {
+      logger().debug("{} truncate seq {} > current {}, truncating",
+                     __func__, op.extent.truncate_seq, os.oi.truncate_seq);
+      os.oi.truncate_seq = op.extent.truncate_seq;
+      os.oi.truncate_size = op.extent.truncate_size;
+    }
+  }
+  maybe_create_new_object(os, txn);
+  txn.truncate(coll->get_cid(),
+               ghobject_t{os.oi.soid}, op.extent.offset);
+  if (os.oi.size > op.extent.offset) {
+    // TODO: modified_ranges.union_of(trim);
+    osd_op_params.clean_regions.mark_data_region_dirty(op.extent.offset,
+        os.oi.size - op.extent.offset);
+  } else if (os.oi.size < op.extent.offset) {
+    osd_op_params.clean_regions.mark_data_region_dirty(os.oi.size,
+        op.extent.offset - os.oi.size);
+  }
+  // TODO: truncate_update_size_and_usage()
+  // TODO: ctx->delta_stats.num_wr++;
+  // ----
+  // do no set exists, or we will break above DELETE -> TRUNCATE munging.
+  os.oi.clear_data_digest();
+  return write_ertr::now();
+}
+
 seastar::future<> PGBackend::create(
   ObjectState& os,
   const OSDOp& osd_op,
index 88fe608722fe0f188972de0b63e64c965f9057f2..dec58406eb32b9bad7c3d8fbefb3a93d7dd549d4 100644 (file)
@@ -68,6 +68,9 @@ public:
     const ObjectState& os,
     OSDOp& osd_op);
 
+  // TODO: switch the entire write family to errorator.
+  using write_ertr = crimson::errorator<
+    crimson::ct_error::file_too_large>;
   seastar::future<> create(
     ObjectState& os,
     const OSDOp& osd_op,
@@ -85,6 +88,11 @@ public:
     const OSDOp& osd_op,
     ceph::os::Transaction& trans,
     osd_op_params_t& osd_op_params);
+  write_ertr::future<> truncate(
+    ObjectState& os,
+    const OSDOp& osd_op,
+    ceph::os::Transaction& trans,
+    osd_op_params_t& osd_op_params);
   seastar::future<crimson::osd::acked_peers_t> mutate_object(
     std::set<pg_shard_t> pg_shards,
     crimson::osd::ObjectContextRef &&obc,