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

src/* : use lsblk --json output format #631

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

sohankunkerkar
Copy link
Member

Fixes: #516

let devinfo = Device::lsblk(Path::new(devpath), false)?;
let fs = devinfo[0]
.fstype
.as_ref()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to drop the as_ref() and just consume the devinfo. But we need to change the Device::lsblk API first (see below).

src/blockdev.rs Outdated
.uuid
.as_ref()
.ok_or_else(|| anyhow::anyhow!("missing uuid in {}", devinfo[0].name))?;
Ok(uuid.to_string())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good example where consuming would be more efficient because we don't have to clone the string again.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still cloning.

src/blockdev.rs Outdated
}

impl Device {
pub fn lsblk(dev: &Path, with_deps: bool) -> Result<Vec<Device>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think here a really nice thing about switching to JSON is that we capture the hierarchy of the block devices. In this case, subdevices of the main device we're querying will be in children.

So here I think we want to output a Result<Device> instead. The lsblk output supports outputting multiple top-level devices, but in our uses of lsblk we're always really just interested in a single top-level device (and possibly its children if with_deps is enabled). So this function could sanity-check that only one device matched, and return that one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also rename with_deps to with_children, since that's the name in the structure we return.

Though hmm, kinda tempting to drop the with_deps argument altogether since we'd always return one device now unlike before. lsblk will be doing more work than it needs to in some cases, but meh... feels like it's worth the cleaner API we get. @bgilbert might have a different opinion.

src/blockdev.rs Outdated
let deviceinfos: Vec<Device> = Device::lsblk(Path::new(&self.path), true)?;
for deviceinfo in deviceinfos {
let mut partition = self.compute_partition(&deviceinfo, with_holders)?;
result.append(&mut partition);
if let Some(children) = deviceinfo.children.as_ref() {
if !children.is_empty() {
for child in children {
let mut childpartitions = self.compute_partition(child, with_holders)?;
result.append(&mut childpartitions)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, right OK you had to do some refactoring here to deal with children not being in the main iteration anymore.

Though I don't think this flow is functionally equivalent, because we're only going one level down. I think we want a recursive model here instead? So e.g. you have get_partitions call to get_partitions_recurse with the top-level Device, and then that function calls itself for each child in the device, aggregating partitions in the vector as it goes. Then we return that vector. Does that make sense?

This is almost an exact revert of coreos#308, which was necessary at the time
when RHCOS shipped with its rootfs inside a LUKS container. It no longer
does that, so let's simplify the code.
Comment on lines +77 to +84
let devinfo = devs
.blockdevices
.into_iter()
.next()
.ok_or_else(|| anyhow!("failed to get device information"))?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should verify that there is only one dev and return that dev. Otherwise error out.

src/blockdev.rs Outdated
.uuid
.as_ref()
.ok_or_else(|| anyhow::anyhow!("missing uuid in {}", devinfo[0].name))?;
Ok(uuid.to_string())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still cloning.

src/blockdev.rs Outdated
Comment on lines 190 to 185
let deviceinfo = Device::lsblk(Path::new(&self.path), true)?;
let mut partition = self.compute_partition(&deviceinfo, with_holders)?;
if !partition.is_empty() {
result.append(&mut partition);
}
let mut childpartitioninfo = self.get_partitions_recurse(&deviceinfo, with_holders)?;
if !childpartitioninfo.is_empty() {
result.append(&mut childpartitioninfo);
}
Ok(result)
}

fn get_partitions_recurse(
&self,
deviceinfo: &Device,
with_holders: bool,
) -> Result<Vec<Partition>> {
let mut result: Vec<Partition> = Vec::new();
if let Some(children) = deviceinfo.children.as_ref() {
if !children.is_empty() {
for child in children {
let mut childpartitions = self.compute_partition(child, with_holders)?;
result.append(&mut childpartitions);
self.get_partitions_recurse(child, with_holders)?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK digging more into this took me to #648. Let's do that first, and then this should essentially be just get_partitions() enumerating over the immediate children only for partitions (so no need for recursion).

Also, maybe as a follow-up we should investigate just returning Vec<Device> here instead of a separate Partition type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Switch from lsblk --pairs to lsblk --json
2 participants