]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/seastore: reject oversized writes and zeros instead of aborting
authorKefu Chai <k.chai@proxmox.com>
Wed, 20 May 2026 07:36:51 +0000 (15:36 +0800)
committerKefu Chai <k.chai@proxmox.com>
Wed, 20 May 2026 11:23:33 +0000 (19:23 +0800)
prepare_data_reservation() ceph_assert()s the request fits within
seastore_default_max_object_size (16 MiB), but the OSD validates writes
against osd_max_object_size (128 MiB).  Anything between the two limits
passes OSD validation then trips the assert, crashing the OSD and its
replicas.

_zero() already returned EIO for this case; mirror that in _write() and
fix _zero()'s off-by-one (>= should be >, matching the <= in the assert).

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
src/crimson/os/seastore/seastore.cc

index 02c4d952652582bb718ef19882d15ffc3878bf40..35f0fa78dc9b1b46406a17f413784ee8a2541cfe 100644 (file)
@@ -2151,6 +2151,17 @@ SeaStore::Shard::_write(
   ceph::bufferlist &&_bl,
   uint32_t fadvise_flags)
 {
+  // SeaStore reserves max_object_size of laddr space per object;
+  // ObjectDataHandler::prepare_data_reservation() ceph_assert()s that
+  // the requested size fits.  Reject oversized writes here -- mirrors
+  // the corresponding check in _zero() -- so the OSD returns EIO to the
+  // client instead of aborting (and taking peer replicas with it).
+  if (offset + len > max_object_size) {
+    LOG_PREFIX(SeaStoreS::_write);
+    ERRORT("0x{:x}~0x{:x} > 0x{:x}",
+           *ctx.transaction, offset, len, max_object_size);
+    return crimson::ct_error::input_output_error::make();
+  }
   const auto &object_size = onode.get_layout().size;
   if (offset + len > object_size) {
     onode.update_onode_size(
@@ -2268,9 +2279,9 @@ SeaStore::Shard::_zero(
   objaddr_t offset,
   extent_len_t len)
 {
-  if (offset + len >= max_object_size) {
+  if (offset + len > max_object_size) {
     LOG_PREFIX(SeaStoreS::_zero);
-    ERRORT("0x{:x}~0x{:x} >= 0x{:x}",
+    ERRORT("0x{:x}~0x{:x} > 0x{:x}",
            *ctx.transaction, offset, len, max_object_size);
     return crimson::ct_error::input_output_error::make();
   }