| 161 | } |
| 162 | |
| 163 | fn write_vectored( |
| 164 | &mut self, |
| 165 | offset: libc::off_t, |
| 166 | iovecs: &[libc::iovec], |
| 167 | user_data: u64, |
| 168 | ) -> AsyncIoResult<()> { |
| 169 | let address = offset as u64; |
| 170 | let total_len: usize = iovecs.iter().map(|v| v.iov_len).sum(); |
| 171 | let mut buf_offset = 0usize; |
| 172 | |
| 173 | while buf_offset < total_len { |
| 174 | let curr_addr = address + buf_offset as u64; |
| 175 | let intra_offset = curr_addr & (self.cluster_size - 1); |
| 176 | let remaining_in_cluster = (self.cluster_size - intra_offset) as usize; |
| 177 | let count = min(total_len - buf_offset, remaining_in_cluster); |
| 178 | |
| 179 | // Read backing data for COW if this is a partial cluster |
| 180 | // write to an unallocated cluster with a backing file. |
| 181 | let backing_data = if let Some(backing) = self |
| 182 | .backing_file |
| 183 | .as_ref() |
| 184 | .filter(|_| intra_offset != 0 || count < self.cluster_size as usize) |
| 185 | { |
| 186 | let cluster_begin = curr_addr - intra_offset; |
| 187 | let mut data = vec![0u8; self.cluster_size as usize]; |
| 188 | backing |
| 189 | .read_at(cluster_begin, &mut data) |
| 190 | .map_err(AsyncIoError::WriteVectored)?; |
| 191 | Some(data) |
| 192 | } else { |
| 193 | None |
| 194 | }; |
| 195 | |
| 196 | let mapping = self |
| 197 | .metadata |
| 198 | .map_cluster_for_write(curr_addr, backing_data) |
| 199 | .map_err(AsyncIoError::WriteVectored)?; |
| 200 | |
| 201 | match mapping { |
| 202 | ClusterWriteMapping::Allocated { |
| 203 | offset: host_offset, |
| 204 | } => { |
| 205 | if self.alignment > 0 { |
| 206 | // O_DIRECT, gather directly into aligned buffer. |
| 207 | let mut abuf = AlignedBuf::new(count, self.alignment) |
| 208 | .map_err(AsyncIoError::WriteVectored)?; |
| 209 | // SAFETY: iovecs point to valid guest memory buffers |
| 210 | unsafe { |
| 211 | gather_from_iovecs_into(iovecs, buf_offset, abuf.as_mut_slice(count)); |
| 212 | } |
| 213 | aligned_pwrite( |
| 214 | self.data_file.as_raw_fd(), |
| 215 | abuf.as_slice(count), |
| 216 | host_offset, |
| 217 | self.alignment, |
| 218 | ) |
| 219 | .map_err(AsyncIoError::WriteVectored)?; |
| 220 | } else { |