Traverse the L1 and L2 tables to find all reachable data clusters.
(
refcounts: &mut [u64],
header: &QcowHeader,
cluster_size: u64,
raw_file: &mut QcowRawFile,
max_refcount: u64,
refcount_bits: u
| 1088 | |
| 1089 | // Traverse the L1 and L2 tables to find all reachable data clusters. |
| 1090 | fn set_data_refcounts( |
| 1091 | refcounts: &mut [u64], |
| 1092 | header: &QcowHeader, |
| 1093 | cluster_size: u64, |
| 1094 | raw_file: &mut QcowRawFile, |
| 1095 | max_refcount: u64, |
| 1096 | refcount_bits: u64, |
| 1097 | ) -> Result<()> { |
| 1098 | let l1_table = raw_file |
| 1099 | .read_pointer_table( |
| 1100 | header.l1_table_offset, |
| 1101 | u64::from(header.l1_size), |
| 1102 | Some(L1_TABLE_OFFSET_MASK), |
| 1103 | ) |
| 1104 | .map_err(Error::ReadingPointers)?; |
| 1105 | for l1_index in 0..header.l1_size as usize { |
| 1106 | let l2_addr_disk = *l1_table.get(l1_index).ok_or(Error::InvalidIndex)?; |
| 1107 | if l2_addr_disk != 0 { |
| 1108 | // Add a reference to the L2 table cluster itself. |
| 1109 | add_ref( |
| 1110 | refcounts, |
| 1111 | cluster_size, |
| 1112 | l2_addr_disk, |
| 1113 | max_refcount, |
| 1114 | refcount_bits, |
| 1115 | )?; |
| 1116 | |
| 1117 | // Read the L2 table and find all referenced data clusters. |
| 1118 | let l2_table = raw_file |
| 1119 | .read_pointer_table( |
| 1120 | l2_addr_disk, |
| 1121 | cluster_size / size_of::<u64>() as u64, |
| 1122 | Some(L2_TABLE_OFFSET_MASK), |
| 1123 | ) |
| 1124 | .map_err(Error::ReadingPointers)?; |
| 1125 | for data_cluster_addr in l2_table { |
| 1126 | if data_cluster_addr != 0 { |
| 1127 | add_ref( |
| 1128 | refcounts, |
| 1129 | cluster_size, |
| 1130 | data_cluster_addr, |
| 1131 | max_refcount, |
| 1132 | refcount_bits, |
| 1133 | )?; |
| 1134 | } |
| 1135 | } |
| 1136 | } |
| 1137 | } |
| 1138 | |
| 1139 | Ok(()) |
| 1140 | } |
| 1141 | |
| 1142 | // Add references to the top-level refcount table clusters. |
| 1143 | fn set_refcount_table_refcounts( |
nothing calls this directly
no test coverage detected