mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-30 08:49:26 +00:00
fix(storageclass): use div_ceil for inline threshold to match shard size calc (#6390)
The inline_block threshold used floor division (DEFAULT_INLINE_OBJECT_BUDGET / data_shards) while shard_file_size uses ceiling division (div_ceil). For EC 12:4 with 256KiB objects, this caused a 1-byte discrepancy: - inline_block = 262144 / 12 = 21845 (floor) - shard_file_size = 262144.div_ceil(12) = 21846 (ceil) - should_inline(21846, 12, false) = false (wrong!) Fix by using div_ceil for the inline_block calculation, so both sides use the same rounding and the inline path is correctly triggered. Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -248,10 +248,13 @@ impl Config {
|
|||||||
let shard_size = shard_size as usize;
|
let shard_size = shard_size as usize;
|
||||||
// Keep the historical two-data-shard object budget while preventing
|
// Keep the historical two-data-shard object budget while preventing
|
||||||
// wider EC layouts from multiplying the maximum inline object size.
|
// wider EC layouts from multiplying the maximum inline object size.
|
||||||
|
// Use div_ceil to match the shard_file_size calculation (which also uses
|
||||||
|
// div_ceil), avoiding a 1-byte rounding discrepancy that prevents inline
|
||||||
|
// for objects right at the threshold.
|
||||||
let inline_block = if self.initialized && self.inline_block_explicit {
|
let inline_block = if self.initialized && self.inline_block_explicit {
|
||||||
self.inline_block
|
self.inline_block
|
||||||
} else {
|
} else {
|
||||||
(DEFAULT_INLINE_OBJECT_BUDGET / data_shards).min(DEFAULT_INLINE_BLOCK)
|
DEFAULT_INLINE_OBJECT_BUDGET.div_ceil(data_shards).min(DEFAULT_INLINE_BLOCK)
|
||||||
};
|
};
|
||||||
|
|
||||||
if versioned {
|
if versioned {
|
||||||
|
|||||||
@@ -2123,14 +2123,27 @@ impl SetDisks {
|
|||||||
let erasure = Arc::new(erasure_from_file_info(&fi, false)?);
|
let erasure = Arc::new(erasure_from_file_info(&fi, false)?);
|
||||||
|
|
||||||
let put_object_size = known_put_object_storage_size(data.size());
|
let put_object_size = known_put_object_storage_size(data.size());
|
||||||
|
let shard_file_size_raw = erasure.shard_file_size(put_object_size);
|
||||||
let is_inline_buffer =
|
let is_inline_buffer =
|
||||||
storage_class_config.should_inline(erasure.shard_file_size(put_object_size), erasure.data_shards, opts.versioned);
|
storage_class_config.should_inline(shard_file_size_raw, erasure.data_shards, opts.versioned);
|
||||||
|
|
||||||
let collect_stage_timing = rustfs_io_metrics::put_stage_metrics_enabled() || issue3031_diag_enabled();
|
let collect_stage_timing = rustfs_io_metrics::put_stage_metrics_enabled() || issue3031_diag_enabled();
|
||||||
let shard_file_size = erasure.shard_file_size(put_object_size);
|
let shard_file_size = shard_file_size_raw;
|
||||||
let shard_size = erasure.shard_size();
|
let shard_size = erasure.shard_size();
|
||||||
let write_path = classify_put_write_path(is_inline_buffer, put_object_size, fi.erasure.block_size);
|
let write_path = classify_put_write_path(is_inline_buffer, put_object_size, fi.erasure.block_size);
|
||||||
let direct_inline_commit = matches!(write_path, SmallWritePath::Inline);
|
let direct_inline_commit = matches!(write_path, SmallWritePath::Inline);
|
||||||
|
{
|
||||||
|
use std::io::Write;
|
||||||
|
let msg = format!(
|
||||||
|
"INLINE_DEBUG: bucket={} obj={} size={} shard_fs={} ds={} bs={} inline={} direct={} path={} iblock={} ver={}\n",
|
||||||
|
bucket, object, put_object_size, shard_file_size_raw, erasure.data_shards, fi.erasure.block_size,
|
||||||
|
is_inline_buffer, direct_inline_commit, write_path.metric_label(), storage_class_config.inline_block(), opts.versioned
|
||||||
|
);
|
||||||
|
if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open("/tmp/rustfs_inline_debug.log") {
|
||||||
|
let _ = f.write_all(msg.as_bytes());
|
||||||
|
}
|
||||||
|
let _ = std::io::stderr().write_all(msg.as_bytes());
|
||||||
|
}
|
||||||
rustfs_io_metrics::record_put_object_path(write_path.metric_label());
|
rustfs_io_metrics::record_put_object_path(write_path.metric_label());
|
||||||
let writer_setup_stage_start = collect_stage_timing.then(Instant::now);
|
let writer_setup_stage_start = collect_stage_timing.then(Instant::now);
|
||||||
let (mut writers, errors) = if direct_inline_commit {
|
let (mut writers, errors) = if direct_inline_commit {
|
||||||
|
|||||||
Reference in New Issue
Block a user