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