1use super::{
6 ActiveRequests, DecodedRequest, DeviceInfo, FIFO_MAX_REQUESTS, HandleRequestResult,
7 IntoOrchestrator, KeyRegistry, OffsetMap, Operation, SessionHelper, TraceFlowId,
8};
9use crate::mapper::serve_mapper_session;
10use crate::verifier::Verifier;
11use anyhow::Error;
12use block_protocol::{BlockFifoRequest, BlockFifoResponse, ReadOptions, WriteFlags, WriteOptions};
13use fidl::endpoints::ServerEnd;
14use fidl_fuchsia_storage_block as fblock;
15use fidl_fuchsia_storage_block::DeviceFlag;
16use fuchsia_async as fasync;
17use fuchsia_sync::Mutex;
18use futures::future::{Fuse, FusedFuture, join};
19use futures::stream::FuturesUnordered;
20use futures::{FutureExt, StreamExt, select_biased};
21use mapping::reader::{BlockService, MAX_READ_BUFFER_SIZE};
22use std::borrow::Cow;
23use std::collections::VecDeque;
24use std::future::{Future, poll_fn};
25use std::mem::MaybeUninit;
26use std::pin::pin;
27use std::sync::{Arc, OnceLock};
28use std::task::{Poll, ready};
29use storage_device::buffer::{Buffer, OwnedBuffer};
30use storage_device::buffer_allocator::{BufferAllocator, BufferSource};
31
32pub trait Interface: Send + Sync + Unpin + 'static {
33 fn open_session(
62 &self,
63 session_manager: Arc<SessionManager<Self>>,
64 stream: fblock::SessionRequestStream,
65 offset_map: OffsetMap,
66 block_size: u32,
67 ) -> impl Future<Output = Result<(), Error>> + Send {
68 session_manager.serve_session(
70 stream,
71 offset_map,
72 self.get_info().max_transfer_blocks(),
73 block_size,
74 )
75 }
76
77 fn open_mapper_session(
80 session_manager: Arc<SessionManager<Self>>,
81 session: ServerEnd<fblock::MapperSessionMarker>,
82 mapping_vmo: zx::Vmo,
83 block_size: u32,
84 port: Option<zx::Port>,
85 delivery_queue: Option<zx::Vmo>,
86 ) -> Result<impl Future<Output = Result<(), Error>> + Send + 'static, zx::Status> {
87 let buffer_source = BufferSource::new(MAX_READ_BUFFER_SIZE * 16);
88 let vmo = buffer_source.vmo().clone();
89 let allocator = Arc::new(BufferAllocator::new(
90 std::cmp::max(block_size as usize, zx::system_get_page_size() as usize),
91 buffer_source,
92 ));
93 let scope = fasync::Scope::new();
94 let service: Arc<dyn BlockService> = Arc::new(AsyncBlockService::new_with_allocator(
95 session_manager.interface.clone(),
96 block_size,
97 allocator,
98 scope.to_handle(),
99 ));
100 let interface = session_manager.interface.clone();
101 let session_fut = serve_mapper_session(
102 Arc::new(move |mapping_vmo: &zx::Vmo, dq: zx::Vmo| {
103 interface.on_open_mapper_session(mapping_vmo, dq)
104 }),
105 service,
106 session,
107 mapping_vmo,
108 port,
109 delivery_queue,
110 )?;
111 Ok(async move {
112 session_manager.interface.on_attach_vmo(&vmo).await?;
113 scopeguard::defer! {
114 session_manager.interface.on_detach_vmo(&vmo);
115 }
116 let res = session_fut.await;
117 scope.cancel().await;
118 res
119 })
120 }
121
122 fn on_open_mapper_session(
125 &self,
126 _mapping_vmo: &zx::Vmo,
127 delivery_queue: zx::Vmo,
128 ) -> Result<Verifier, zx::Status> {
129 Ok(Verifier::new(delivery_queue))
130 }
131
132 fn on_attach_vmo(&self, _vmo: &zx::Vmo) -> impl Future<Output = Result<(), zx::Status>> + Send {
136 async { Ok(()) }
137 }
138
139 fn on_detach_vmo(&self, _vmo: &zx::Vmo) {}
141
142 fn get_info(&self) -> Cow<'_, DeviceInfo>;
144
145 fn read(
152 &self,
153 device_block_offset: u64,
154 block_count: u32,
155 vmo: &Arc<zx::Vmo>,
156 vmo_offset: u64, opts: ReadOptions,
158 trace_flow_id: TraceFlowId,
159 ) -> impl Future<Output = Result<(), zx::Status>> + Send;
160
161 fn write(
168 &self,
169 device_block_offset: u64,
170 block_count: u32,
171 vmo: &Arc<zx::Vmo>,
172 vmo_offset: u64, opts: WriteOptions,
174 trace_flow_id: TraceFlowId,
175 ) -> impl Future<Output = Result<(), zx::Status>> + Send;
176
177 fn flush(
179 &self,
180 trace_flow_id: TraceFlowId,
181 ) -> impl Future<Output = Result<(), zx::Status>> + Send;
182
183 fn trim(
190 &self,
191 device_block_offset: u64,
192 block_count: u32,
193 trace_flow_id: TraceFlowId,
194 ) -> impl Future<Output = Result<(), zx::Status>> + Send;
195
196 fn get_volume_info(
198 &self,
199 ) -> impl Future<Output = Result<(fblock::VolumeManagerInfo, fblock::VolumeInfo), zx::Status>> + Send
200 {
201 async { Err(zx::Status::NOT_SUPPORTED) }
202 }
203
204 fn query_slices(
206 &self,
207 _start_slices: &[u64],
208 ) -> impl Future<Output = Result<Vec<fblock::VsliceRange>, zx::Status>> + Send {
209 async { Err(zx::Status::NOT_SUPPORTED) }
210 }
211
212 fn extend(
214 &self,
215 _start_slice: u64,
216 _slice_count: u64,
217 ) -> impl Future<Output = Result<(), zx::Status>> + Send {
218 async { Err(zx::Status::NOT_SUPPORTED) }
219 }
220
221 fn shrink(
223 &self,
224 _start_slice: u64,
225 _slice_count: u64,
226 ) -> impl Future<Output = Result<(), zx::Status>> + Send {
227 async { Err(zx::Status::NOT_SUPPORTED) }
228 }
229}
230
231pub struct PassthroughSession(fblock::SessionProxy);
233
234impl PassthroughSession {
235 pub fn new(proxy: fblock::SessionProxy) -> Self {
236 Self(proxy)
237 }
238
239 async fn handle_request(&self, request: fblock::SessionRequest) -> Result<(), Error> {
240 match request {
241 fblock::SessionRequest::GetFifo { responder } => {
242 responder.send(self.0.get_fifo().await?)?;
243 }
244 fblock::SessionRequest::AttachVmo { vmo, responder } => {
245 responder.send(self.0.attach_vmo(vmo).await?.as_ref().map_err(|s| *s))?;
246 }
247 fblock::SessionRequest::RegisterKey { key_token, responder } => {
248 responder.send(self.0.register_key(key_token).await?)?;
249 }
250 fblock::SessionRequest::Close { responder } => {
251 responder.send(self.0.close().await?)?;
252 }
253 }
254 Ok(())
255 }
256
257 pub async fn serve(&self, mut stream: fblock::SessionRequestStream) -> Result<(), Error> {
259 while let Some(Ok(request)) = stream.next().await {
260 if let Err(error) = self.handle_request(request).await {
261 log::warn!(error:?; "FIDL error");
262 }
263 }
264 Ok(())
265 }
266}
267
268pub struct SessionManager<I: Interface + ?Sized> {
269 interface: Arc<I>,
270 active_requests: ActiveRequests<usize>,
271 key_registry: KeyRegistry,
272
273 buffer_allocator: OnceLock<BufferAllocator>,
276}
277
278impl<I: Interface + ?Sized> Drop for SessionManager<I> {
279 fn drop(&mut self) {
280 if let Some(allocator) = self.buffer_allocator.get() {
281 self.interface.on_detach_vmo(allocator.buffer_source().vmo());
282 }
283 }
284}
285
286impl<I: Interface + ?Sized> SessionManager<I> {
287 pub fn new(interface: Arc<I>) -> Self {
288 Self {
289 interface,
290 active_requests: ActiveRequests::default(),
291 key_registry: KeyRegistry::default(),
292 buffer_allocator: OnceLock::new(),
293 }
294 }
295
296 pub fn interface(&self) -> &Arc<I> {
297 &self.interface
298 }
299
300 pub async fn serve_session(
302 self: Arc<Self>,
303 stream: fblock::SessionRequestStream,
304 offset_map: OffsetMap,
305 max_transfer_blocks: Option<std::num::NonZero<u32>>,
306 block_size: u32,
307 ) -> Result<(), Error> {
308 let (helper, fifo) =
309 SessionHelper::new(self.clone(), offset_map, max_transfer_blocks, block_size)?;
310 let session = Arc::new(Session {
311 helper: Arc::new(helper),
312 interface: self.interface.clone(),
313 close_callback: Mutex::new(None),
314 });
315
316 let (stop_sender, stop_receiver) = futures::channel::oneshot::channel();
317
318 let mut stream = stream.fuse();
319 let scope = fasync::Scope::new();
320 let session_clone = session.clone();
321 let mut fifo_task = scope
322 .spawn(async move {
323 if let Err(status) = session_clone.run_fifo(fifo, stop_receiver).await {
324 if status != zx::Status::PEER_CLOSED {
325 log::error!(status:?; "FIFO error");
326 }
327 }
328 })
329 .fuse();
330
331 scopeguard::defer! {
333 for (_, registered_vmo) in session.helper.take_vmos() {
334 self.interface.on_detach_vmo(®istered_vmo.vmo);
335 }
336 }
337
338 let mut closing = false;
339 let mut stop_sender = Some(stop_sender);
340
341 loop {
342 futures::select! {
343 maybe_req = if closing {
344 futures::future::pending().left_future()
345 } else {
346 stream.next().right_future()
347 } => {
348 if let Some(req) = maybe_req {
349 match session.helper.handle_request(req?).await? {
350 HandleRequestResult::Ok => {},
351 HandleRequestResult::Closed(callback) => {
352 *session.close_callback.lock() = Some(callback);
353 if let Some(sender) = stop_sender.take() {
355 let _ = sender.send(());
356 }
357 closing = true;
358 }
359 }
360 } else {
361 if let Some(sender) = stop_sender.take() {
363 let _ = sender.send(());
364 }
365 closing = true;
366 }
367 }
368 _ = fifo_task => break,
369 }
370 }
371 Ok(())
372 }
373}
374
375pub struct Session<I: Interface + ?Sized> {
376 interface: Arc<I>,
377 helper: Arc<SessionHelper<SessionManager<I>>>,
378 close_callback: Mutex<Option<Box<dyn FnOnce() + Send + 'static>>>,
379}
380
381impl<I: Interface + ?Sized> Session<I> {
382 async fn run_fifo(
384 &self,
385 fifo: zx::Fifo<BlockFifoRequest, BlockFifoResponse>,
386 stop_signal: futures::channel::oneshot::Receiver<()>,
387 ) -> Result<(), zx::Status> {
388 scopeguard::defer! {
389 self.helper.drop_active_requests(|session| *session == self as *const _ as usize);
392 }
393
394 let mut fifo = fasync::Fifo::from_fifo(fifo);
404 let (mut reader, mut writer) = fifo.async_io();
405 let mut requests = [MaybeUninit::<BlockFifoRequest>::uninit(); FIFO_MAX_REQUESTS];
406 let active_requests = &self.helper.session_manager().active_requests;
407 let mut active_request_futures = FuturesUnordered::new();
408 let mut responses = Vec::new();
409
410 let mut map_future = pin!(Fuse::terminated());
415 let mut pending_mappings: VecDeque<DecodedRequest> = VecDeque::new();
416
417 let mut stop_signal = pin!(stop_signal.fuse());
420 let mut is_closed = false;
421
422 loop {
423 let new_requests = {
424 let pending_requests = active_request_futures.len() + responses.len();
427
428 if is_closed
429 && pending_requests == 0
430 && map_future.is_terminated()
431 && pending_mappings.is_empty()
432 {
433 return Ok(());
434 }
435
436 let count = requests.len().saturating_sub(pending_requests);
437 let mut receive_requests = pin!(if count == 0 || is_closed {
438 Fuse::terminated()
439 } else {
440 reader.read_entries(&mut requests[..count]).fuse()
441 });
442 let mut send_responses = pin!(if responses.is_empty() {
443 Fuse::terminated()
444 } else {
445 poll_fn(|cx| -> Poll<Result<(), zx::Status>> {
446 match ready!(writer.try_write(cx, &responses[..])) {
447 Ok(written) => {
448 responses.drain(..written.get());
449 Poll::Ready(Ok(()))
450 }
451 Err(status) => Poll::Ready(Err(status)),
452 }
453 })
454 .fuse()
455 });
456
457 select_biased!(
460 res = send_responses => {
461 res?;
462 0
463 },
464 response = active_request_futures.select_next_some() => {
465 responses.extend(response);
466 0
467 }
468 result = map_future => {
469 match result {
470 Ok((request, remainder, commit_decompression_buffers)) => {
471 active_request_futures.push(self.process_fifo_request(
472 request,
473 commit_decompression_buffers,
474 ));
475 if let Some(remainder) = remainder {
476 map_future.set(
477 self.map_request_or_get_response(remainder).fuse()
478 );
479 }
480 }
481 Err(response) => responses.extend(response),
482 }
483 if map_future.is_terminated() {
484 if let Some(request) = pending_mappings.pop_front() {
485 map_future.set(self.map_request_or_get_response(request).fuse());
486 }
487 }
488 0
489 }
490 _ = stop_signal => {
491 is_closed = true;
492 0
493 }
494 count = receive_requests => {
495 count?.get()
496 }
497 )
498 };
499
500 for request in &mut requests[..new_requests] {
503 match self.helper.decode_fifo_request(self as *const _ as usize, unsafe {
504 request.assume_init_mut()
505 }) {
506 Ok(DecodedRequest {
507 operation: Operation::CloseVmo, vmo, request_id, ..
508 }) => {
509 if let Some(vmo) = vmo {
510 self.interface.on_detach_vmo(vmo.as_ref());
511 }
512 responses.extend(
513 active_requests
514 .complete_and_take_response(request_id, Ok(()))
515 .map(|(_, response)| response),
516 );
517 }
518 Ok(request) => {
519 if map_future.is_terminated() {
520 map_future.set(self.map_request_or_get_response(request).fuse());
521 } else {
522 pending_mappings.push_back(request);
523 }
524 }
525 Err(None) => {}
526 Err(Some(response)) => responses.push(response),
527 }
528 }
529 }
530 }
531
532 async fn map_request_or_get_response(
533 &self,
534 request: DecodedRequest,
535 ) -> Result<(DecodedRequest, Option<DecodedRequest>, bool), Option<BlockFifoResponse>> {
536 let request_id = request.request_id;
537 self.map_request(request).await.map_err(|status| {
538 self.helper
539 .orchestrator
540 .active_requests
541 .complete_and_take_response(request_id, Err(status))
542 .map(|(_, r)| r)
543 })
544 }
545
546 async fn map_request(
549 &self,
550 mut request: DecodedRequest,
551 ) -> Result<(DecodedRequest, Option<DecodedRequest>, bool), zx::Status> {
552 let mut active_requests;
553 let active_request;
554 let mut commit_decompression_buffers = false;
555 let flags = self.interface.get_info().as_ref().device_flags();
556 if !flags.contains(DeviceFlag::BARRIER_SUPPORT)
559 && request.operation.take_write_flag(WriteFlags::PRE_BARRIER)
560 {
561 if let Some(id) = request.trace_flow_id {
562 fuchsia_trace::async_instant!(
563 fuchsia_trace::Id::from(id.get()),
564 "storage",
565 "block_server::SimulatedBarrier",
566 "request_id" => request.request_id.0
567 );
568 }
569 self.interface.flush(request.trace_flow_id).await?;
570 }
571
572 match request.operation {
574 Operation::StartDecompressedRead {
575 required_buffer_size,
576 device_block_offset,
577 block_count,
578 options,
579 } => {
580 let allocator = match self.helper.session_manager().buffer_allocator.get() {
581 Some(a) => a,
582 None => {
583 let source = BufferSource::new(fblock::MAX_DECOMPRESSED_BYTES as usize);
586 self.interface.on_attach_vmo(&source.vmo()).await?;
587 let allocator = BufferAllocator::new(
588 std::cmp::max(
589 self.helper.block_size as usize,
590 zx::system_get_page_size() as usize,
591 ),
592 source,
593 );
594 self.helper.session_manager().buffer_allocator.set(allocator).unwrap();
595 self.helper.session_manager().buffer_allocator.get().unwrap()
596 }
597 };
598
599 if required_buffer_size > fblock::MAX_DECOMPRESSED_BYTES as usize {
600 return Err(zx::Status::OUT_OF_RANGE);
601 }
602
603 let buffer = allocator.allocate_buffer(required_buffer_size).await;
604 let vmo_offset = buffer.range().start as u64;
605
606 unsafe fn remove_lifetime(buffer: Buffer<'_>) -> Buffer<'static> {
610 unsafe { std::mem::transmute(buffer) }
611 }
612
613 active_requests = self.helper.session_manager().active_requests.0.lock();
614 active_request = &mut active_requests.requests[request.request_id.0];
615
616 active_request.decompression_info.as_mut().unwrap().buffer =
619 Some(unsafe { remove_lifetime(buffer) });
620
621 request.operation = Operation::Read {
622 device_block_offset,
623 block_count,
624 _unused: 0,
625 vmo_offset,
626 options,
627 };
628 request.vmo = Some(allocator.buffer_source().vmo().clone());
629
630 commit_decompression_buffers = true;
631 }
632 Operation::ContinueDecompressedRead {
633 offset,
634 device_block_offset,
635 block_count,
636 options,
637 } => {
638 active_requests = self.helper.session_manager().active_requests.0.lock();
639 active_request = &mut active_requests.requests[request.request_id.0];
640
641 let buffer =
642 active_request.decompression_info.as_ref().unwrap().buffer.as_ref().unwrap();
643
644 if offset >= buffer.len() as u64
646 || buffer.len() as u64 - offset
647 < block_count as u64 * self.helper.block_size as u64
648 {
649 return Err(zx::Status::OUT_OF_RANGE);
650 }
651
652 request.operation = Operation::Read {
653 device_block_offset,
654 block_count,
655 _unused: 0,
656 vmo_offset: buffer.range().start as u64 + offset,
657 options,
658 };
659
660 let allocator = self.helper.session_manager().buffer_allocator.get().unwrap();
661 request.vmo = Some(allocator.buffer_source().vmo().clone());
662 }
663 _ => {
664 active_requests = self.helper.session_manager().active_requests.0.lock();
665 active_request = &mut active_requests.requests[request.request_id.0];
666 }
667 }
668
669 self.helper
673 .map_request(request, active_request)
674 .map(|(request, remainder)| (request, remainder, commit_decompression_buffers))
675 }
676
677 async fn process_fifo_request(
679 &self,
680 DecodedRequest { request_id, operation, vmo, trace_flow_id }: DecodedRequest,
681 commit_decompression_buffers: bool,
682 ) -> Option<BlockFifoResponse> {
683 let mut needs_postflush = false;
684 let result = match operation {
685 Operation::Read { device_block_offset, block_count, _unused, vmo_offset, options } => {
686 join(
687 self.interface.read(
688 device_block_offset,
689 block_count,
690 vmo.as_ref().unwrap(),
691 vmo_offset,
692 options,
693 trace_flow_id,
694 ),
695 async {
696 if commit_decompression_buffers {
697 let (target_slice, buffer_slice, buffer_range) = {
698 let active_request = self
699 .helper
700 .session_manager()
701 .active_requests
702 .request(request_id);
703 let info = active_request.decompression_info.as_ref().unwrap();
704 (
705 info.uncompressed_slice(),
706 self.helper
707 .orchestrator
708 .buffer_allocator
709 .get()
710 .unwrap()
711 .buffer_source()
712 .slice(),
713 info.buffer.as_ref().unwrap().range(),
714 )
715 };
716 let vmar = fuchsia_runtime::vmar_root_self();
717 let addr = target_slice.addr();
719 let unaligned = addr % zx::system_get_page_size() as usize;
720 if let Err(error) = vmar.op_range(
721 zx::VmarOp::COMMIT,
722 addr - unaligned,
723 target_slice.len() + unaligned,
724 ) {
725 log::warn!(error:?; "Unable to commit target range");
726 }
727 if let Err(error) = vmar.op_range(
729 zx::VmarOp::PREFETCH,
730 buffer_slice.addr() + buffer_range.start,
731 buffer_range.len(),
732 ) {
733 log::warn!(
734 error:?,
735 buffer_range:?;
736 "Unable to prefetch source range",
737 );
738 }
739 }
740 },
741 )
742 .await
743 .0
744 }
745 Operation::Write {
746 device_block_offset,
747 block_count,
748 _unused,
749 vmo_offset,
750 mut options,
751 } => {
752 if options.flags.contains(WriteFlags::FORCE_ACCESS) {
755 let flags = self.interface.get_info().as_ref().device_flags();
756 if !flags.contains(DeviceFlag::FUA_SUPPORT) {
757 options.flags.remove(WriteFlags::FORCE_ACCESS);
758 needs_postflush = true;
759 }
760 }
761 self.interface
762 .write(
763 device_block_offset,
764 block_count,
765 vmo.as_ref().unwrap(),
766 vmo_offset,
767 options,
768 trace_flow_id,
769 )
770 .await
771 }
772 Operation::Flush => self.interface.flush(trace_flow_id).await,
773 Operation::Trim { device_block_offset, block_count } => {
774 self.interface.trim(device_block_offset, block_count, trace_flow_id).await
775 }
776 Operation::CloseVmo
777 | Operation::StartDecompressedRead { .. }
778 | Operation::ContinueDecompressedRead { .. } => {
779 unreachable!()
781 }
782 };
783 let response = self
784 .helper
785 .orchestrator
786 .active_requests
787 .complete_and_take_response(request_id, result)
788 .map(|(_, r)| r);
789 if let Some(mut response) = response {
790 if zx::Status::ok(response.status).is_ok() && needs_postflush {
792 if let Some(id) = trace_flow_id {
793 fuchsia_trace::async_instant!(
794 fuchsia_trace::Id::from(id.get()),
795 "storage",
796 "block_server::SimulatedFUA",
797 "request_id" => request_id.0
798 );
799 }
800 response.status =
801 zx::Status::result_into_raw(self.interface.flush(trace_flow_id).await);
802 }
803 Some(response)
804 } else {
805 response
806 }
807 }
808}
809
810impl<I: Interface + ?Sized> super::SessionManager for SessionManager<I> {
811 type Orchestrator = Self;
812
813 const SUPPORTS_DECOMPRESSION: bool = true;
814
815 type Session = usize;
817
818 fn session_eq(a: &usize, b: &usize) -> bool {
819 a == b
820 }
821
822 async fn on_attach_vmo(orchestrator: Arc<Self>, vmo: &Arc<zx::Vmo>) -> Result<(), zx::Status> {
823 I::on_attach_vmo(&orchestrator.interface, vmo).await
824 }
825
826 async fn open_session(
827 orchestrator: Arc<Self>,
828 stream: fblock::SessionRequestStream,
829 offset_map: OffsetMap,
830 block_size: u32,
831 ) -> Result<(), Error> {
832 I::open_session(
833 &orchestrator.interface,
834 orchestrator.clone(),
835 stream,
836 offset_map,
837 block_size,
838 )
839 .await
840 }
841
842 fn get_info(&self) -> Cow<'_, DeviceInfo> {
843 self.interface.get_info()
844 }
845
846 async fn get_volume_info(
847 &self,
848 ) -> Result<(fblock::VolumeManagerInfo, fblock::VolumeInfo), zx::Status> {
849 self.interface.get_volume_info().await
850 }
851
852 async fn query_slices(
853 &self,
854 start_slices: &[u64],
855 ) -> Result<Vec<fblock::VsliceRange>, zx::Status> {
856 self.interface.query_slices(start_slices).await
857 }
858
859 async fn extend(&self, start_slice: u64, slice_count: u64) -> Result<(), zx::Status> {
860 self.interface.extend(start_slice, slice_count).await
861 }
862
863 async fn shrink(&self, start_slice: u64, slice_count: u64) -> Result<(), zx::Status> {
864 self.interface.shrink(start_slice, slice_count).await
865 }
866
867 fn open_mapper_session(
868 orchestrator: Arc<Self>,
869 session: fidl::endpoints::ServerEnd<fblock::MapperSessionMarker>,
870 mapping_vmo: zx::Vmo,
871 block_size: u32,
872 port: Option<zx::Port>,
873 delivery_queue: Option<zx::Vmo>,
874 ) -> Result<impl Future<Output = Result<(), Error>> + Send, zx::Status> {
875 I::open_mapper_session(orchestrator, session, mapping_vmo, block_size, port, delivery_queue)
876 }
877
878 fn active_requests(&self) -> &ActiveRequests<Self::Session> {
879 return &self.active_requests;
880 }
881
882 fn key_registry(&self) -> &KeyRegistry {
883 &self.key_registry
884 }
885}
886
887impl<I: Interface + ?Sized> Drop for Session<I> {
888 fn drop(&mut self) {
889 let callback = std::mem::take(&mut *self.close_callback.lock());
890 if let Some(callback) = callback {
891 callback();
892 }
893 }
894}
895
896impl<I: Interface> IntoOrchestrator for Arc<I> {
897 type SM = SessionManager<I>;
898
899 fn into_orchestrator(self) -> Arc<Self::SM> {
900 Arc::new(SessionManager::new(self))
901 }
902}
903
904pub struct AsyncBlockService<I: Interface + ?Sized> {
908 interface: Arc<I>,
909 allocator: Arc<BufferAllocator>,
910 block_size: u32,
911 max_transfer_bytes: usize,
912 scope: fasync::ScopeHandle,
913}
914
915impl<I: Interface + ?Sized> AsyncBlockService<I> {
916 pub async fn new(
917 interface: Arc<I>,
918 block_size: u32,
919 pool_capacity: usize,
920 scope: fasync::ScopeHandle,
921 ) -> Result<Self, zx::Status> {
922 let source = BufferSource::new(pool_capacity);
923 interface.on_attach_vmo(&source.vmo()).await?;
924 let allocator = Arc::new(BufferAllocator::new(
925 std::cmp::max(block_size as usize, zx::system_get_page_size() as usize),
926 source,
927 ));
928 Ok(Self::new_with_allocator(interface, block_size, allocator, scope))
929 }
930
931 pub fn new_with_allocator(
932 interface: Arc<I>,
933 block_size: u32,
934 allocator: Arc<BufferAllocator>,
935 scope: fasync::ScopeHandle,
936 ) -> Self {
937 let max_transfer_bytes = interface
938 .get_info()
939 .max_transfer_blocks()
940 .map(|blocks| {
941 let bytes = (blocks.get() as usize).saturating_mul(block_size as usize);
942 std::cmp::max(
943 bytes & !(mapping::BLOCK_SIZE as usize - 1),
944 mapping::BLOCK_SIZE as usize,
945 )
946 })
947 .unwrap_or(MAX_READ_BUFFER_SIZE);
948 Self { interface, allocator, block_size, max_transfer_bytes, scope }
949 }
950
951 pub fn interface(&self) -> &Arc<I> {
952 &self.interface
953 }
954
955 pub fn allocator(&self) -> &Arc<BufferAllocator> {
956 &self.allocator
957 }
958}
959
960impl<I: Interface + ?Sized> BlockService for AsyncBlockService<I> {
961 fn allocate_buffer(&self, max_len: usize) -> OwnedBuffer {
962 let max_len = max_len
963 .min(MAX_READ_BUFFER_SIZE)
964 .min(self.max_transfer_bytes)
965 .min(self.allocator.buffer_source().size());
966 self.allocator.allocate_buffer_sync_owned(max_len)
967 }
968
969 fn read_blocks(
970 &self,
971 device_offset: u64,
972 dest_buffer: OwnedBuffer,
973 on_complete: Box<dyn FnOnce(Result<OwnedBuffer, Error>) + Send>,
974 ) -> Result<(), Error> {
975 let block_size = self.block_size as u64;
976 let device_block_offset = device_offset / block_size;
977 let block_count = (dest_buffer.len() as u64 / block_size) as u32;
978
979 let vmo_offset = dest_buffer.range().start as u64;
980 let vmo = self.allocator.buffer_source().vmo().clone();
981 let interface = self.interface.clone();
982
983 self.scope.spawn(async move {
984 let res = interface
985 .read(
986 device_block_offset,
987 block_count,
988 &vmo,
989 vmo_offset,
990 ReadOptions::default(),
991 TraceFlowId::default(),
992 )
993 .await;
994 match res {
995 Ok(()) => on_complete(Ok(dest_buffer)),
996 Err(status) => on_complete(Err(anyhow::anyhow!("Read failed: {:?}", status))),
997 }
998 });
999
1000 Ok(())
1001 }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006 use super::*;
1007 use crate::BlockServer;
1008 use fuchsia_async as fasync;
1009 use mapping::Extents;
1010 use mapping::reader::read_aligned_range;
1011 use std::sync::atomic::{AtomicU64, Ordering};
1012
1013 struct FakeInterface {
1014 data: Vec<u8>,
1015 block_size: u32,
1016 read_count: AtomicU64,
1017 }
1018
1019 impl FakeInterface {
1020 fn new(data: Vec<u8>, block_size: u32) -> Self {
1021 Self { data, block_size, read_count: AtomicU64::new(0) }
1022 }
1023 }
1024
1025 impl Interface for FakeInterface {
1026 fn on_open_mapper_session(
1027 &self,
1028 _mapping_vmo: &zx::Vmo,
1029 delivery_queue: zx::Vmo,
1030 ) -> Result<Verifier, zx::Status> {
1031 Ok(Verifier::new(delivery_queue))
1032 }
1033
1034 fn get_info(&self) -> Cow<'_, DeviceInfo> {
1035 Cow::Owned(DeviceInfo::Block(crate::BlockInfo {
1036 block_count: (self.data.len() / self.block_size as usize) as u64,
1037 max_transfer_blocks: None,
1038 device_flags: fblock::DeviceFlag::empty(),
1039 }))
1040 }
1041
1042 async fn read(
1043 &self,
1044 device_block_offset: u64,
1045 block_count: u32,
1046 vmo: &Arc<zx::Vmo>,
1047 vmo_offset: u64,
1048 _opts: ReadOptions,
1049 _trace_flow_id: TraceFlowId,
1050 ) -> Result<(), zx::Status> {
1051 self.read_count.fetch_add(1, Ordering::Relaxed);
1052 let byte_offset = (device_block_offset * self.block_size as u64) as usize;
1053 let byte_len = (block_count * self.block_size) as usize;
1054 let slice = &self.data[byte_offset..byte_offset + byte_len];
1055 vmo.write(slice, vmo_offset).map_err(|_| zx::Status::IO)?;
1056 Ok(())
1057 }
1058
1059 async fn write(
1060 &self,
1061 _device_block_offset: u64,
1062 _block_count: u32,
1063 _vmo: &Arc<zx::Vmo>,
1064 _vmo_offset: u64,
1065 _opts: WriteOptions,
1066 _trace_flow_id: TraceFlowId,
1067 ) -> Result<(), zx::Status> {
1068 Ok(())
1069 }
1070
1071 async fn flush(&self, _trace_flow_id: TraceFlowId) -> Result<(), zx::Status> {
1072 Ok(())
1073 }
1074
1075 async fn trim(
1076 &self,
1077 _device_block_offset: u64,
1078 _block_count: u32,
1079 _trace_flow_id: TraceFlowId,
1080 ) -> Result<(), zx::Status> {
1081 Ok(())
1082 }
1083 }
1084
1085 #[fasync::run_singlethreaded(test)]
1086 async fn test_async_block_service_read_aligned_range() {
1087 let block_size = 512;
1088 let test_data: Vec<u8> = (0..8192).map(|i| (i % 255) as u8).collect();
1089 let interface = Arc::new(FakeInterface::new(test_data.clone(), block_size));
1090 let scope = fasync::Scope::current();
1091
1092 let block_service = Arc::new(
1093 AsyncBlockService::new(interface, block_size, 16384, scope)
1094 .await
1095 .expect("Failed to create AsyncBlockService"),
1096 );
1097
1098 let encoded = (1u64 << 32) | 0u64;
1099 let extents = Extents::from_encoded([encoded], 0).unwrap();
1100 let service = block_service.clone();
1101 let (send, recv) = futures::channel::oneshot::channel();
1102 let send = std::sync::Mutex::new(Some(send));
1103 let read_buf = std::sync::Mutex::new(Vec::new());
1104
1105 read_aligned_range(&extents, 0..4096, &*service, move |buffer_result| {
1106 let buffer = buffer_result.unwrap();
1107 let mut read_guard = read_buf.lock().unwrap();
1108 buffer.as_ptr_slice().append_to(&mut read_guard);
1109 if read_guard.len() == 4096 {
1110 if let Some(s) = send.lock().unwrap().take() {
1111 let _ = s.send(read_guard.clone());
1112 }
1113 }
1114 std::ops::ControlFlow::Continue(())
1115 });
1116
1117 let result = recv.await.unwrap();
1118 assert_eq!(result, &test_data[0..4096]);
1119 }
1120
1121 #[fasync::run_singlethreaded(test)]
1122 async fn test_async_block_service_concurrent_reads_larger_than_pool_capacity() {
1123 let block_size = 512;
1124 let total_size = 65536; let test_data: Vec<u8> = (0..total_size).map(|i| (i % 251) as u8).collect();
1126 let interface = Arc::new(FakeInterface::new(test_data.clone(), block_size));
1127 let scope = fasync::Scope::current();
1128
1129 let pool_capacity = 8192;
1132 let source = BufferSource::new(pool_capacity);
1133 interface.on_attach_vmo(&source.vmo()).await.unwrap();
1134 let allocator = Arc::new(BufferAllocator::new(
1135 std::cmp::max(block_size as usize, zx::system_get_page_size() as usize),
1136 source,
1137 ));
1138 let block_service = Arc::new(AsyncBlockService::new_with_allocator(
1139 interface, block_size, allocator, scope,
1140 ));
1141
1142 let encoded = (16u64 << 32) | 0u64;
1143 let extents = Arc::new(Extents::from_encoded([encoded], 0).unwrap());
1144
1145 let ranges = [0..16384, 16384..32768, 32768..49152, 49152..65536];
1147 let mut receivers = Vec::new();
1148
1149 for range in ranges {
1150 let (send, recv) = futures::channel::oneshot::channel();
1151 let service = block_service.clone();
1152 let extents = extents.clone();
1153
1154 std::thread::spawn(move || {
1155 let send = std::sync::Mutex::new(Some(send));
1156 let read_buf = std::sync::Mutex::new(Vec::new());
1157 let target_len = (range.end - range.start) as usize;
1158
1159 read_aligned_range(&extents, range, &*service, move |buffer_result| {
1160 let buffer = buffer_result.unwrap();
1161 let mut read_guard = read_buf.lock().unwrap();
1162 buffer.as_ptr_slice().append_to(&mut read_guard);
1163 if read_guard.len() == target_len {
1164 if let Some(s) = send.lock().unwrap().take() {
1165 let _ = s.send(read_guard.clone());
1166 }
1167 }
1168 std::ops::ControlFlow::Continue(())
1169 });
1170 });
1171
1172 receivers.push(recv);
1173 }
1174
1175 let results = futures::future::join_all(receivers).await;
1176 for (i, res) in results.into_iter().enumerate() {
1177 let data = res.unwrap();
1178 let start = i * 16384;
1179 let end = start + 16384;
1180 assert_eq!(data, &test_data[start..end]);
1181 }
1182 }
1183
1184 #[fuchsia::test]
1185 async fn test_async_interface_mapper_hierarchical_session() {
1186 use assert_matches::assert_matches;
1187
1188 let block_size = 512;
1189 let test_data = vec![0xCDu8; 8192];
1190 let interface = Arc::new(FakeInterface::new(test_data.clone(), block_size));
1191 let block_server = BlockServer::new(block_size, interface.clone());
1192
1193 let (mapper_proxy, mapper_stream) =
1194 fidl::endpoints::create_proxy_and_stream::<fblock::MapperMarker>();
1195 let scope = fasync::Scope::new();
1196 scope.spawn(async move {
1197 let _ = block_server.handle_mapper_requests(mapper_stream).await;
1198 });
1199
1200 let (root_session_proxy, root_session_server) =
1202 fidl::endpoints::create_proxy::<fblock::MapperSessionMarker>();
1203 let root_mapping_vmo = zx::Vmo::create(65536).unwrap();
1204
1205 let partition_key = 500u64;
1206 let extents =
1207 mapping::Extents::try_new([mapping::Extent::new(0..4096, Some(4096))], 0).unwrap();
1208 let partition_extents: Vec<u64> = mapping::Extents::encode_extents(&extents).collect();
1209 let mut payload_bytes = Vec::new();
1210 for w in &partition_extents {
1211 payload_bytes.extend_from_slice(&w.to_le_bytes());
1212 }
1213 let cmd = mapping::RawMappingCommand {
1214 opcode: mapping::MAPPINGS_COMMAND,
1215 offset: 0,
1216 key: partition_key,
1217 stored_size: 4096,
1218 device_offset: 0,
1219 metadata_count: 0,
1220 extent_count: partition_extents.len() as u32,
1221 };
1222 let mut sender = vmo_fifo::SyncSender::<mapping::RawMappingCommand>::new(
1223 root_mapping_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1224 1024,
1225 256,
1226 )
1227 .unwrap();
1228 let mut payload_buf = sender.reserve_payload(payload_bytes.len()).unwrap();
1229 payload_buf.data().copy_from_slice(&payload_bytes);
1230 payload_buf.commit(cmd).unwrap();
1231
1232 let res = mapper_proxy
1233 .open_session(root_session_server, root_mapping_vmo, None, None)
1234 .await
1235 .unwrap();
1236 assert_matches!(res, Ok(()));
1237
1238 let pager = Arc::new(zx::Pager::create(zx::PagerOptions::empty()).unwrap());
1240 let port = zx::Port::create();
1241 let child_key = 2002u64;
1242 let paged_vmo = pager.create_vmo(zx::VmoOptions::empty(), &port, child_key, 4096).unwrap();
1243
1244 let child_mapping_vmo = zx::Vmo::create(65536).unwrap();
1245 let delivery_queue = zx::Vmo::create(65536).unwrap();
1246 let vmo_provider = Arc::new(blob_pager_and_verifier::TestVmoProvider::new(
1247 pager.clone(),
1248 delivery_queue.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1249 ));
1250 vmo_provider
1251 .register_vmo(child_key, paged_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap());
1252 let receiver = vmo_fifo::Receiver::<mapping::RawDeliveryCommand>::new(
1253 delivery_queue.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1254 mapping::PENDING_DELIVERY_COMMANDS_CAPACITY,
1255 )
1256 .unwrap();
1257 let _delivery_processor = blob_pager_and_verifier::DeliveryQueueProcessor::spawn(
1258 receiver,
1259 vmo_provider,
1260 delivery_queue.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1261 )
1262 .unwrap();
1263
1264 let extents =
1265 mapping::Extents::try_new([mapping::Extent::new(0..4096, Some(0))], 0).unwrap();
1266 let child_extents: Vec<u64> = mapping::Extents::encode_extents(&extents).collect();
1267 let mut child_payload_bytes = Vec::new();
1268 for w in &child_extents {
1269 child_payload_bytes.extend_from_slice(&w.to_le_bytes());
1270 }
1271 let child_cmd = mapping::RawMappingCommand {
1272 opcode: mapping::MAPPINGS_COMMAND,
1273 offset: 0,
1274 key: child_key,
1275 stored_size: 4096,
1276 device_offset: 0,
1277 metadata_count: 0,
1278 extent_count: child_extents.len() as u32,
1279 };
1280 let mut child_sender = vmo_fifo::SyncSender::<mapping::RawMappingCommand>::new(
1281 child_mapping_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1282 1024,
1283 256,
1284 )
1285 .unwrap();
1286 let mut child_payload_buf =
1287 child_sender.reserve_payload(child_payload_bytes.len()).unwrap();
1288 child_payload_buf.data().copy_from_slice(&child_payload_bytes);
1289 child_payload_buf.commit(child_cmd).unwrap();
1290
1291 let mut child_session = None;
1292 for _ in 0..100 {
1293 let (child_session_proxy, child_session_server) =
1294 fidl::endpoints::create_proxy::<fblock::MapperSessionMarker>();
1295 let child_res_raw = root_session_proxy
1296 .open_child_session(
1297 child_session_server,
1298 child_mapping_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1299 partition_key,
1300 Some(port.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap()),
1301 Some(delivery_queue.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap()),
1302 )
1303 .await
1304 .unwrap();
1305 if child_res_raw.is_ok() {
1306 child_session = Some(child_session_proxy);
1307 break;
1308 }
1309 fasync::Timer::new(std::time::Duration::from_millis(10)).await;
1310 }
1311 assert!(child_session.is_some());
1312
1313 let (tx, rx) = futures::channel::oneshot::channel();
1314 std::thread::spawn(move || {
1315 let mut buf = [0u8; 4096];
1316 paged_vmo.read(&mut buf, 0).expect("paged vmo read failed");
1317 let _ = tx.send(buf);
1318 });
1319
1320 let read_bytes = rx.await.unwrap();
1321 assert_eq!(read_bytes.len(), 4096);
1322 assert_eq!(read_bytes, &test_data[4096..8192]);
1323 }
1324
1325 #[fuchsia::test]
1326 async fn test_async_interface_mapper_child_session_closed_when_parent_closed() {
1327 use assert_matches::assert_matches;
1328 use fidl::endpoints::Proxy as _;
1329
1330 let block_size = 512;
1331 let test_data = vec![0u8; 8192];
1332 let interface = Arc::new(FakeInterface::new(test_data, block_size));
1333 let block_server = BlockServer::new(block_size, interface.clone());
1334
1335 let (mapper_proxy, mapper_stream) =
1336 fidl::endpoints::create_proxy_and_stream::<fblock::MapperMarker>();
1337 let scope = fasync::Scope::new();
1338 scope.spawn(async move {
1339 let _ = block_server.handle_mapper_requests(mapper_stream).await;
1340 });
1341
1342 let (root_session_proxy, root_session_server) =
1343 fidl::endpoints::create_proxy::<fblock::MapperSessionMarker>();
1344 let root_mapping_vmo = zx::Vmo::create(65536).unwrap();
1345
1346 let partition_key = 500u64;
1347 let extents =
1348 mapping::Extents::try_new([mapping::Extent::new(0..4096, Some(4096))], 0).unwrap();
1349 let partition_extents: Vec<u64> = mapping::Extents::encode_extents(&extents).collect();
1350 let mut payload_bytes = Vec::new();
1351 for w in &partition_extents {
1352 payload_bytes.extend_from_slice(&w.to_le_bytes());
1353 }
1354 let cmd = mapping::RawMappingCommand {
1355 opcode: mapping::MAPPINGS_COMMAND,
1356 offset: 0,
1357 key: partition_key,
1358 stored_size: 4096,
1359 device_offset: 0,
1360 metadata_count: 0,
1361 extent_count: partition_extents.len() as u32,
1362 };
1363 let mut sender = vmo_fifo::SyncSender::<mapping::RawMappingCommand>::new(
1364 root_mapping_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1365 1024,
1366 256,
1367 )
1368 .unwrap();
1369 let mut payload_buf = sender.reserve_payload(payload_bytes.len()).unwrap();
1370 payload_buf.data().copy_from_slice(&payload_bytes);
1371 payload_buf.commit(cmd).unwrap();
1372
1373 let res = mapper_proxy
1374 .open_session(root_session_server, root_mapping_vmo, None, None)
1375 .await
1376 .unwrap();
1377 assert_matches!(res, Ok(()));
1378
1379 let child_mapping_vmo = zx::Vmo::create(65536).unwrap();
1380 let mut child_session = None;
1381 for _ in 0..100 {
1382 let (child_session_proxy, child_session_server) =
1383 fidl::endpoints::create_proxy::<fblock::MapperSessionMarker>();
1384 let child_res_raw = root_session_proxy
1385 .open_child_session(
1386 child_session_server,
1387 child_mapping_vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap(),
1388 partition_key,
1389 None,
1390 None,
1391 )
1392 .await
1393 .unwrap();
1394 if child_res_raw.is_ok() {
1395 child_session = Some(child_session_proxy);
1396 break;
1397 }
1398 fasync::Timer::new(std::time::Duration::from_millis(10)).await;
1399 }
1400 let child_session_proxy = child_session.expect("Failed to open child session");
1401
1402 root_session_proxy.close().await.unwrap().expect("Close parent session failed");
1403 child_session_proxy.on_closed().await.unwrap();
1404 }
1405}