Skip to content

Commit 69dfa13

Browse files
committed
partitioning: Add new attributes for gpt tagging
Signed-off-by: Ikey Doherty <[email protected]>
1 parent 72fd15b commit 69dfa13

File tree

6 files changed

+111
-9
lines changed

6 files changed

+111
-9
lines changed

crates/partitioning/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ thiserror.workspace = true
1010
log.workspace = true
1111
gpt.workspace = true
1212
nix.workspace = true
13+
uuid.workspace = true
1314
linux-raw-sys = { workspace = true, features = ["loop_device", "ioctl"] }
1415

1516
[dev-dependencies]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-FileCopyrightText: Copyright © 2025 AerynOS Developers
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
use gpt::partition_types;
6+
use uuid::Uuid;
7+
8+
/// Represents the attributes of a GPT partition
9+
#[derive(Debug, Clone)]
10+
pub struct GptAttributes {
11+
/// The type GUID that identifies the partition type
12+
pub type_guid: partition_types::Type,
13+
/// Optional name for the partition
14+
pub name: Option<String>,
15+
/// Optional UUID for the partition
16+
pub uuid: Option<Uuid>,
17+
}
18+
19+
impl Default for GptAttributes {
20+
fn default() -> Self {
21+
Self {
22+
type_guid: partition_types::BASIC,
23+
name: None,
24+
uuid: None,
25+
}
26+
}
27+
}
28+
29+
/// Represents attributes specific to different partition table types
30+
#[derive(Debug, Clone)]
31+
pub enum PartitionAttributes {
32+
/// GPT partition attributes
33+
Gpt(GptAttributes),
34+
//Mbr(MbrAttributes),
35+
}
36+
37+
impl PartitionAttributes {
38+
/// Returns a reference to the GPT attributes if this is a GPT partition
39+
///
40+
/// # Returns
41+
/// - `Some(&GptAttributes)` if this is a GPT partition
42+
/// - `None` if this is not a GPT partition
43+
pub fn as_gpt(&self) -> Option<&GptAttributes> {
44+
match self {
45+
PartitionAttributes::Gpt(attr) => Some(attr),
46+
}
47+
}
48+
}

crates/partitioning/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ pub mod blkpg;
66
pub mod loopback;
77
pub mod sparsefile;
88

9+
mod attributes;
10+
pub use attributes::*;
11+
912
pub use gpt;
1013

1114
pub mod planner;

crates/partitioning/src/planner.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use log::{debug, warn};
1717
use std::collections::VecDeque;
1818
use thiserror::Error;
1919

