Skip to content

Commit

Permalink
Handle mount with FS with 1 device
Browse files Browse the repository at this point in the history
If the user passes a single device node during the mount and
we have no information for it in the udev db, we read up the
super block.  When we do this, if the FS only has 1 block device
we will simply go ahead and do the mount instead of walking
all the block devices and reading up super blocks looking for
devices with a matching FS UUID.

Signed-off-by: Tony Asleson <[email protected]>
  • Loading branch information
tasleson committed May 2, 2024
1 parent 0aa1c77 commit c4f3afa
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
4 changes: 4 additions & 0 deletions bch_bindgen/src/bcachefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
37 changes: 27 additions & 10 deletions src/commands/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,22 @@ fn get_devices_by_uuid(
fn get_uuid_for_dev_node(
udev_bcachefs: &HashMap<String, Vec<String>>,
device: &std::path::PathBuf,
) -> anyhow::Result<Option<Uuid>> {
) -> anyhow::Result<(Option<Uuid>, Option<(PathBuf, bch_sb_handle)>)> {
let canonical = fs::canonicalize(device)?;

if !udev_bcachefs.is_empty() {
let dev_node_str = canonical.into_os_string().into_string().unwrap();

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.
Expand Down Expand Up @@ -289,12 +291,27 @@ fn devs_str_sbs_from_device(
udev_info: &HashMap<String, Vec<String>>,
device: &std::path::PathBuf,
) -> anyhow::Result<(String, Vec<bch_sb_handle>)> {
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()))
}
}
}

Expand Down

0 comments on commit c4f3afa

Please sign in to comment.