Skip to main content

dio_align/linux/
old.rs

1use rustix::fs::{
2  AtFlags, Mode, OFlags, StatxFlags, ioctl_blkpbszget, ioctl_blksszget, open, statx,
3};
4use smol_str::format_smolstr;
5
6use std::{io, path::Path};
7
8use super::{
9  super::DirectInfo, ABS_BLOCK_PATH, BLOCK_PATH, PHYSICAL_BLOCK_SIZE_FILE_NAME, QUEUE_PATH,
10  read_block_size,
11};
12
13const LOGICAL_BLOCK_SIZE_FILE_NAME: &str = "logical_block_size";
14
15/// Fetch direct I/O alignment information for a path.
16pub fn fetch<P: AsRef<Path>>(path: P) -> io::Result<DirectInfo> {
17  let path = path.as_ref();
18  let fd = open(path.as_os_str(), OFlags::RDONLY, Mode::empty())?;
19  match ioctl_blksszget(&fd) {
20    Ok(logical_blk_size) => {
21      let physical_blk_size = ioctl_blkpbszget(&fd).unwrap_or(logical_blk_size);
22      Ok(DirectInfo::new(logical_blk_size, physical_blk_size))
23    }
24    Err(_) => {
25      let abs = path.canonicalize()?;
26      let parent_dir = abs.parent().ok_or_else(|| {
27        io::Error::new(
28          io::ErrorKind::InvalidInput,
29          format!("path '{}' has no parent directory", abs.display()),
30        )
31      })?;
32
33      let parent_fd = open(parent_dir, OFlags::RDONLY, Mode::empty())?;
34
35      let file_name = abs.file_name().ok_or_else(|| {
36        io::Error::new(
37          io::ErrorKind::InvalidInput,
38          format!("path '{}' has no file name", abs.display()),
39        )
40      })?;
41
42      let stx = statx(
43        parent_fd,
44        file_name,
45        AtFlags::empty(),
46        StatxFlags::BASIC_STATS,
47      )?;
48      let major = stx.stx_dev_major;
49      let minor = stx.stx_dev_minor;
50
51      let mut current = {
52        let path = format_smolstr!("{ABS_BLOCK_PATH}/{major}:{minor}");
53        let path: &str = path.as_ref();
54        let path: &Path = path.as_ref();
55        path.canonicalize()?
56      };
57
58      loop {
59        let queue = current.join(QUEUE_PATH);
60        let logical_blk_path = queue.join(LOGICAL_BLOCK_SIZE_FILE_NAME);
61        if logical_blk_path.exists() {
62          let logical_blk_size = read_block_size(&logical_blk_path)?;
63
64          let physical_blk_path = queue.join(PHYSICAL_BLOCK_SIZE_FILE_NAME);
65          let physical_blk_size = read_block_size(&physical_blk_path).unwrap_or(logical_blk_size);
66          return Ok(DirectInfo::new(logical_blk_size, physical_blk_size));
67        }
68
69        match current.parent() {
70          Some(p) if p.file_name().is_some_and(|n| n.ne(BLOCK_PATH)) => current = p.to_path_buf(),
71          _ => {
72            return Err(io::Error::new(
73              io::ErrorKind::InvalidInput,
74              "cannot find the logical and physical block size information",
75            ));
76          }
77        }
78      }
79    }
80  }
81}