diff --git a/bch_bindgen/src/bcachefs.rs b/bch_bindgen/src/bcachefs.rs index 837b0272b..7b8a03df7 100644 --- a/bch_bindgen/src/bcachefs.rs +++ b/bch_bindgen/src/bcachefs.rs @@ -59,6 +59,10 @@ impl bch_sb { uuid::Uuid::from_bytes(self.user_uuid.b) } + pub fn number_of_devices(&self) -> u8 { + self.nr_devices + } + /// Get the nonce used to encrypt the superblock pub fn nonce(&self) -> nonce { use byteorder::{LittleEndian, ReadBytesExt}; diff --git a/src/commands/mount.rs b/src/commands/mount.rs index 03215fcda..5eb9aa58f 100644 --- a/src/commands/mount.rs +++ b/src/commands/mount.rs @@ -208,7 +208,7 @@ fn get_devices_by_uuid( fn get_uuid_for_dev_node( udev_bcachefs: &HashMap>, device: &std::path::PathBuf, -) -> anyhow::Result> { +) -> anyhow::Result<(Option, Option<(PathBuf, bch_sb_handle)>)> { let canonical = fs::canonicalize(device)?; if !udev_bcachefs.is_empty() { @@ -216,12 +216,14 @@ fn get_uuid_for_dev_node( if udev_bcachefs.contains_key(&dev_node_str) && udev_bcachefs[&dev_node_str].len() == 1 { let uuid_str = udev_bcachefs[&dev_node_str][0].clone(); - return Ok(Some(Uuid::parse_str(&uuid_str)?)); + return Ok((Some(Uuid::parse_str(&uuid_str)?), None)); } } else { - return read_super_silent(&canonical).map_or(Ok(None), |sb| Ok(Some(sb.sb().uuid()))); + return read_super_silent(&canonical).map_or(Ok((None, None)), |sb| { + Ok((Some(sb.sb().uuid()), Some((canonical, sb)))) + }); } - Ok(None) + Ok((None, None)) } /// Mount a bcachefs filesystem by its UUID. @@ -289,12 +291,27 @@ fn devs_str_sbs_from_device( udev_info: &HashMap>, device: &std::path::PathBuf, ) -> anyhow::Result<(String, Vec)> { - let uuid = get_uuid_for_dev_node(udev_info, device)?; - - if let Some(bcache_fs_uuid) = uuid { - devs_str_sbs_from_uuid(udev_info, bcache_fs_uuid.to_string()) - } else { - Ok((String::new(), Vec::new())) + let (uuid, sb_info) = get_uuid_for_dev_node(udev_info, device)?; + + match (uuid, sb_info) { + (Some(uuid), Some((path, sb))) => { + // If we have a super block, it implies we aren't using udev db. If we only need + // 1 device to mount, we'll simply return it as we're done, else we'll use the uuid + // to walk through all the block devices. + debug!("number of devices in this FS = {}", sb.sb().number_of_devices()); + if sb.sb().number_of_devices() == 1 { + let dev = path.into_os_string().into_string().unwrap(); + Ok((dev, vec!(sb))) + } else { + devs_str_sbs_from_uuid(udev_info, uuid.to_string()) + } + } + (Some(uuid), None) => { + devs_str_sbs_from_uuid(udev_info, uuid.to_string()) + } + _ => { + Ok((String::new(), Vec::new())) + } } }