1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::path::PathBuf;
use super::device::Device;
use super::deviceinfo::DeviceInfo;
use super::dm::{DM, DM_STATUS_TABLE, DM_SUSPEND, DmFlags};
use super::result::{DmError, DmResult, ErrorEnum};
use super::types::{DevId, DmName, DmUuid, Sectors, TargetLine};
pub trait DmDevice {
fn devnode(&self) -> PathBuf;
fn device(&self) -> Device;
fn name(&self) -> &DmName;
fn size(&self) -> Sectors;
fn teardown(self, dm: &DM) -> DmResult<()>;
}
pub fn message(dm: &DM, target: &DmDevice, msg: &str) -> DmResult<()> {
dm.target_msg(&DevId::Name(target.name()), None, msg)?;
Ok(())
}
pub fn device_create(dm: &DM,
name: &DmName,
uuid: Option<&DmUuid>,
table: &[TargetLine])
-> DmResult<DeviceInfo> {
dm.device_create(name, uuid, DmFlags::empty())?;
let id = DevId::Name(name);
let dev_info = match dm.table_load(&id, table) {
Err(e) => {
dm.device_remove(&id, DmFlags::empty())?;
return Err(e);
}
Ok(dev_info) => dev_info,
};
dm.device_suspend(&id, DmFlags::empty())?;
Ok(dev_info)
}
fn device_match(dm: &DM,
name: &DmName,
uuid: Option<&DmUuid>,
table: &[TargetLine])
-> DmResult<DeviceInfo> {
let table_status = dm.table_status(&DevId::Name(name), DM_STATUS_TABLE)?;
if table_status.1 != table {
let err_msg = format!("Specified new table \"{:?}\" does not match kernel table \"{:?}\"",
table,
table_status.1);
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}
let status = table_status.0;
if status.uuid() != uuid {
let err_msg = format!("Specified uuid \"{:?}\" does not match kernel uuuid \"{:?}\"",
uuid,
status.uuid());
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}
Ok(status)
}
pub fn device_setup(dm: &DM,
name: &DmName,
uuid: Option<&DmUuid>,
table: &[TargetLine])
-> DmResult<DeviceInfo> {
if device_exists(dm, name)? {
device_match(dm, name, uuid, table)
} else {
device_create(dm, name, uuid, table)
}
}
pub fn table_reload(dm: &DM, id: &DevId, table: &[TargetLine]) -> DmResult<DeviceInfo> {
let dev_info = dm.table_load(id, table)?;
dm.device_suspend(id, DM_SUSPEND)?;
dm.device_suspend(id, DmFlags::empty())?;
Ok(dev_info)
}
pub fn device_exists(dm: &DM, name: &DmName) -> DmResult<bool> {
Ok(dm.list_devices()
.map(|l| l.iter().any(|&(ref n, _, _)| n.as_ref() == name))?)
}