/// Information about a all mounts in a process's mount namespace. /// /// This data is taken from the `/proc/[pid]/mountinfo` file. pubstruct MountInfos(pub Vec<MountInfo>);
implcrate::FromBufRead for MountInfos { fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> { let lines = r.lines(); letmut vec = Vec::new(); for line in lines {
vec.push(MountInfo::from_line(&line?)?);
}
Ok(MountInfos(vec))
}
}
impl IntoIterator for MountInfos { type IntoIter = std::vec::IntoIter<MountInfo>; type Item = MountInfo;
/// Information about a specific mount in a process's mount namespace. /// /// This data is taken from the `/proc/[pid]/mountinfo` file. /// /// For an example, see the /// [mountinfo.rs](https://github.com/eminence/procfs/tree/master/procfs/examples) example in the /// source repo. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct MountInfo { /// Mount ID. A unique ID for the mount (but may be reused after `unmount`) pub mnt_id: i32, /// Parent mount ID. The ID of the parent mount (or of self for the root of the mount /// namespace's mount tree). /// /// If the parent mount point lies outside the process's root directory, the ID shown here /// won't have a corresponding record in mountinfo whose mount ID matches this parent mount /// ID (because mount points that lie outside the process's root directory are not shown in /// mountinfo). As a special case of this point, the process's root mount point may have a /// parent mount (for the initramfs filesystem) that lies outside the process's root /// directory, and an entry for that mount point will not appear in mountinfo. pub pid: i32, /// The value of `st_dev` for files on this filesystem pub majmin: String, /// The pathname of the directory in the filesystem which forms the root of this mount. pub root: String, /// The pathname of the mount point relative to the process's root directory. pub mount_point: PathBuf, /// Per-mount options pub mount_options: HashMap<String, Option<String>>, /// Optional fields pub opt_fields: Vec<MountOptFields>, /// Filesystem type pub fs_type: String, /// Mount source pub mount_source: Option<String>, /// Per-superblock options. pub super_options: HashMap<String, Option<String>>,
}
/// Optional fields used in [MountInfo] #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubenum MountOptFields { /// This mount point is shared in peer group. Each peer group has a unique ID that is /// automatically generated by the kernel, and all mount points in the same peer group will /// show the same ID
Shared(u32), /// THis mount is a slave to the specified shared peer group.
Master(u32), /// This mount is a slave and receives propagation from the shared peer group
PropagateFrom(u32), /// This is an unbindable mount
Unbindable,
}
/// A single entry in [MountStats]. #[derive(Debug, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct MountStat { /// The name of the mounted device pub device: Option<String>, /// The mountpoint within the filesystem tree pub mount_point: PathBuf, /// The filesystem type pub fs: String, /// If the mount is NFS, this will contain various NFS statistics pub statistics: Option<MountNFSStatistics>,
}
/// Mount information from `/proc/<pid>/mountstats`. #[derive(Debug, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct MountStats(pub Vec<MountStat>);
implcrate::FromBufRead for MountStats { /// This should correspond to data in `/proc/<pid>/mountstats`. fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> { letmut v = Vec::new(); letmut lines = r.lines(); whilelet Some(Ok(line)) = lines.next() { if line.starts_with("device ") { // line will be of the format: // device proc mounted on /proc with fstype proc letmut s = line.split_whitespace();
let device = Some(expect!(s.nth(1)).to_owned()); let mount_point = PathBuf::from(expect!(s.nth(2))); let fs = expect!(s.nth(2)).to_owned(); let statistics = match s.next() {
Some(stats) if stats.starts_with("statvers=") => {
Some(MountNFSStatistics::from_lines(&mut lines, &stats[9..])?)
}
_ => None,
};
/// Only NFS mounts provide additional statistics in `MountStat` entries. // // Thank you to Chris Siebenmann for their helpful work in documenting these structures: // https://utcc.utoronto.ca/~cks/space/blog/linux/NFSMountstatsIndex #[derive(Debug, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct MountNFSStatistics { /// The version of the NFS statistics block. Either "1.0" or "1.1". pub version: String, /// The mount options. /// /// The meaning of these can be found in the manual pages for mount(5) and nfs(5) pub opts: Vec<String>, /// Duration the NFS mount has been in existence. pub age: Duration, // * fsc (?) // * impl_id (NFSv4): Option<HashMap<String, Some(String)>> /// NFS Capabilities. /// /// See `include/linux/nfs_fs_sb.h` /// /// Some known values: /// * caps: server capabilities. See [NFSServerCaps]. /// * wtmult: server disk block size /// * dtsize: readdir size /// * bsize: server block size pub caps: Vec<String>, // * nfsv4 (NFSv4): Option<HashMap<String, Some(String)>> pub sec: Vec<String>, pub events: NFSEventCounter, pub bytes: NFSByteCounter, // * RPC iostats version: // * xprt // * per-op statistics pub per_op_stats: NFSPerOpStats,
}
impl MountNFSStatistics { // Keep reading lines until we get to a blank line fn from_lines<B: BufRead>(r: &mut Lines<B>, statsver: &str) -> ProcResult<MountNFSStatistics> { letmut parsing_per_op = false;
Ok(MountNFSStatistics {
version: statsver.to_string(),
opts: expect!(opts, "Failed to find opts field in nfs stats"),
age: expect!(age, "Failed to find age field in nfs stats"),
caps: expect!(caps, "Failed to find caps field in nfs stats"),
sec: expect!(sec, "Failed to find sec field in nfs stats"),
events: expect!(events, "Failed to find events section in nfs stats"),
bytes: expect!(bytes, "Failed to find bytes section in nfs stats"),
per_op_stats: per_op,
})
}
/// Attempts to parse the caps= value from the [caps](struct.MountNFSStatistics.html#structfield.caps) field. pubfn server_caps(&self) -> ProcResult<Option<NFSServerCaps>> { for data in &self.caps { iflet Some(stripped) = data.strip_prefix("caps=0x") { let val = from_str!(u32, stripped, 16); return Ok(NFSServerCaps::from_bits(val));
}
}
Ok(None)
}
}
/// Represents NFS data from `/proc/<pid>/mountstats` under the section `events`. /// /// The underlying data structure in the kernel can be found under *fs/nfs/iostat.h* `nfs_iostat`. /// The fields are documented in the kernel source only under *include/linux/nfs_iostat.h* `enum /// nfs_stat_eventcounters`. #[derive(Debug, Copy, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct NFSEventCounter { pub inode_revalidate: u64, pub deny_try_revalidate: u64, pub data_invalidate: u64, pub attr_invalidate: u64, pub vfs_open: u64, pub vfs_lookup: u64, pub vfs_access: u64, pub vfs_update_page: u64, pub vfs_read_page: u64, pub vfs_read_pages: u64, pub vfs_write_page: u64, pub vfs_write_pages: u64, pub vfs_get_dents: u64, pub vfs_set_attr: u64, pub vfs_flush: u64, pub vfs_fs_sync: u64, pub vfs_lock: u64, pub vfs_release: u64, pub congestion_wait: u64, pub set_attr_trunc: u64, pub extend_write: u64, pub silly_rename: u64, pub short_read: u64, pub short_write: u64, pub delay: u64, pub pnfs_read: u64, pub pnfs_write: u64,
}
/// Represents NFS data from `/proc/<pid>/mountstats` under the section `bytes`. /// /// The underlying data structure in the kernel can be found under *fs/nfs/iostat.h* `nfs_iostat`. /// The fields are documented in the kernel source only under *include/linux/nfs_iostat.h* `enum /// nfs_stat_bytecounters` #[derive(Debug, Copy, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct NFSByteCounter { pub normal_read: u64, pub normal_write: u64, pub direct_read: u64, pub direct_write: u64, pub server_read: u64, pub server_write: u64, pub pages_read: u64, pub pages_write: u64,
}
/// Represents NFS data from `/proc/<pid>/mountstats` under the section of `per-op statistics`. /// /// Here is what the Kernel says about the attributes: /// /// Regarding `operations`, `transmissions` and `major_timeouts`: /// /// > These counters give an idea about how many request /// > transmissions are required, on average, to complete that /// > particular procedure. Some procedures may require more /// > than one transmission because the server is unresponsive, /// > the client is retransmitting too aggressively, or the /// > requests are large and the network is congested. /// /// Regarding `bytes_sent` and `bytes_recv`: /// /// > These count how many bytes are sent and received for a /// > given RPC procedure type. This indicates how much load a /// > particular procedure is putting on the network. These /// > counts include the RPC and ULP headers, and the request /// > payload. /// /// Regarding `cum_queue_time`, `cum_resp_time` and `cum_total_req_time`: /// /// > The length of time an RPC request waits in queue before /// > transmission, the network + server latency of the request, /// > and the total time the request spent from init to release /// > are measured. /// /// (source: *include/linux/sunrpc/metrics.h* `struct rpc_iostats`) #[derive(Debug, Clone)] #[cfg_attr(test, derive(PartialEq))] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct NFSOperationStat { /// Count of rpc operations. pub operations: u64, /// Count of rpc transmissions pub transmissions: u64, /// Count of rpc major timeouts pub major_timeouts: u64, /// Count of bytes send. Does not only include the RPC payload but the RPC headers as well. pub bytes_sent: u64, /// Count of bytes received as `bytes_sent`. pub bytes_recv: u64, /// How long all requests have spend in the queue before being send. pub cum_queue_time: Duration, /// How long it took to get a response back. pub cum_resp_time: Duration, /// How long all requests have taken from beeing queued to the point they where completely /// handled. pub cum_total_req_time: Duration,
}
let operations = from_str!(u64, expect!(s.next())); let transmissions = from_str!(u64, expect!(s.next())); let major_timeouts = from_str!(u64, expect!(s.next())); let bytes_sent = from_str!(u64, expect!(s.next())); let bytes_recv = from_str!(u64, expect!(s.next())); let cum_queue_time_ms = from_str!(u64, expect!(s.next())); let cum_resp_time_ms = from_str!(u64, expect!(s.next())); let cum_total_req_time_ms = from_str!(u64, expect!(s.next()));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.