20+
use crate::PartitionAttributes;
21+
2022
/// Errors that can occur while planning partition changes
2123
///
2224
/// These errors help prevent invalid partition layouts by catching problems
@@ -39,7 +41,12 @@ pub enum PlanError {
3941
#[derive(Debug, Clone)]
4042
pub enum Change {
4143
/// Add a new partition
42-
AddPartition { start: u64, end: u64, partition_id: u32 },
44+
AddPartition {
45+
start: u64,
46+
end: u64,
47+
partition_id: u32,
48+
attributes: Option<PartitionAttributes>,
49+
},
4350
/// Delete an existing partition
4451
DeletePartition { original_index: usize, partition_id: u32 },
4552
}
@@ -203,6 +210,7 @@ impl Change {
203210
start,
204211
end,
205212
partition_id,
213+
..
206214
} => {
207215
format!(
208216
"Add new partition #{}: {} ({} at {})",
@@ -311,6 +319,7 @@ impl Planner {
311319
start,
312320
end,
313321
partition_id,
322+
..
314323
} = change
315324
{
316325
debug!("Adding partition {}..{} (ID: {})", start, end, partition_id);
@@ -326,6 +335,10 @@ impl Planner {
326335
layout
327336
}
328337

338+
pub fn plan_add_partition(&mut self, start: u64, end: u64) -> Result<(), PlanError> {
339+
self.plan_add_partition_with_attributes(start, end, None)
340+
}
341+
329342
/// Plan to add a new partition between two absolute positions on disk.
330343
///
331344
/// # Arguments
@@ -335,7 +348,12 @@ impl Planner {
335348
/// Both positions will be aligned to the nearest appropriate boundary (usually 1MB).
336349
/// The partition will occupy the range [start, end).
337350
///
338-
pub fn plan_add_partition(&mut self, start: u64, end: u64) -> Result<(), PlanError> {
351+
pub fn plan_add_partition_with_attributes(
352+
&mut self,
353+
start: u64,
354+
end: u64,
355+
attributes: Option<PartitionAttributes>,
356+
) -> Result<(), PlanError> {
339357
debug!("Planning to add partition {}..{}", start, end);
340358
debug!("Original size requested: {}", end - start);
341359

@@ -401,6 +419,7 @@ impl Planner {
401419
start: aligned_start,
402420
end: aligned_end,
403421
partition_id,
422+
attributes,
404423
});
405424
Ok(())
406425
}

crates/partitioning/src/strategy.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,18 @@
2020
//! // Request needed partitions
2121
//! strategy.add_request(PartitionRequest {
2222
//! size: SizeRequirement::Exact(512 * 1024 * 1024), // 512MB EFI partition
23+
//! attributes: None,
2324
//! });
2425
//! strategy.add_request(PartitionRequest {
2526
//! size: SizeRequirement::Remaining, // Rest for root
27+
//! attributes: None,
2628
//! });
2729
//! ```
2830
2931
use crate::planner::{PlanError, Planner};
3032

3133
use crate::planner::Region;
34+
use crate::PartitionAttributes;
3235

3336
/// Strategy for allocating partitions
3437
#[derive(Debug, Clone)]
@@ -61,6 +64,7 @@ pub enum SizeRequirement {
6164
#[derive(Debug, Clone)]
6265
pub struct PartitionRequest {
6366
pub size: SizeRequirement,
67+
pub attributes: Option<PartitionAttributes>,
6468
}
6569

6670
/// Handles planning partition layouts according to specific strategies
@@ -201,15 +205,15 @@ impl Strategy {
201205
// First pass: allocate exact size partitions
202206
for request in &self.requests {
203207
if let SizeRequirement::Exact(size) = request.size {
204-
planner.plan_add_partition(current, current + size)?;
208+
planner.plan_add_partition_with_attributes(current, current + size, request.attributes.clone())?;
205209
current += size;
206210
remaining -= size;
207211
}
208212
}
209213

210214
// Second pass: allocate flexible partitions
211215
let mut remaining_flexible = flexible_requests.len();
212-
for (_idx, min, max_opt) in &flexible_requests {
216+
for (idx, min, max_opt) in &flexible_requests {
213217
remaining_flexible -= 1;
214218

215219
// First verify we have enough space for minimum requirement
@@ -243,7 +247,11 @@ impl Strategy {
243247
}
244248
};
245249

246-
match planner.plan_add_partition(current, current + size) {
250+
match planner.plan_add_partition_with_attributes(
251+
current,
252+
current + size,
253+
self.requests.get(*idx).and_then(|r| r.attributes.clone()),
254+
) {
247255
Ok(_) => {
248256
current += size;
249257
remaining -= size;
@@ -284,6 +292,7 @@ mod tests {
284292
fn root_partition() -> PartitionRequest {
285293
PartitionRequest {
286294
size: SizeRequirement::AtLeast(ROOT_MIN),
295+
attributes: None,
287296
}
288297
}
289298

@@ -294,20 +303,23 @@ mod tests {
294303
min: ROOT_MIN,
295304
max: ROOT_MAX,
296305
},
306+
attributes: None,
297307
}
298308
}
299309

300310
/// Creates a standard EFI system partition request
301311
fn efi_partition() -> PartitionRequest {
302312
PartitionRequest {
303313
size: SizeRequirement::Exact(EFI_SIZE),
314+
attributes: None,
304315
}
305316
}
306317

307318
/// Creates a /boot partition request
308319
fn boot_partition() -> PartitionRequest {
309320
PartitionRequest {
310321
size: SizeRequirement::Exact(BOOT_SIZE),
322+
attributes: None,
311323
}
312324
}
313325

@@ -318,13 +330,15 @@ mod tests {
318330
min: SWAP_MIN,
319331
max: SWAP_MAX,
320332
},
333+
attributes: None,
321334
}
322335
}
323336

324337
/// Creates a home partition request that uses all remaining space
325338
fn home_partition() -> PartitionRequest {
326339
PartitionRequest {
327340
size: SizeRequirement::Remaining,
341+
attributes: None,
328342
}
329343
}
330344
fn create_test_disk() -> MockDisk {
@@ -395,6 +409,7 @@ mod tests {
395409
strategy.add_request(boot_partition());
396410
strategy.add_request(PartitionRequest {
397411
size: SizeRequirement::Remaining,
412+
attributes: None,
398413
});
399414

400415
eprintln!("\nMinimal Server Strategy:\n{}", strategy.describe());
@@ -414,6 +429,7 @@ mod tests {
414429
// Try to allocate more than available
415430
strategy.add_request(PartitionRequest {
416431
size: SizeRequirement::Exact(20 * GB),
432+
attributes: None,
417433
});
418434

419435
assert!(strategy.apply(&mut planner).is_err());
@@ -428,9 +444,11 @@ mod tests {
428444
// Request more than available in flexible partitions
429445
strategy.add_request(PartitionRequest {
430446
size: SizeRequirement::AtLeast(6 * GB),
447+
attributes: None,
431448
});
432449
strategy.add_request(PartitionRequest {
433450
size: SizeRequirement::AtLeast(6 * GB),
451+
attributes: None,
434452
});
435453

436454
// Should fail because total minimum (12GB) exceeds disk size (10GB)
@@ -448,18 +466,21 @@ mod tests {
448466
// Request sequence where first two would fit but third won't
449467
strategy.add_request(PartitionRequest {
450468
size: SizeRequirement::Range { min: GB, max: 2 * GB },
469+
attributes: None,
451470
});
452471
strategy.add_request(PartitionRequest {
453472
size: SizeRequirement::Range {
454473
min: 2 * GB,
455474
max: 4 * GB,
456475
},
476+
attributes: None,
457477
});
458478
strategy.add_request(PartitionRequest {
459479
size: SizeRequirement::Range {
460480
min: 25 * GB,
461481
max: 120 * GB,
462482
},
483+
attributes: None,
463484
});
464485

465486
// Should fail and undo partial changes

crates/partitioning/src/writer.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use disks::BlockDevice;
99
use gpt::{mbr, partition_types, GptConfig};
1010
use thiserror::Error;
1111

12-
use crate::planner::{Change, Planner};
12+
use crate::{
13+
planner::{Change, Planner},
14+
GptAttributes,
15+
};
1316

1417
/// Errors that can occur when writing changes to disk
1518
#[derive(Debug, Error)]
@@ -139,12 +142,19 @@ impl<'a> DiskWriter<'a> {
139142
start,
140143
end,
141144
partition_id,
145+
attributes,
142146
} => {
143147
let start_lba = *start / 512;
144148
let size_lba = (*end - *start) / 512;
145-
let part_type = partition_types::BASIC;
146-
147-
let id = gpt_table.add_partition_at("", *partition_id, start_lba, size_lba, part_type, 0)?;
149+
let (part_type, part_name) = match attributes.as_ref().and_then(|a| a.as_gpt()) {
150+
Some(GptAttributes { type_guid, name, .. }) => {
151+
(type_guid.clone(), name.clone().unwrap_or_default())
152+
}
153+
None => (partition_types::BASIC, "".to_string()),
154+
};
155+
156+
let id =
157+
gpt_table.add_partition_at(&part_name, *partition_id, start_lba, size_lba, part_type, 0)?;
148158
println!("Added partition {}: {:?}", partition_id, id);
149159
}
150160
}

0 commit comments

Comments
 (0)