1#![forbid(unsafe_code)]
8
9use disk_backend::pr;
10use nvme_spec::nvm;
11use thiserror::Error;
12
13pub fn to_nvme_reservation_type(reservation_type: pr::ReservationType) -> nvm::ReservationType {
15 match reservation_type {
16 pr::ReservationType::WriteExclusive => nvm::ReservationType::WRITE_EXCLUSIVE,
17 pr::ReservationType::ExclusiveAccess => nvm::ReservationType::EXCLUSIVE_ACCESS,
18 pr::ReservationType::WriteExclusiveRegistrantsOnly => {
19 nvm::ReservationType::WRITE_EXCLUSIVE_REGISTRANTS_ONLY
20 }
21 pr::ReservationType::ExclusiveAccessRegistrantsOnly => {
22 nvm::ReservationType::EXCLUSIVE_ACCESS_REGISTRANTS_ONLY
23 }
24 pr::ReservationType::WriteExclusiveAllRegistrants => {
25 nvm::ReservationType::WRITE_EXCLUSIVE_ALL_REGISTRANTS
26 }
27 pr::ReservationType::ExclusiveAccessAllRegistrants => {
28 nvm::ReservationType::EXCLUSIVE_ACCESS_ALL_REGISTRANTS
29 }
30 }
31}
32
33#[derive(Debug, Error)]
35#[error("invalid nvme reservation type: {0:#x?}")]
36pub struct InvalidReservationType(nvm::ReservationType);
37
38pub fn from_nvme_reservation_type(
40 nvme_type: nvm::ReservationType,
41) -> Result<pr::ReservationType, InvalidReservationType> {
42 let reservation_type = match nvme_type {
43 nvm::ReservationType::WRITE_EXCLUSIVE => pr::ReservationType::WriteExclusive,
44 nvm::ReservationType::EXCLUSIVE_ACCESS => pr::ReservationType::ExclusiveAccess,
45 nvm::ReservationType::WRITE_EXCLUSIVE_REGISTRANTS_ONLY => {
46 pr::ReservationType::WriteExclusiveRegistrantsOnly
47 }
48 nvm::ReservationType::EXCLUSIVE_ACCESS_REGISTRANTS_ONLY => {
49 pr::ReservationType::ExclusiveAccessRegistrantsOnly
50 }
51 nvm::ReservationType::WRITE_EXCLUSIVE_ALL_REGISTRANTS => {
52 pr::ReservationType::WriteExclusiveAllRegistrants
53 }
54 nvm::ReservationType::EXCLUSIVE_ACCESS_ALL_REGISTRANTS => {
55 pr::ReservationType::ExclusiveAccessAllRegistrants
56 }
57 _ => return Err(InvalidReservationType(nvme_type)),
58 };
59 Ok(reservation_type)
60}
61
62pub fn from_nvme_reservation_capabilities(
64 rescap: nvm::ReservationCapabilities,
65) -> pr::ReservationCapabilities {
66 pr::ReservationCapabilities {
67 write_exclusive: rescap.write_exclusive(),
68 exclusive_access: rescap.exclusive_access(),
69 write_exclusive_registrants_only: rescap.write_exclusive_registrants_only(),
70 exclusive_access_registrants_only: rescap.exclusive_access_registrants_only(),
71 write_exclusive_all_registrants: rescap.write_exclusive_all_registrants(),
72 exclusive_access_all_registrants: rescap.exclusive_access_all_registrants(),
73 persist_through_power_loss: rescap.persist_through_power_loss(),
74 }
75}
76
77pub fn from_nvme_reservation_report(
79 report_header: &nvm::ReservationReport,
80 controllers: &[nvm::RegisteredControllerExtended],
81) -> Result<pr::ReservationReport, InvalidReservationType> {
82 let reservation_type = if report_header.rtype.0 != 0 {
83 Some(from_nvme_reservation_type(report_header.rtype)?)
84 } else {
85 None
86 };
87
88 let controllers = controllers
89 .iter()
90 .map(|controller| pr::RegisteredController {
91 key: controller.rkey,
92 holds_reservation: controller.rcsts.holds_reservation(),
93 controller_id: controller.cntlid,
94 host_id: controller.hostid.to_vec(),
95 })
96 .collect();
97
98 let report = pr::ReservationReport {
99 generation: report_header.generation,
100 reservation_type,
101 controllers,
102 persist_through_power_loss: report_header.ptpls != 0,
103 };
104
105 Ok(report)
106}