Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for devices with a non-512-byte sector size #181

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions crates/disk-ops/src/mklabel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use std::path::Path;

/// Writes a new partition table to the disk, clobbering it in the process.
pub fn mklabel<P: AsRef<Path>>(device_path: P, kind: PartitionTable) -> io::Result<()> {
let _ = zero(&device_path, 2047, 1);
let _ = wipefs(&device_path);

info!(
Expand Down Expand Up @@ -41,16 +40,3 @@ pub fn mklabel<P: AsRef<Path>>(device_path: P, kind: PartitionTable) -> io::Resu

Ok(())
}

/// Write sectors of zeroes to a block device
pub fn zero<P: AsRef<Path>>(device: P, sectors: u64, offset: u64) -> io::Result<()> {
let zeroed_sector = [0; 512];
File::open(device.as_ref())
.and_then(|mut file| {
if offset != 0 {
file.seek(SeekFrom::Start(512 * offset)).map(|_| ())?;
}

(0..sectors).map(|_| file.write(&zeroed_sector).map(|_| ())).collect()
})
}
10 changes: 6 additions & 4 deletions crates/disk-ops/src/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ pub struct PartitionChange {
pub start: u64,
/// The end sector that the partition will have.
pub end: u64,
/// Size of this partition's sectors.
pub sector_size: u64,
/// The file system that is currently on the partition.
pub filesystem: Option<FileSystem>,
/// A diff of flags which should be set on the partition.
Expand Down Expand Up @@ -301,8 +303,8 @@ where
// Each file system uses different units for specifying the size, and these
// units are sometimes written in non-standard and conflicting ways.
let size = match unit {
ResizeUnit::AbsoluteBytes => format!("{}", resize.absolute_sectors() * 512),
ResizeUnit::AbsoluteKibis => format!("{}ki", resize.absolute_sectors() / 2),
ResizeUnit::AbsoluteBytes => format!("{}", resize.absolute_sectors() * change.sector_size),
ResizeUnit::AbsoluteKibis => format!("{}ki", (resize.absolute_sectors() / 2) * (change.sector_size / 512)),
ResizeUnit::AbsoluteSectorsWithUnit => format!("{}s", resize.absolute_sectors()),
ResizeUnit::AbsoluteMebibyte => format!("{}M", resize.as_absolute_mebibyte()),
ResizeUnit::AbsoluteMegabyte => format!("{}M", resize.as_absolute_megabyte()),
Expand Down Expand Up @@ -345,7 +347,7 @@ where
let abs_sectors = resize.absolute_sectors();
resize.old.resize_to(abs_sectors); // TODO: NLL

move_partition(&change.device_path, resize.offset(), 512)
move_partition(&change.device_path, resize.offset(), change.sector_size)
.map_err(|why| io::Error::new(
why.kind(),
format!("failed to move partition at {}: {}", change.path.display(), why)
Expand Down Expand Up @@ -383,7 +385,7 @@ where
let abs_sectors = resize.absolute_sectors();
resize.old.resize_to(abs_sectors); // TODO: NLL

move_partition(&change.device_path, resize.offset(), 512)
move_partition(&change.device_path, resize.offset(), change.sector_size)
.map_err(|why| io::Error::new(
why.kind(),
format!("failed to move partition at {}: {}", change.path.display(), why)
Expand Down
16 changes: 11 additions & 5 deletions crates/disks/src/config/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ pub struct Disk {
pub mount_point: Option<PathBuf>,
/// The size of the disk in sectors.
pub size: u64,
/// The size of each sector
pub sector_size: u64,
/// The type of the device, such as SCSI.
pub device_type: String,
/// The partition table may be either **MSDOS** or **GPT**.
Expand All @@ -119,7 +121,7 @@ impl BlockDeviceExt for Disk {
}

impl SectorExt for Disk {
fn get_sector_size(&self) -> u64 { 512 }
fn get_sector_size(&self) -> u64 { self.sector_size }

fn get_sectors(&self) -> u64 { self.size }
}
Expand Down Expand Up @@ -173,6 +175,7 @@ impl Disk {
};

let size = device.length();
let sector_size = device.sector_size();
let device_type = format!("{:?}", device.type_());
let read_only = device.read_only();

Expand All @@ -197,6 +200,7 @@ impl Disk {
file_system: None,
serial,
size,
sector_size,
device_type,
read_only,
table_type,
Expand Down Expand Up @@ -436,6 +440,7 @@ impl Disk {
/// will be located at the provided `end` value, and checks whether or not that this will
/// be possible to do.
pub fn resize_partition(&mut self, partition: i32, mut end: u64) -> Result<u64, DiskError> {
let sector_size = self.get_sector_size();
let (backup, num, start);
{
let partition = self.get_partition_mut(partition)
Expand All @@ -450,7 +455,7 @@ impl Disk {

{
let length = end - partition.start_sector;
end -= length % (2 * 1024);
end -= length % (crate::sectors_normalize(2 * 1024, sector_size));
}

info!(
Expand All @@ -459,10 +464,10 @@ impl Disk {
end - partition.start_sector
);

assert_eq!(0, (end - partition.start_sector) % (2 * 1024));
assert_eq!(0, (end - partition.start_sector) % (crate::sectors_normalize(2 * 1024, sector_size)));

if end < partition.start_sector
|| end - partition.start_sector <= (10 * 1024 * 1024) / 512
|| end - partition.start_sector <= crate::sectors_normalize(10 * 1024 * 1024, sector_size) / sector_size
{
return Err(DiskError::new_partition_error(
partition.device_path.clone(),
Expand Down Expand Up @@ -540,7 +545,7 @@ impl Disk {
self.path().display(),
fs,
);
let sector_size = 512;
let sector_size = self.get_sector_size();
self.get_partition_mut(partition)
.ok_or(DiskError::PartitionNotFound { partition })
.and_then(|partition| {
Expand Down Expand Up @@ -750,6 +755,7 @@ impl Disk {
kind: new.part_type,
start: new.start_sector,
end: new.end_sector,
sector_size: self.get_sector_size(),
filesystem: source.filesystem,
flags: flags_diff(
&source.flags,
Expand Down
4 changes: 3 additions & 1 deletion crates/disks/src/config/disk_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ pub trait DiskExt: BlockDeviceExt + SectorExt + PartitionTableExt {
///
/// An error can occur if the partition will not fit onto the disk.
fn add_partition(&mut self, mut builder: PartitionBuilder) -> Result<(), DiskError> {
let sector_size = self.get_sector_size();

// Ensure that the values aren't already contained within an existing partition.
if !Self::LOGICAL && builder.part_type != PartitionType::Extended {
info!(
Expand Down Expand Up @@ -136,7 +138,7 @@ pub trait DiskExt: BlockDeviceExt + SectorExt + PartitionTableExt {
).partition_type(PartitionType::Extended);

self.push_partition(part.build());
builder.start_sector += 1_024_000 / 512 + 1;
builder.start_sector += 1_024_000 / sector_size + 1;
}

let fs = builder.filesystem;
Expand Down
17 changes: 11 additions & 6 deletions crates/disks/src/config/disks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ impl Disks {
partition: &mut PartitionInfo,
path: &Path,
enc: &LvmEncryption,
sector_size: u64,
) -> Result<LogicalDevice, DecryptionError> {
// Attempt to decrypt the device.
cryptsetup_open(path, &enc).map_err(|why| DecryptionError::Open {
Expand All @@ -480,7 +481,7 @@ impl Disks {
Some(Some(vg)) => {
// Set values in the device's partition.
partition.volume_group = Some((vg.clone(), Some(enc.clone())));
let mut luks = LogicalDevice::new(vg, Some(enc.clone()), partition.get_sectors(), 512, true);
let mut luks = LogicalDevice::new(vg, Some(enc.clone()), partition.get_sectors(), sector_size, true);
info!("settings luks_parent to {:?}", path);
luks.set_luks_parent(path.to_path_buf());

Expand All @@ -494,7 +495,7 @@ impl Disks {
pv,
Some(enc.clone()),
partition.get_sectors(),
512,
sector_size,
true
);

Expand All @@ -516,16 +517,18 @@ impl Disks {

// Attempt to find the device in the configuration.
for device in &mut self.physical {
let sector_size = device.get_sector_size();

// TODO: NLL
if let Some(partition) = device.get_file_system_mut() {
if partition.get_device_path() == path {
decrypt(partition, path, &enc)?;
decrypt(partition, path, &enc, sector_size)?;
}
}

for partition in device.file_system.as_mut().into_iter().chain(device.partitions.iter_mut()) {
if partition.get_device_path() == path {
new_device = Some(decrypt(partition, path, &enc)?);
new_device = Some(decrypt(partition, path, &enc, sector_size)?);
break
}
}
Expand Down Expand Up @@ -955,6 +958,8 @@ impl Disks {
}
};

let sector_size = device.get_sector_size();

if is_efi {
// Check if the EFI partition is on a GPT disk.
if device.get_partition_table() != Some(PartitionTable::Gpt) {
Expand Down Expand Up @@ -988,9 +993,9 @@ impl Disks {
}

// 256 MiB should be the minimal size of the ESP partition.
const REQUIRED_SECTORS: u64 = 524_288;
let required_sectors = crate::sectors_normalize(524_288, sector_size);

if boot.get_sectors() < REQUIRED_SECTORS {
if boot.get_sectors() < required_sectors {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"the ESP partition must be at least 256 MiB in size"
Expand Down
5 changes: 5 additions & 0 deletions crates/disks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ pub use bootloader::{Bootloader, FORCE_BOOTLOADER};
pub use self::config::*;
pub use self::error::{DecryptionError, DiskError, PartitionError, PartitionSizeError};
pub use libparted::PartitionFlag;

/// Normalize 512-byte sector counts to the given sector size
fn sectors_normalize(base_count: u64, sector_size: u64) -> u64 {
base_count / (sector_size / 512)
}
5 changes: 5 additions & 0 deletions ffi/distinst.vapi
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ namespace Distinst {
public int get_partition ();
public uint64 get_sectors_free ();
public uint64 get_sectors_total ();
public uint64 get_sector_size ();
}

/**
Expand Down Expand Up @@ -182,6 +183,10 @@ namespace Distinst {
* Gets the number of sectors that this option's device contains.
*/
public uint64 get_sectors ();
/**
* Gets the size of sectors on this device
*/
public uint64 get_sector_size ();
}

/**
Expand Down
26 changes: 24 additions & 2 deletions ffi/src/auto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub unsafe extern "C" fn distinst_alongside_option_get_sectors_free(
let option = &*(option as *const AlongsideOption);
match option.method {
AlongsideMethod::Shrink { sectors_free, .. } => sectors_free,
AlongsideMethod::Free(ref region) => region.size()
AlongsideMethod::Free(ref region, _) => region.size()
}
}

Expand All @@ -131,10 +131,20 @@ pub unsafe extern "C" fn distinst_alongside_option_get_sectors_total(
let option = &*(option as *const AlongsideOption);
match option.method {
AlongsideMethod::Shrink { sectors_total, .. } => sectors_total,
AlongsideMethod::Free(ref region) => region.size()
AlongsideMethod::Free(ref region, _) => region.size()
}
}

#[no_mangle]
pub unsafe extern "C" fn distinst_alongside_option_get_sector_size(
option: *const DistinstAlongsideOption,
) -> libc::uint64_t {
let option = &*(option as *const AlongsideOption);
match option.method {
AlongsideMethod::Shrink { sector_size, .. } => sector_size,
AlongsideMethod::Free(_, size) => size
}
}

#[repr(C)]
pub struct DistinstRefreshOption;
Expand Down Expand Up @@ -284,6 +294,18 @@ pub unsafe extern "C" fn distinst_erase_option_get_sectors(
option.sectors
}

#[no_mangle]
pub unsafe extern "C" fn distinst_erase_option_get_sector_size(
option: *const DistinstEraseOption,
) -> libc::uint64_t {
if null_check(option).is_err() {
return 0;
}

let option = &*(option as *const EraseOption);
option.sector_size
}

#[no_mangle]
pub unsafe extern "C" fn distinst_erase_option_is_rotational(
option: *const DistinstEraseOption,
Expand Down
13 changes: 7 additions & 6 deletions src/auto/options/alongside_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ pub enum AlongsideMethod {
partition: i32,
sectors_total: u64,
sectors_free: u64,
sector_size: u64,
path: PathBuf,
},
Free(Region)
Free(Region, u64)
}

#[derive(Debug)]
Expand All @@ -37,24 +38,24 @@ impl fmt::Display for AlongsideOption {
let device = self.device.display();

match self.method {
AlongsideMethod::Shrink { sectors_total, sectors_free, ref path, .. } => {
AlongsideMethod::Shrink { sectors_total, sectors_free, sector_size, ref path, .. } => {
write!(
f,
"alongside {:?} ({}) by shrinking {}: {} of {} MiB free",
os,
device,
path.display(),
sectors_free / 2048,
sectors_total / 2048
sectors_free / 2048 * (sector_size / 512),
sectors_total / 2048 * (sector_size / 512)
)
},
AlongsideMethod::Free(ref region) => {
AlongsideMethod::Free(ref region, ref sector_size) => {
write!(
f,
"alongside {:?} ({}) using free space: {} MiB free",
os,
device,
region.size() / 2048,
region.size() / 2048 * (*sector_size / 512),
)
}
}
Expand Down
Loading