summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadoslaw Zarzynski <rzarzyns@redhat.com>2020-08-03 21:50:33 +0200
committerRadoslaw Zarzynski <rzarzyns@redhat.com>2020-08-03 21:51:05 +0200
commitdca8467764a7c6362d41d3254878ef4acaa740c3 (patch)
treeecd4b87962a4aa929245fbe2e1f839ddecf31749
parentMerge pull request #36367 from tchaikov/wip-46771 (diff)
downloadceph-dca8467764a7c6362d41d3254878ef4acaa740c3.tar.xz
ceph-dca8467764a7c6362d41d3254878ef4acaa740c3.zip
crimson/osd: add support for CEPH_OSD_OP_TRUNCATE.
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
-rw-r--r--src/crimson/common/errorator.h2
-rw-r--r--src/crimson/osd/ops_executer.cc7
-rw-r--r--src/crimson/osd/ops_executer.h2
-rw-r--r--src/crimson/osd/pg_backend.cc61
-rw-r--r--src/crimson/osd/pg_backend.h8
5 files changed, 80 insertions, 0 deletions
diff --git a/src/crimson/common/errorator.h b/src/crimson/common/errorator.h
index 95454ca424c..52ade2dde1f 100644
--- a/src/crimson/common/errorator.h
+++ b/src/crimson/common/errorator.h
@@ -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>
diff --git a/src/crimson/osd/ops_executer.cc b/src/crimson/osd/ops_executer.cc
index 739b7c65e33..a313beaf348 100644
--- a/src/crimson/osd/ops_executer.cc
+++ b/src/crimson/osd/ops_executer.cc
@@ -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:
diff --git a/src/crimson/osd/ops_executer.h b/src/crimson/osd/ops_executer.h
index 8c5168dc8bb..036c02632c0 100644
--- a/src/crimson/osd/ops_executer.h
+++ b/src/crimson/osd/ops_executer.h
@@ -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>;
diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc
index 2daecc49acb..bb1e36c7684 100644
--- a/src/crimson/osd/pg_backend.cc
+++ b/src/crimson/osd/pg_backend.cc
@@ -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,
diff --git a/src/crimson/osd/pg_backend.h b/src/crimson/osd/pg_backend.h
index 88fe608722f..dec58406eb3 100644
--- a/src/crimson/osd/pg_backend.h
+++ b/src/crimson/osd/pg_backend.h
@@ -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,