Skip to content

Commit 72fd15b

Browse files
committed
partitioning/strategy: Fail if flexible over-allocation
Signed-off-by: Ikey Doherty <[email protected]>
1 parent 5b0de9d commit 72fd15b

File tree

1 file changed

+88
-3
lines changed

1 file changed

+88
-3
lines changed

crates/partitioning/src/strategy.rs

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ impl Strategy {
212212
for (_idx, min, max_opt) in &flexible_requests {
213213
remaining_flexible -= 1;
214214

215+
// First verify we have enough space for minimum requirement
216+
if *min > remaining {
217+
// Clean up any changes we made since we can't complete all requests
218+
while planner.has_changes() {
219+
planner.undo();
220+
}
221+
return Err(PlanError::RegionOutOfBounds {
222+
start: current,
223+
end: current + min,
224+
});
225+
}
226+
215227
let size = if remaining_flexible == 0 {
216228
// Last flexible partition gets all remaining space
217229
let size = remaining;
@@ -231,9 +243,19 @@ impl Strategy {
231243
}
232244
};
233245

234-
planner.plan_add_partition(current, current + size)?;
235-
current += size;
236-
remaining -= size;
246+
match planner.plan_add_partition(current, current + size) {
247+
Ok(_) => {
248+
current += size;
249+
remaining -= size;
250+
}
251+
Err(e) => {
252+
// Clean up any changes we made since we can't complete all requests
253+
while planner.has_changes() {
254+
planner.undo();
255+
}
256+
return Err(e);
257+
}
258+
}
237259
}
238260

239261
Ok(())
@@ -382,4 +404,67 @@ mod tests {
382404
let layout = planner.current_layout();
383405
assert_eq!(layout.len(), 2);
384406
}
407+
408+
#[test]
409+
fn test_insufficient_space() {
410+
let disk = MockDisk::new(10 * GB); // Intentionally small disk
411+
let mut planner = Planner::new(&BlockDevice::mock_device(disk));
412+
let mut strategy = Strategy::new(AllocationStrategy::InitializeWholeDisk);
413+
414+
// Try to allocate more than available
415+
strategy.add_request(PartitionRequest {
416+
size: SizeRequirement::Exact(20 * GB),
417+
});
418+
419+
assert!(strategy.apply(&mut planner).is_err());
420+
}
421+
422+
#[test]
423+
fn test_flexible_partition_overflow() {
424+
let disk = MockDisk::new(10 * GB);
425+
let mut planner = Planner::new(&BlockDevice::mock_device(disk));
426+
let mut strategy = Strategy::new(AllocationStrategy::InitializeWholeDisk);
427+
428+
// Request more than available in flexible partitions
429+
strategy.add_request(PartitionRequest {
430+
size: SizeRequirement::AtLeast(6 * GB),
431+
});
432+
strategy.add_request(PartitionRequest {
433+
size: SizeRequirement::AtLeast(6 * GB),
434+
});
435+
436+
// Should fail because total minimum (12GB) exceeds disk size (10GB)
437+
let result = strategy.apply(&mut planner);
438+
assert!(matches!(result, Err(PlanError::RegionOutOfBounds { .. })));
439+
assert!(!planner.has_changes());
440+
}
441+
442+
#[test]
443+
fn test_partial_partition_creation() {
444+
let disk = MockDisk::new(8 * GB);
445+
let mut planner = Planner::new(&BlockDevice::mock_device(disk));
446+
let mut strategy = Strategy::new(AllocationStrategy::InitializeWholeDisk);
447+
448+
// Request sequence where first two would fit but third won't
449+
strategy.add_request(PartitionRequest {
450+
size: SizeRequirement::Range { min: GB, max: 2 * GB },
451+
});
452+
strategy.add_request(PartitionRequest {
453+
size: SizeRequirement::Range {
454+
min: 2 * GB,
455+
max: 4 * GB,
456+
},
457+
});
458+
strategy.add_request(PartitionRequest {
459+
size: SizeRequirement::Range {
460+
min: 25 * GB,
461+
max: 120 * GB,
462+
},
463+
});
464+
465+
// Should fail and undo partial changes
466+
let result = strategy.apply(&mut planner);
467+
assert!(matches!(result, Err(PlanError::RegionOutOfBounds { .. })));
468+
assert!(!planner.has_changes(), "Partial changes should be undone");
469+
}
385470
}

0 commit comments

Comments
 (0)