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