1use std::fs::{read_to_string, read_dir, DirEntry};
117use regex::Regex;
118use crate::ProcSysParserError;
119
120#[derive(Debug, PartialEq, Default)]
122pub struct SysBlock {
123 pub block_devices: Vec<BlockDevice>
124}
125
126#[derive(Default)]
128pub struct Builder {
129 pub sys_path : String,
130 pub filter : String,
131}
132
133impl Builder {
134 pub fn new() -> Builder {
135 Builder {
136 sys_path: "/sys".to_string(),
137 filter: "^dm-".to_string(),
138 }
139 }
140 pub fn path(mut self, sys_path: &str) -> Builder {
141 self.sys_path = sys_path.to_string();
142 self
143 }
144 pub fn regex(mut self, filter: &str) -> Builder {
145 self.filter = filter.to_string();
146 self
147 }
148 pub fn read(self) -> Result<SysBlock, ProcSysParserError> {
149 SysBlock::read_sys_block_devices(format!("{}/block", self.sys_path).as_str(), self.filter.as_str())
150 }
151}
152
153pub fn read() -> Result<SysBlock, ProcSysParserError> {
156 Builder::new().read()
157}
158
159#[derive(Debug, PartialEq, Default)]
161pub struct BlockDevice {
162 pub device_name: String,
164 pub alignment_offset: u64,
168 pub cache_type: Option<String>,
178 pub dev_block_major: u64,
180 pub dev_block_minor: u64,
182 pub discard_alignment: u64,
188 pub diskseq: Option<u64>,
192 pub hidden: u64,
196 pub inflight_reads: u64,
201 pub inflight_writes: u64,
206 pub queue_add_random: u64,
209 pub queue_chunk_sectors: Option<u64>,
214 pub queue_dax: u64,
218 pub queue_discard_granularity: u64,
222 pub queue_discard_max_bytes: u64,
227 pub queue_discard_max_hw_bytes: u64,
232 pub queue_hw_sector_size: u64,
235 pub queue_io_poll: u64,
238 pub queue_io_poll_delay: i64,
246 pub queue_logical_block_size: u64,
249 pub queue_max_discard_segments: u64,
252 pub queue_max_hw_sectors_kb: u64,
256 pub queue_max_sectors_kb: u64,
260 pub queue_max_integrity_segments: u64,
264 pub queue_max_segments: u64,
266 pub queue_max_segment_size: u64,
268 pub queue_minimum_io_size: u64,
271 pub queue_nomerges: u64,
278 pub queue_nr_requests: u64,
282 pub queue_nr_zones: Option<u64>,
286 pub queue_optimal_io_size: u64,
289 pub queue_physical_block_size: u64,
292 pub queue_read_ahead_kb: u64,
295 pub queue_rotational: u64,
298 pub queue_rq_affinity: u64,
304 pub queue_scheduler: String,
308 pub queue_write_cache: String,
313 pub queue_write_same_max_bytes: u64,
317 pub queue_zoned: Option<String>,
325 pub range: u64,
328 pub removable: u64,
331 pub ro: u64,
334 pub size: u64,
338 pub stat_reads_completed_success: u64,
341 pub stat_reads_merged: u64,
343 pub stat_reads_sectors: u64,
345 pub stat_reads_time_spent_ms: u64,
348 pub stat_writes_completed_success: u64,
351 pub stat_writes_merged: u64,
353 pub stat_writes_sectors: u64,
355 pub stat_writes_time_spent_ms: u64,
358 pub stat_ios_in_progress: u64,
361 pub stat_ios_time_spent_ms: u64,
363 pub stat_ios_weighted_time_spent_ms: u64,
366 pub stat_discards_completed_success: Option<u64>,
370 pub stat_discards_merged: Option<u64>,
373 pub stat_discards_sectors: Option<u64>,
376 pub stat_discards_time_spent_ms: Option<u64>,
380 pub stat_flush_requests_completed_success: Option<u64>,
385 pub stat_flush_requests_time_spent_ms: Option<u64>,
389}
390
391impl BlockDevice {
392 pub fn new() -> BlockDevice {
393 BlockDevice::default()
394 }
395}
396
397impl SysBlock {
398 pub fn new() -> SysBlock {
399 SysBlock::default()
400 }
401 fn parse_dev(
402 blockdevice_data: &mut BlockDevice,
403 blockdevice_dir: &DirEntry,
404 ) -> Result<(), ProcSysParserError> {
405 let dev_contents = read_to_string(blockdevice_dir.path().join("dev"))
407 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join("dev").to_string_lossy().to_string(), error})?
408 .trim_end_matches('\n').to_string();
409 let mut fields = dev_contents.split(':');
410 blockdevice_data.dev_block_major = fields.next().ok_or(ProcSysParserError::IteratorItemError { item: "block parse_dev major".to_string() })?
411 .parse::<u64>().map_err(ProcSysParserError::ParseToIntegerError)?;
412 blockdevice_data.dev_block_minor = fields.next().ok_or(ProcSysParserError::IteratorItemError { item: "block parse_dev minor".to_string() })?
413 .parse::<u64>().map_err(ProcSysParserError::ParseToIntegerError)?;
414 Ok(())
415 }
416 fn parse_inflight(
417 blockdevice_data: &mut BlockDevice,
418 blockdevice_dir: &DirEntry,
419 ) -> Result<(), ProcSysParserError> {
420 let inflight_from_file = read_to_string(blockdevice_dir.path().join("inflight"))
421 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join("inflight").to_string_lossy().to_string(), error})?
422 .trim_end_matches('\n').to_string();
423 blockdevice_data.inflight_reads = inflight_from_file.split_whitespace()
424 .nth(0)
425 .ok_or(ProcSysParserError::IteratorItemError { item: "block parse_inflight reads".to_string() })?
426 .parse::<u64>()
427 .map_err(ProcSysParserError::ParseToIntegerError)?;
428 blockdevice_data.inflight_writes = inflight_from_file.split_whitespace()
429 .nth(1)
430 .ok_or(ProcSysParserError::IteratorItemError { item: "block parse_inflight writes".to_string() })?
431 .parse::<u64>()
432 .map_err(ProcSysParserError::ParseToIntegerError)?;
433 Ok(())
434 }
435 fn parse_queue_scheduler(
436 blockdevice_data: &mut BlockDevice,
437 blockdevice_dir: &DirEntry,
438 ) -> Result<(), ProcSysParserError> {
439 let nr_requests = read_to_string(blockdevice_dir.path().join("queue").join("scheduler"))
440 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join("queue").join("scheduler").to_string_lossy().to_string(), error })?
441 .trim_end_matches('\n').to_string();
442 let left_bracket = nr_requests.find('[');
443 let right_bracket = nr_requests.find(']');
444
445 if left_bracket.is_some() && right_bracket.is_some() {
446 blockdevice_data.queue_scheduler = nr_requests[left_bracket.ok_or(ProcSysParserError::FindItemError { item: "block parse_queue_scheduler '['".to_string() })?+1..right_bracket.ok_or(ProcSysParserError::FindItemError { item: "block parse_queue_scheduler ']'".to_string() })?].to_string();
447 } else {
448 blockdevice_data.queue_scheduler = "?".to_string();
449 }
450 Ok(())
451 }
452 fn parse_stat(
453 blockdevice_data: &mut BlockDevice,
454 blockdevice_dir: &DirEntry,
455 ) -> Result<(), ProcSysParserError> {
456 let parse_next_and_conversion_into_option_u64 = |result: Option<&str>| -> Option<u64> {
457 match result {
458 None => None,
459 Some(value) => {
460 match value.parse::<u64>() {
461 Err(_) => None,
462 Ok(number) => Some(number),
463 }
464 },
465 }
466 };
467
468 let stat_contents = read_to_string(blockdevice_dir.path().join("stat"))
469 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join("stat").to_string_lossy().to_string(), error })?
470 .trim_end_matches('\n')
471 .to_string();
472 let mut stat_contents_splitted = stat_contents
473 .split_whitespace();
474
475 blockdevice_data.stat_reads_completed_success = stat_contents_splitted.next()
476 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat reads_completed_success".to_string() })?
477 .parse::<u64>()
478 .map_err(ProcSysParserError::ParseToIntegerError)?;
479 blockdevice_data.stat_reads_merged = stat_contents_splitted.next()
480 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat reads_merged".to_string() })?
481 .parse::<u64>()
482 .map_err(ProcSysParserError::ParseToIntegerError)?;
483 blockdevice_data.stat_reads_sectors = stat_contents_splitted.next()
484 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat reads_sectors".to_string() })?
485 .parse::<u64>()
486 .map_err(ProcSysParserError::ParseToIntegerError)?;
487 blockdevice_data.stat_reads_time_spent_ms = stat_contents_splitted.next()
488 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat reads_time_spent_ms".to_string() })?
489 .parse::<u64>()
490 .map_err(ProcSysParserError::ParseToIntegerError)?;
491 blockdevice_data.stat_writes_completed_success = stat_contents_splitted.next()
492 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat writes_completed_success".to_string() })?
493 .parse::<u64>()
494 .map_err(ProcSysParserError::ParseToIntegerError)?;
495 blockdevice_data.stat_writes_merged = stat_contents_splitted.next()
496 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat writes_completed_success".to_string() })?
497 .parse::<u64>()
498 .map_err(ProcSysParserError::ParseToIntegerError)?;
499 blockdevice_data.stat_writes_sectors = stat_contents_splitted.next()
500 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat writes_sectors".to_string() })?
501 .parse::<u64>()
502 .map_err(ProcSysParserError::ParseToIntegerError)?;
503 blockdevice_data.stat_writes_time_spent_ms = stat_contents_splitted.next()
504 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat writes_time_spent_ms".to_string() })?
505 .parse::<u64>()
506 .map_err(ProcSysParserError::ParseToIntegerError)?;
507 blockdevice_data.stat_ios_in_progress = stat_contents_splitted.next()
508 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat ios_in_progress".to_string() })?
509 .parse::<u64>()
510 .map_err(ProcSysParserError::ParseToIntegerError)?;
511 blockdevice_data.stat_ios_time_spent_ms = stat_contents_splitted.next()
512 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat ios_time_spent_ms".to_string() })?
513 .parse::<u64>()
514 .map_err(ProcSysParserError::ParseToIntegerError)?;
515 blockdevice_data.stat_ios_weighted_time_spent_ms = stat_contents_splitted.next()
516 .ok_or(ProcSysParserError::FindItemError { item: "block parse_stat ios_weighted_time_spent_ms".to_string() })?
517 .parse::<u64>()
518 .map_err(ProcSysParserError::ParseToIntegerError)?;
519 blockdevice_data.stat_discards_completed_success = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
520 blockdevice_data.stat_discards_merged = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
521 blockdevice_data.stat_discards_sectors = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
522 blockdevice_data.stat_discards_time_spent_ms = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
523 blockdevice_data.stat_flush_requests_completed_success = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
524 blockdevice_data.stat_flush_requests_time_spent_ms = parse_next_and_conversion_into_option_u64(stat_contents_splitted.next());
525 Ok(())
526 }
527 fn parse_contents_file_u64(
528 file: &str,
529 blockdevice_dir: &DirEntry,
530 ) -> Result<u64, ProcSysParserError> {
531 read_to_string(blockdevice_dir.path().join(file))
532 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join(file).to_string_lossy().to_string(), error })?
533 .trim_end_matches('\n')
534 .to_string()
535 .parse::<u64>()
536 .map_err(ProcSysParserError::ParseToIntegerError)
537 }
538 fn parse_contents_file_i64(
539 file: &str,
540 blockdevice_dir: &DirEntry,
541 ) -> Result<i64, ProcSysParserError> {
542 read_to_string(blockdevice_dir.path().join(file))
543 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join(file).to_string_lossy().to_string(), error })?
544 .trim_end_matches('\n')
545 .to_string()
546 .parse::<i64>()
547 .map_err(ProcSysParserError::ParseToIntegerError)
548 }
549 fn parse_contents_file_option_u64(
550 file: &str,
551 blockdevice_dir: &DirEntry,
552 ) -> Result<Option<u64>, ProcSysParserError>
553 {
554 match read_to_string(blockdevice_dir.path().join(file)) {
555 Ok(result) => {
556 Ok(
557 Some(result
558 .trim_end_matches('\n')
559 .to_string()
560 .parse::<u64>()
561 .map_err(ProcSysParserError::ParseToIntegerError)?)
562 )
563 },
564 Err(_) => Ok(None),
565 }
566 }
567 fn parse_contents_file_option_string(
568 file: &str,
569 blockdevice_dir: &DirEntry,
570 ) -> Result<Option<String>, ProcSysParserError> {
571 Ok(match read_to_string(blockdevice_dir.path().join(file)) {
572 Ok(result) => Some(result.trim_end_matches('\n').to_string()),
573 Err(_) => None
574 })
575 }
576 fn parse_contents_file_string(
577 file: &str,
578 blockdevice_dir: &DirEntry,
579 ) -> Result <String, ProcSysParserError> {
580 Ok(read_to_string(blockdevice_dir.path().join(file))
581 .map_err(|error| ProcSysParserError::FileReadError { file: blockdevice_dir.path().join(file).to_string_lossy().to_string(), error })?
582 .trim_end_matches('\n')
583 .to_string())
584 }
585 pub fn read_sys_block_devices(
586 sys_block_path: &str,
587 filter: &str,
588 ) -> Result<SysBlock, ProcSysParserError> {
589 let mut sysblock = SysBlock::new();
590
591 let blockdevice_directories = read_dir(sys_block_path)
592 .map_err(|error| ProcSysParserError::DirectoryReadError { directory: sys_block_path.to_string(), error })?;
593 let filter_regex = Regex::new(filter)
594 .map_err(|_| ProcSysParserError::RegexCompileError { regex: filter.to_string() })?;
595
596 for blockdevice in blockdevice_directories {
597 let directory_entry = blockdevice.unwrap_or_else(|error| panic!("Error {} reading block device sysfs entry", error));
598
599 if !filter_regex.as_str().is_empty() && filter_regex.is_match(&directory_entry.file_name().into_string().unwrap()) { continue };
601
602 let mut blockdevice_data = BlockDevice::new();
603
604 blockdevice_data.device_name = directory_entry.file_name().into_string().unwrap();
605 blockdevice_data.alignment_offset = SysBlock::parse_contents_file_u64("alignment_offset", &directory_entry)?;
606 blockdevice_data.cache_type = SysBlock::parse_contents_file_option_string("cache_type", &directory_entry)?;
607 SysBlock::parse_dev(&mut blockdevice_data, &directory_entry)?;
608 blockdevice_data.discard_alignment = SysBlock::parse_contents_file_u64("discard_alignment", &directory_entry)?;
609 blockdevice_data.diskseq = SysBlock::parse_contents_file_option_u64("diskseq", &directory_entry)?;
610 blockdevice_data.hidden = SysBlock::parse_contents_file_u64("hidden", &directory_entry)?;
611 SysBlock::parse_inflight(&mut blockdevice_data, &directory_entry)?;
612 blockdevice_data.queue_add_random = SysBlock::parse_contents_file_u64("queue/add_random", &directory_entry)?;
613 blockdevice_data.queue_chunk_sectors = SysBlock::parse_contents_file_option_u64("queue/chunk_sectors", &directory_entry)?;
614 blockdevice_data.queue_dax = SysBlock::parse_contents_file_u64("queue/dax", &directory_entry)?;
615 blockdevice_data.queue_discard_granularity = SysBlock::parse_contents_file_u64("queue/discard_granularity", &directory_entry)?;
616 blockdevice_data.queue_discard_max_bytes = SysBlock::parse_contents_file_u64("queue/discard_max_bytes", &directory_entry)?;
617 blockdevice_data.queue_discard_max_hw_bytes = SysBlock::parse_contents_file_u64("queue/discard_max_hw_bytes", &directory_entry)?;
618 blockdevice_data.queue_hw_sector_size = SysBlock::parse_contents_file_u64("queue/hw_sector_size", &directory_entry)?;
619 blockdevice_data.queue_io_poll = SysBlock::parse_contents_file_u64("queue/io_poll", &directory_entry)?;
620 blockdevice_data.queue_io_poll_delay = SysBlock::parse_contents_file_i64("queue/io_poll_delay", &directory_entry)?;
621 blockdevice_data.queue_logical_block_size = SysBlock::parse_contents_file_u64("queue/logical_block_size", &directory_entry)?;
622 blockdevice_data.queue_max_discard_segments = SysBlock::parse_contents_file_u64("queue/max_discard_segments", &directory_entry)?;
623 blockdevice_data.queue_max_hw_sectors_kb = SysBlock::parse_contents_file_u64("queue/max_hw_sectors_kb", &directory_entry)?;
624 blockdevice_data.queue_max_integrity_segments = SysBlock::parse_contents_file_u64("queue/max_integrity_segments", &directory_entry)?;
625 blockdevice_data.queue_max_sectors_kb = SysBlock::parse_contents_file_u64("queue/max_sectors_kb", &directory_entry)?;
626 blockdevice_data.queue_max_segment_size = SysBlock::parse_contents_file_u64("queue/max_segment_size", &directory_entry)?;
627 blockdevice_data.queue_max_segments = SysBlock::parse_contents_file_u64("queue/max_segments", &directory_entry)?;
628 blockdevice_data.queue_minimum_io_size = SysBlock::parse_contents_file_u64("queue/minimum_io_size", &directory_entry)?;
629 blockdevice_data.queue_nomerges = SysBlock::parse_contents_file_u64("queue/nomerges", &directory_entry)?;
630 blockdevice_data.queue_nr_requests = SysBlock::parse_contents_file_u64("queue/nr_requests", &directory_entry)?;
631 blockdevice_data.queue_nr_zones = SysBlock::parse_contents_file_option_u64("queue/nr_zones", &directory_entry)?;
632 blockdevice_data.queue_optimal_io_size = SysBlock::parse_contents_file_u64("queue/optimal_io_size", &directory_entry)?;
633 blockdevice_data.queue_physical_block_size = SysBlock::parse_contents_file_u64("queue/physical_block_size", &directory_entry)?;
634 blockdevice_data.queue_read_ahead_kb = SysBlock::parse_contents_file_u64("queue/read_ahead_kb", &directory_entry)?;
635 blockdevice_data.queue_rotational = SysBlock::parse_contents_file_u64("queue/rotational", &directory_entry)?;
636 blockdevice_data.queue_rq_affinity = SysBlock::parse_contents_file_u64("queue/rq_affinity", &directory_entry)?;
637 SysBlock::parse_queue_scheduler(&mut blockdevice_data, &directory_entry)?;
638 blockdevice_data.queue_write_cache = SysBlock::parse_contents_file_string("queue/write_cache", &directory_entry)?;
639 blockdevice_data.queue_write_same_max_bytes = SysBlock::parse_contents_file_u64("queue/write_same_max_bytes", &directory_entry)?;
640 blockdevice_data.queue_zoned = SysBlock::parse_contents_file_option_string("queue/zoned", &directory_entry)?;
641 blockdevice_data.range = SysBlock::parse_contents_file_u64("range", &directory_entry)?;
642 blockdevice_data.removable = SysBlock::parse_contents_file_u64("removable", &directory_entry)?;
643 blockdevice_data.ro = SysBlock::parse_contents_file_u64("ro", &directory_entry)?;
644 blockdevice_data.size = SysBlock::parse_contents_file_u64("size", &directory_entry)?;
645
646 SysBlock::parse_stat(&mut blockdevice_data, &directory_entry)?;
647
648 sysblock.block_devices.push(blockdevice_data);
649 }
650
651 Ok(sysblock)
652 }
653}
654
655#[cfg(test)]
656mod tests {
657 use std::fs::{write, remove_dir_all, create_dir_all};
658 use rand::{thread_rng, Rng};
659 use rand::distributions::Alphanumeric;
660 use super::*;
661
662 #[test]
663 fn create_sys_block_device_parse_files() {
664 let alignment_offset = format!("0\n");
665 let cache_type = format!("write back\n");
666 let dev= format!("253:0\n");
667 let discard_alignment = format!("0\n");
668 let diskseq = format!("9\n");
669 let hidden = format!("0\n");
670 let inflight = format!(" 1 2\n");
671 let queue_add_random= format!("0\n");
672 let queue_chunk_sectors = format!("0\n");
673 let queue_dax = format!("0\n");
674 let queue_discard_granularity = format!("512\n");
675 let queue_discard_max_bytes = format!("2147483136\n");
676 let queue_discard_max_hw_bytes = format!("2147483136\n");
677 let queue_hw_sector_size = format!("512\n");
678 let queue_io_poll = format!("0\n");
679 let queue_io_poll_delay = format!("-1\n");
680 let queue_logical_block_size = format!("512\n");
681 let queue_max_discard_segments = format!("1\n");
682 let queue_max_hw_sectors_kb = format!("2147483647\n");
683 let queue_max_integrity_segments = format!("0\n");
684 let queue_max_sectors_kb = format!("1280\n");
685 let queue_max_segment_size = format!("4294967295\n");
686 let queue_max_segments = format!("254\n");
687 let queue_minimum_io_size = format!("512\n");
688 let queue_nomerges = format!("0\n");
689 let queue_nr_requests = format!("256\n");
690 let queue_nr_zones = format!("0\n");
691 let queue_optimal_io_size = format!("0\n");
692 let queue_physical_block_size = format!("512\n");
693 let queue_read_ahead_kb = format!("128\n");
694 let queue_rotational = format!("1\n");
695 let queue_rq_affinity = format!("1\n");
696 let queue_scheduler = format!("[none] mq-deadline\n");
697 let queue_write_cache = format!("write back\n");
698 let queue_write_same_max_bytes = format!("0\n");
699 let queue_zoned = format!("none\n");
700 let range = format!("16\n");
701 let removable = format!("0\n");
702 let ro = format!("0\n");
703 let size = format!("125829120\n");
704 let stat = format!(" 9718 3826 1052371 3026 2856 2331 312397 1947 0 6004 5554 7141 0 88014755 276 591 304\n");
705
706 let directory_suffix: String = thread_rng().sample_iter(&Alphanumeric).take(8).map(char::from).collect();
707 let test_path = format!("/tmp/test.{}", directory_suffix);
708 create_dir_all(format!("{}/block/sda/queue", test_path)).expect("Error creating mock sysfs directories.");
709 write(format!("{}/block/sda/alignment_offset", test_path),alignment_offset).expect("error writing to mock sysfs alignment_offset file.");
710 write(format!("{}/block/sda/cache_type", test_path),cache_type).expect("error writing to mock sysfs cache_type file.");
711 write(format!("{}/block/sda/dev", test_path),dev).expect("error writing to mock sysfs dev file.");
712 write(format!("{}/block/sda/discard_alignment", test_path),discard_alignment).expect("error writing to mock sysfs discard_alginment file.");
713 write(format!("{}/block/sda/diskseq", test_path),diskseq).expect("error writing to mock sysfs diskseq file.");
714 write(format!("{}/block/sda/hidden", test_path),hidden).expect("error writing to mock sysfs hidden file.");
715 write(format!("{}/block/sda/inflight", test_path),inflight).expect("error writing to mock sysfs inflight file.");
716 write(format!("{}/block/sda/queue/add_random", test_path),queue_add_random).expect("error writing to mock sysfs queue/add_random file.");
717 write(format!("{}/block/sda/queue/chunk_sectors", test_path),queue_chunk_sectors).expect("error writing to mock sysfs queue/chunk_sectors file.");
718 write(format!("{}/block/sda/queue/dax", test_path),queue_dax).expect("error writing to mock sysfs queue/dax file.");
719 write(format!("{}/block/sda/queue/discard_granularity", test_path),queue_discard_granularity).expect("error writing to mock sysfs queue/discard_granularity file.");
720 write(format!("{}/block/sda/queue/discard_max_bytes", test_path),queue_discard_max_bytes).expect("error writing to mock sysfs queue/discard_max_bytes file.");
721 write(format!("{}/block/sda/queue/discard_max_hw_bytes", test_path),queue_discard_max_hw_bytes).expect("error writing to mock sysfs queue/discard_max_hw_bytes file.");
722 write(format!("{}/block/sda/queue/hw_sector_size", test_path),queue_hw_sector_size).expect("error writing to mock sysfs queue/hw_sector_size file.");
723 write(format!("{}/block/sda/queue/io_poll", test_path),queue_io_poll).expect("error writing to mock sysfs queue/io_poll file.");
724 write(format!("{}/block/sda/queue/io_poll_delay", test_path),queue_io_poll_delay).expect("error writing to mock sysfs queue/io_poll_delay file.");
725 write(format!("{}/block/sda/queue/logical_block_size", test_path),queue_logical_block_size).expect("error writing to mock sysfs queue/logical_block_size file.");
726 write(format!("{}/block/sda/queue/max_discard_segments", test_path),queue_max_discard_segments).expect("error writing to mock sysfs queue/max_discard_segments file.");
727 write(format!("{}/block/sda/queue/max_hw_sectors_kb", test_path),queue_max_hw_sectors_kb).expect("error writing to mock sysfs queue/max_hw_sectors_kb file.");
728 write(format!("{}/block/sda/queue/max_integrity_segments", test_path),queue_max_integrity_segments).expect("error writing to mock sysfs queue/max_integrity_segments file.");
729 write(format!("{}/block/sda/queue/max_sectors_kb", test_path),queue_max_sectors_kb).expect("error writing to mock sysfs queue/max_sectors_kb file.");
730 write(format!("{}/block/sda/queue/max_segment_size", test_path),queue_max_segment_size).expect("error writing to mock sysfs queue/max_segment_size file.");
731 write(format!("{}/block/sda/queue/max_segments", test_path),queue_max_segments).expect("error writing to mock sysfs queue/max_segments file.");
732 write(format!("{}/block/sda/queue/minimum_io_size", test_path),queue_minimum_io_size).expect("error writing to mock sysfs queue/minimum_io_size file.");
733 write(format!("{}/block/sda/queue/nomerges", test_path),queue_nomerges).expect("error writing to mock sysfs queue/nomerges file.");
734 write(format!("{}/block/sda/queue/nr_requests", test_path),queue_nr_requests).expect("error writing to mock sysfs queue/nr_requests file.");
735 write(format!("{}/block/sda/queue/nr_zones", test_path),queue_nr_zones).expect("error writing to mock sysfs queue/nr_zones file.");
736 write(format!("{}/block/sda/queue/optimal_io_size", test_path),queue_optimal_io_size).expect("error writing to mock sysfs queue/optimal_io_size file.");
737 write(format!("{}/block/sda/queue/physical_block_size", test_path),queue_physical_block_size).expect("error writing to mock sysfs queue/physical_block_size file.");
738 write(format!("{}/block/sda/queue/read_ahead_kb", test_path),queue_read_ahead_kb).expect("error writing to mock sysfs queue/read_ahead_kb file.");
739 write(format!("{}/block/sda/queue/rotational", test_path),queue_rotational).expect("error writing to mock sysfs queue/rotational file.");
740 write(format!("{}/block/sda/queue/rq_affinity", test_path),queue_rq_affinity).expect("error writing to mock sysfs queue/rq_affinity file.");
741 write(format!("{}/block/sda/queue/scheduler", test_path),queue_scheduler).expect("error writing to mock sysfs queue/scheduler file.");
742 write(format!("{}/block/sda/queue/write_cache", test_path),queue_write_cache).expect("error writing to mock sysfs queue/write_cache file.");
743 write(format!("{}/block/sda/queue/write_same_max_bytes", test_path),queue_write_same_max_bytes).expect("error writing to mock sysfs queue/write_same_max_bytes file.");
744 write(format!("{}/block/sda/queue/zoned", test_path),queue_zoned).expect("error writing to mock sysfs queue/zoned file.");
745 write(format!("{}/block/sda/range", test_path),range).expect("error writing to mock sysfs range file.");
746 write(format!("{}/block/sda/removable", test_path),removable).expect("error writing to mock sysfs removable file.");
747 write(format!("{}/block/sda/ro", test_path),ro).expect("error writing to mock sysfs ro file.");
748 write(format!("{}/block/sda/size", test_path),size).expect("error writing to mock sysfs size file.");
749 write(format!("{}/block/sda/stat", test_path),stat).expect("error writing to mock sysfs stat file.");
750
751 let result = Builder::new().path(&test_path).read().unwrap();
752
753 remove_dir_all(test_path).unwrap();
754
755 assert_eq!(result, SysBlock {
756 block_devices: vec![
757 BlockDevice {
758 dev_block_major: 253,
759 dev_block_minor: 0,
760 device_name: "sda".to_string(),
761 discard_alignment: 0,
762 stat_reads_completed_success: 9718,
763 stat_reads_merged: 3826,
764 stat_reads_sectors: 1052371,
765 stat_reads_time_spent_ms: 3026,
766 stat_writes_completed_success: 2856,
767 stat_writes_merged: 2331,
768 stat_writes_sectors: 312397,
769 stat_writes_time_spent_ms: 1947,
770 stat_ios_in_progress: 0,
771 stat_ios_time_spent_ms: 6004,
772 stat_ios_weighted_time_spent_ms: 5554,
773 stat_discards_completed_success: Some(
774 7141,
775 ),
776 stat_discards_merged: Some(
777 0,
778 ),
779 stat_discards_sectors: Some(
780 88014755,
781 ),
782 stat_discards_time_spent_ms: Some(
783 276,
784 ),
785 stat_flush_requests_completed_success: Some(
786 591,
787 ),
788 stat_flush_requests_time_spent_ms: Some(
789 304,
790 ),
791 alignment_offset: 0,
792 cache_type: Some("write back".to_string()),
793 diskseq: Some(9),
794 hidden: 0,
795 inflight_reads: 1,
796 inflight_writes: 2,
797 range: 16,
798 removable: 0,
799 ro: 0,
800 size: 125829120,
801 queue_max_hw_sectors_kb: 2147483647,
802 queue_max_sectors_kb: 1280,
803 queue_max_discard_segments: 1,
804 queue_nr_requests: 256,
805 queue_nr_zones: Some(
806 0,
807 ),
808 queue_scheduler: "none".to_string(),
809 queue_rotational: 1,
810 queue_dax: 0,
811 queue_add_random: 0,
812 queue_discard_granularity: 512,
813 queue_discard_max_hw_bytes: 2147483136,
814 queue_discard_max_bytes: 2147483136,
815 queue_hw_sector_size: 512,
816 queue_io_poll: 0,
817 queue_io_poll_delay: -1,
818 queue_logical_block_size: 512,
819 queue_minimum_io_size: 512,
820 queue_max_integrity_segments: 0,
821 queue_max_segments: 254,
822 queue_max_segment_size: 4294967295,
823 queue_nomerges: 0,
824 queue_physical_block_size: 512,
825 queue_optimal_io_size: 0,
826 queue_read_ahead_kb: 128,
827 queue_rq_affinity: 1,
828 queue_write_cache: "write back".to_string(),
829 queue_write_same_max_bytes: 0,
830 queue_chunk_sectors: Some(
831 0,
832 ),
833 queue_zoned: Some(
834 "none".to_string(),
835 ),
836 },
837 ],
838 }
839 );
840 }
841 #[test]
842 fn create_sys_block_device_parse_files_non_existent() {
843 let alignment_offset = "0";
844 let cache_type = "write back";
845 let dev = "253:0";
846 let discard_alignment = "0";
847 let diskseq = "9";
848 let hidden = "0";
849 let inflight = " 1 2";
850 let queue_add_random = "0";
851 let queue_dax = "0";
852 let queue_discard_granularity = "512";
853 let queue_discard_max_bytes = "2147483136";
854 let queue_discard_max_hw_bytes = "2147483136";
855 let queue_hw_sector_size = "512";
856 let queue_io_poll = "0";
857 let queue_io_poll_delay = "-1";
858 let queue_logical_block_size = "512";
859 let queue_max_discard_segments = "1";
860 let queue_max_hw_sectors_kb = "2147483647";
861 let queue_max_integrity_segments = "0";
862 let queue_max_sectors_kb = "1280";
863 let queue_max_segment_size = "4294967295";
864 let queue_max_segments = "254";
865 let queue_minimum_io_size = "512";
866 let queue_nomerges = "0";
867 let queue_nr_requests = "256";
868 let queue_optimal_io_size = "0";
869 let queue_physical_block_size = "512";
870 let queue_read_ahead_kb = "128";
871 let queue_rotational = "1";
872 let queue_rq_affinity = "1";
873 let queue_scheduler = "[none] mq-deadline";
874 let queue_write_cache = "write back";
875 let queue_write_same_max_bytes = "0";
876 let range = "16";
877 let removable = "0";
878 let ro = "0";
879 let size = "125829120";
880 let stat = " 9718 3826 1052371 3026 2856 2331 312397 1947 0 6004 5554";
881
882 let directory_suffix: String = thread_rng().sample_iter(&Alphanumeric).take(8).map(char::from).collect();
883 let test_path = format!("/tmp/test.{}", directory_suffix);
884
885 create_dir_all(format!("{}/block/sda/queue", test_path)).expect("Error creating mock sysfs directories.");
886 write(format!("{}/block/sda/alignment_offset", test_path), alignment_offset).expect("error writing to mock sysfs alignment_offset file.");
887 write(format!("{}/block/sda/cache_type", test_path), cache_type).expect("error writing to mock sysfs cache_type file.");
888 write(format!("{}/block/sda/dev", test_path), dev).expect("error writing to mock sysfs dev file.");
889 write(format!("{}/block/sda/discard_alignment", test_path), discard_alignment).expect("error writing to mock sysfs discard_alginment file.");
890 write(format!("{}/block/sda/diskseq", test_path), diskseq).expect("error writing to mock sysfs diskseq file.");
891 write(format!("{}/block/sda/hidden", test_path), hidden).expect("error writing to mock sysfs hidden file.");
892 write(format!("{}/block/sda/inflight", test_path), inflight).expect("error writing to mock sysfs inflight file.");
893 write(format!("{}/block/sda/queue/add_random", test_path), queue_add_random).expect("error writing to mock sysfs queue/add_random file.");
894 write(format!("{}/block/sda/queue/dax", test_path), queue_dax).expect("error writing to mock sysfs queue/dax file.");
895 write(format!("{}/block/sda/queue/discard_granularity", test_path), queue_discard_granularity).expect("error writing to mock sysfs queue/discard_granularity file.");
896 write(format!("{}/block/sda/queue/discard_max_bytes", test_path), queue_discard_max_bytes).expect("error writing to mock sysfs queue/discard_max_bytes file.");
897 write(format!("{}/block/sda/queue/discard_max_hw_bytes", test_path), queue_discard_max_hw_bytes).expect("error writing to mock sysfs queue/discard_max_hw_bytes file.");
898 write(format!("{}/block/sda/queue/hw_sector_size", test_path), queue_hw_sector_size).expect("error writing to mock sysfs queue/hw_sector_size file.");
899 write(format!("{}/block/sda/queue/io_poll", test_path), queue_io_poll).expect("error writing to mock sysfs queue/io_poll file.");
900 write(format!("{}/block/sda/queue/io_poll_delay", test_path), queue_io_poll_delay).expect("error writing to mock sysfs queue/io_poll_delay file.");
901 write(format!("{}/block/sda/queue/logical_block_size", test_path), queue_logical_block_size).expect("error writing to mock sysfs queue/logical_block_size file.");
902 write(format!("{}/block/sda/queue/max_discard_segments", test_path), queue_max_discard_segments).expect("error writing to mock sysfs queue/max_discard_segments file.");
903 write(format!("{}/block/sda/queue/max_hw_sectors_kb", test_path), queue_max_hw_sectors_kb).expect("error writing to mock sysfs queue/max_hw_sectors_kb file.");
904 write(format!("{}/block/sda/queue/max_integrity_segments", test_path), queue_max_integrity_segments).expect("error writing to mock sysfs queue/max_integrity_segments file.");
905 write(format!("{}/block/sda/queue/max_sectors_kb", test_path), queue_max_sectors_kb).expect("error writing to mock sysfs queue/max_sectors_kb file.");
906 write(format!("{}/block/sda/queue/max_segment_size", test_path), queue_max_segment_size).expect("error writing to mock sysfs queue/max_segment_size file.");
907 write(format!("{}/block/sda/queue/max_segments", test_path), queue_max_segments).expect("error writing to mock sysfs queue/max_segments file.");
908 write(format!("{}/block/sda/queue/minimum_io_size", test_path), queue_minimum_io_size).expect("error writing to mock sysfs queue/minimum_io_size file.");
909 write(format!("{}/block/sda/queue/nomerges", test_path), queue_nomerges).expect("error writing to mock sysfs queue/nomerges file.");
910 write(format!("{}/block/sda/queue/nr_requests", test_path), queue_nr_requests).expect("error writing to mock sysfs queue/nr_requests file.");
911 write(format!("{}/block/sda/queue/optimal_io_size", test_path), queue_optimal_io_size).expect("error writing to mock sysfs queue/optimal_io_size file.");
912 write(format!("{}/block/sda/queue/physical_block_size", test_path), queue_physical_block_size).expect("error writing to mock sysfs queue/physical_block_size file.");
913 write(format!("{}/block/sda/queue/read_ahead_kb", test_path), queue_read_ahead_kb).expect("error writing to mock sysfs queue/read_ahead_kb file.");
914 write(format!("{}/block/sda/queue/rotational", test_path), queue_rotational).expect("error writing to mock sysfs queue/rotational file.");
915 write(format!("{}/block/sda/queue/rq_affinity", test_path), queue_rq_affinity).expect("error writing to mock sysfs queue/rq_affinity file.");
916 write(format!("{}/block/sda/queue/scheduler", test_path), queue_scheduler).expect("error writing to mock sysfs queue/scheduler file.");
917 write(format!("{}/block/sda/queue/write_cache", test_path), queue_write_cache).expect("error writing to mock sysfs queue/write_cache file.");
918 write(format!("{}/block/sda/queue/write_same_max_bytes", test_path), queue_write_same_max_bytes).expect("error writing to mock sysfs queue/write_same_max_bytes file.");
919 write(format!("{}/block/sda/range", test_path), range).expect("error writing to mock sysfs range file.");
920 write(format!("{}/block/sda/removable", test_path), removable).expect("error writing to mock sysfs removable file.");
921 write(format!("{}/block/sda/ro", test_path), ro).expect("error writing to mock sysfs ro file.");
922 write(format!("{}/block/sda/size", test_path), size).expect("error writing to mock sysfs size file.");
923 write(format!("{}/block/sda/stat", test_path), stat).expect("error writing to mock sysfs stat file.");
924
925 let result = Builder::new().path(&test_path).read().unwrap();
926
927 remove_dir_all(test_path).unwrap();
928
929 assert_eq!(result,
930 SysBlock {
931 block_devices: vec![
932 BlockDevice {
933 dev_block_major: 253,
934 dev_block_minor: 0,
935 device_name: "sda".to_string(),
936 discard_alignment: 0,
937 stat_reads_completed_success: 9718,
938 stat_reads_merged: 3826,
939 stat_reads_sectors: 1052371,
940 stat_reads_time_spent_ms: 3026,
941 stat_writes_completed_success: 2856,
942 stat_writes_merged: 2331,
943 stat_writes_sectors: 312397,
944 stat_writes_time_spent_ms: 1947,
945 stat_ios_in_progress: 0,
946 stat_ios_time_spent_ms: 6004,
947 stat_ios_weighted_time_spent_ms: 5554,
948 stat_discards_completed_success: None,
949 stat_discards_merged: None,
950 stat_discards_sectors: None,
951 stat_discards_time_spent_ms: None,
952 stat_flush_requests_completed_success: None,
953 stat_flush_requests_time_spent_ms: None,
954 alignment_offset: 0,
955 cache_type: Some("write back".to_string()),
956 diskseq: Some(9),
957 hidden: 0,
958 inflight_reads: 1,
959 inflight_writes: 2,
960 range: 16,
961 removable: 0,
962 ro: 0,
963 size: 125829120,
964 queue_max_hw_sectors_kb: 2147483647,
965 queue_max_sectors_kb: 1280,
966 queue_max_discard_segments: 1,
967 queue_nr_requests: 256,
968 queue_nr_zones: None,
969 queue_scheduler: "none".to_string(),
970 queue_rotational: 1,
971 queue_dax: 0,
972 queue_add_random: 0,
973 queue_discard_granularity: 512,
974 queue_discard_max_hw_bytes: 2147483136,
975 queue_discard_max_bytes: 2147483136,
976 queue_hw_sector_size: 512,
977 queue_io_poll: 0,
978 queue_io_poll_delay: -1,
979 queue_logical_block_size: 512,
980 queue_minimum_io_size: 512,
981 queue_max_integrity_segments: 0,
982 queue_max_segments: 254,
983 queue_max_segment_size: 4294967295,
984 queue_nomerges: 0,
985 queue_physical_block_size: 512,
986 queue_optimal_io_size: 0,
987 queue_read_ahead_kb: 128,
988 queue_rq_affinity: 1,
989 queue_write_cache: "write back".to_string(),
990 queue_write_same_max_bytes: 0,
991 queue_chunk_sectors: None,
992 queue_zoned: None,
993 },
994 ],
995 }
996 );
997 }
998 #[test]
999 fn create_sys_block_device_test_filter() {
1000 let alignment_offset = "0";
1001 let cache_type = "write back";
1002 let dev = "253:0";
1003 let discard_alignment = "0";
1004 let diskseq = "9";
1005 let hidden = "0";
1006 let inflight = " 1 2";
1007 let queue_add_random = "0";
1008 let queue_dax = "0";
1009 let queue_discard_granularity = "512";
1010 let queue_discard_max_bytes = "2147483136";
1011 let queue_discard_max_hw_bytes = "2147483136";
1012 let queue_hw_sector_size = "512";
1013 let queue_io_poll = "0";
1014 let queue_io_poll_delay = "-1";
1015 let queue_logical_block_size = "512";
1016 let queue_max_discard_segments = "1";
1017 let queue_max_hw_sectors_kb = "2147483647";
1018 let queue_max_integrity_segments = "0";
1019 let queue_max_sectors_kb = "1280";
1020 let queue_max_segment_size = "4294967295";
1021 let queue_max_segments = "254";
1022 let queue_minimum_io_size = "512";
1023 let queue_nomerges = "0";
1024 let queue_nr_requests = "256";
1025 let queue_optimal_io_size = "0";
1026 let queue_physical_block_size = "512";
1027 let queue_read_ahead_kb = "128";
1028 let queue_rotational = "1";
1029 let queue_rq_affinity = "1";
1030 let queue_scheduler = "[none] mq-deadline";
1031 let queue_write_cache = "write back";
1032 let queue_write_same_max_bytes = "0";
1033 let range = "16";
1034 let removable = "0";
1035 let ro = "0";
1036 let size = "125829120";
1037 let stat = " 9718 3826 1052371 3026 2856 2331 312397 1947 0 6004 5554";
1038
1039 let directory_suffix: String = thread_rng().sample_iter(&Alphanumeric).take(8).map(char::from).collect();
1040 let test_path = format!("/tmp/test.{}", directory_suffix);
1041
1042 create_dir_all(format!("{}/block/dm-0/queue", test_path)).expect("Error creating mock sysfs directories.");
1043 write(format!("{}/block/dm-0/alignment_offset", test_path), alignment_offset).expect("error writing to mock sysfs alignment_offset file.");
1044 write(format!("{}/block/dm-0/cache_type", test_path), cache_type).expect("error writing to mock sysfs cache_type file.");
1045 write(format!("{}/block/dm-0/dev", test_path), dev).expect("error writing to mock sysfs dev file.");
1046 write(format!("{}/block/dm-0/discard_alignment", test_path), discard_alignment).expect("error writing to mock sysfs discard_alginment file.");
1047 write(format!("{}/block/dm-0/diskseq", test_path), diskseq).expect("error writing to mock sysfs diskseq file.");
1048 write(format!("{}/block/dm-0/hidden", test_path), hidden).expect("error writing to mock sysfs hidden file.");
1049 write(format!("{}/block/dm-0/inflight", test_path), inflight).expect("error writing to mock sysfs inflight file.");
1050 write(format!("{}/block/dm-0/queue/add_random", test_path), queue_add_random).expect("error writing to mock sysfs queue/add_random file.");
1051 write(format!("{}/block/dm-0/queue/dax", test_path), queue_dax).expect("error writing to mock sysfs queue/dax file.");
1052 write(format!("{}/block/dm-0/queue/discard_granularity", test_path), queue_discard_granularity).expect("error writing to mock sysfs queue/discard_granularity file.");
1053 write(format!("{}/block/dm-0/queue/discard_max_bytes", test_path), queue_discard_max_bytes).expect("error writing to mock sysfs queue/discard_max_bytes file.");
1054 write(format!("{}/block/dm-0/queue/discard_max_hw_bytes", test_path), queue_discard_max_hw_bytes).expect("error writing to mock sysfs queue/discard_max_hw_bytes file.");
1055 write(format!("{}/block/dm-0/queue/hw_sector_size", test_path), queue_hw_sector_size).expect("error writing to mock sysfs queue/hw_sector_size file.");
1056 write(format!("{}/block/dm-0/queue/io_poll", test_path), queue_io_poll).expect("error writing to mock sysfs queue/io_poll file.");
1057 write(format!("{}/block/dm-0/queue/io_poll_delay", test_path), queue_io_poll_delay).expect("error writing to mock sysfs queue/io_poll_delay file.");
1058 write(format!("{}/block/dm-0/queue/logical_block_size", test_path), queue_logical_block_size).expect("error writing to mock sysfs queue/logical_block_size file.");
1059 write(format!("{}/block/dm-0/queue/max_discard_segments", test_path), queue_max_discard_segments).expect("error writing to mock sysfs queue/max_discard_segments file.");
1060 write(format!("{}/block/dm-0/queue/max_hw_sectors_kb", test_path), queue_max_hw_sectors_kb).expect("error writing to mock sysfs queue/max_hw_sectors_kb file.");
1061 write(format!("{}/block/dm-0/queue/max_integrity_segments", test_path), queue_max_integrity_segments).expect("error writing to mock sysfs queue/max_integrity_segments file.");
1062 write(format!("{}/block/dm-0/queue/max_sectors_kb", test_path), queue_max_sectors_kb).expect("error writing to mock sysfs queue/max_sectors_kb file.");
1063 write(format!("{}/block/dm-0/queue/max_segment_size", test_path), queue_max_segment_size).expect("error writing to mock sysfs queue/max_segment_size file.");
1064 write(format!("{}/block/dm-0/queue/max_segments", test_path), queue_max_segments).expect("error writing to mock sysfs queue/max_segments file.");
1065 write(format!("{}/block/dm-0/queue/minimum_io_size", test_path), queue_minimum_io_size).expect("error writing to mock sysfs queue/minimum_io_size file.");
1066 write(format!("{}/block/dm-0/queue/nomerges", test_path), queue_nomerges).expect("error writing to mock sysfs queue/nomerges file.");
1067 write(format!("{}/block/dm-0/queue/nr_requests", test_path), queue_nr_requests).expect("error writing to mock sysfs queue/nr_requests file.");
1068 write(format!("{}/block/dm-0/queue/optimal_io_size", test_path), queue_optimal_io_size).expect("error writing to mock sysfs queue/optimal_io_size file.");
1069 write(format!("{}/block/dm-0/queue/physical_block_size", test_path), queue_physical_block_size).expect("error writing to mock sysfs queue/physical_block_size file.");
1070 write(format!("{}/block/dm-0/queue/read_ahead_kb", test_path), queue_read_ahead_kb).expect("error writing to mock sysfs queue/read_ahead_kb file.");
1071 write(format!("{}/block/dm-0/queue/rotational", test_path), queue_rotational).expect("error writing to mock sysfs queue/rotational file.");
1072 write(format!("{}/block/dm-0/queue/rq_affinity", test_path), queue_rq_affinity).expect("error writing to mock sysfs queue/rq_affinity file.");
1073 write(format!("{}/block/dm-0/queue/scheduler", test_path), queue_scheduler).expect("error writing to mock sysfs queue/scheduler file.");
1074 write(format!("{}/block/dm-0/queue/write_cache", test_path), queue_write_cache).expect("error writing to mock sysfs queue/write_cache file.");
1075 write(format!("{}/block/dm-0/queue/write_same_max_bytes", test_path), queue_write_same_max_bytes).expect("error writing to mock sysfs queue/write_same_max_bytes file.");
1076 write(format!("{}/block/dm-0/range", test_path), range).expect("error writing to mock sysfs range file.");
1077 write(format!("{}/block/dm-0/removable", test_path), removable).expect("error writing to mock sysfs removable file.");
1078 write(format!("{}/block/dm-0/ro", test_path), ro).expect("error writing to mock sysfs ro file.");
1079 write(format!("{}/block/dm-0/size", test_path), size).expect("error writing to mock sysfs size file.");
1080 write(format!("{}/block/dm-0/stat", test_path), stat).expect("error writing to mock sysfs stat file.");
1081
1082 let result = Builder::new().path(&test_path).read().unwrap();
1083
1084 remove_dir_all(test_path).unwrap();
1085
1086 assert_eq!(result, SysBlock { block_devices: vec![] });
1087 }
1088}