gpt_component/
partitions_directory.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::gpt::GptManager;
6use block_server::{BlockServer, SessionManager};
7use fuchsia_sync::Mutex;
8use std::collections::BTreeMap;
9use std::sync::{Arc, Weak};
10use vfs::directory::helper::DirectlyMutable as _;
11
12/// A directory of instances of the fuchsia.storage.partitions.PartitionService service.
13pub struct PartitionsDirectory {
14    node: Arc<vfs::directory::immutable::Simple>,
15    entries: Mutex<BTreeMap<String, PartitionsDirectoryEntry>>,
16}
17
18impl std::fmt::Debug for PartitionsDirectory {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
20        f.debug_struct("PartitionDirectory").field("entries", &self.entries).finish()
21    }
22}
23
24impl PartitionsDirectory {
25    pub fn new(node: Arc<vfs::directory::immutable::Simple>) -> Self {
26        Self { node, entries: Default::default() }
27    }
28
29    pub fn clear(&self) {
30        self.node.remove_all_entries();
31        self.entries.lock().clear();
32    }
33
34    pub fn add_entry<SM: SessionManager + Send + Sync + 'static>(
35        &self,
36        name: &str,
37        block_server: Weak<BlockServer<SM>>,
38        gpt_manager: Weak<GptManager>,
39        gpt_index: usize,
40    ) {
41        let entry = PartitionsDirectoryEntry::new(block_server, gpt_manager, gpt_index);
42        self.node.add_entry(name, entry.node.clone()).expect("Added an entry twice");
43        self.entries.lock().insert(name.to_string(), entry);
44    }
45}
46
47/// A node which hosts an instance of fuchsia.storage.partitions.PartitionService.
48pub struct PartitionsDirectoryEntry {
49    node: Arc<vfs::directory::immutable::Simple>,
50}
51
52impl std::fmt::Debug for PartitionsDirectoryEntry {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
54        f.debug_struct("PartitionDirectoryEntry").finish()
55    }
56}
57
58impl PartitionsDirectoryEntry {
59    pub fn new<SM: SessionManager + Send + Sync + 'static>(
60        block_server: Weak<BlockServer<SM>>,
61        gpt_manager: Weak<GptManager>,
62        gpt_index: usize,
63    ) -> Self {
64        let node = vfs::directory::immutable::simple();
65        node.add_entry(
66            "volume",
67            vfs::service::host(move |requests| {
68                let server = block_server.clone();
69                async move {
70                    if let Some(server) = server.upgrade() {
71                        if let Err(err) = server.handle_requests(requests).await {
72                            log::error!(err:?; "Error handling requests");
73                        }
74                    }
75                }
76            }),
77        )
78        .unwrap();
79        node.add_entry(
80            "partition",
81            vfs::service::host(move |requests| {
82                let manager = gpt_manager.clone();
83                async move {
84                    if let Some(manager) = manager.upgrade() {
85                        if let Err(err) =
86                            manager.handle_partitions_requests(gpt_index, requests).await
87                        {
88                            log::error!(err:?; "Error handling requests");
89                        }
90                    }
91                }
92            }),
93        )
94        .unwrap();
95
96        Self { node }
97    }
98}