1

I'm working on a fuse filesystem using fuse_mt. In the process, I'm implementing a method of the FileSystemMT trait that looks like this:

    fn opendir(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpen {
        Err(libc::ENOSYS)
    }

opendir is supposed to return a unique handle that identifies the directory.

In my implementation, I wanted to maintain a HashMap of directory handles that I can return when opendir is called. I have the following struct:

pub struct RtFS {
  pub rt: Box<Artifactory>,
  pub repo: String,
  _dir_handles: HashMap<u64, String>,
  _last_dir_handle: u64,
  _last_file_handle: u64,
}

My plan was to initialize _last_dir_handle with a random value, then increment it for each opendir call. Then, I would store each allocated handle in the _dir_handles HashMap. This is where I ran into a problem. If I attempt to do this in the opendir function:

        self._last_dir_handle += 1;
        self._dir_handles.insert(
          self._last_dir_handle,
          path.to_str().expect("Could not convert path").to_string(),
        );

then the borrow checker will (unsurprisingly) complain:

error[E0594]: cannot assign to `self._last_dir_handle` which is behind a `&` reference                                                  │
   --> src/rtfs.rs:117:7                                                                                                                │
    |                                                                                                                                   │
110 |   fn opendir(&self, _req: RequestInfo, path: &Path, _flags: u32) -> ResultOpen {                                                  │
    |              ----- help: consider changing this to be a mutable reference: `&mut self`                                            │
...                                                                                                                                     │
117 |       self._last_dir_handle += 1;                                                                                                 │
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written                            │
                                                                                                                                        │
error[E0596]: cannot borrow `self._dir_handles` as mutable, as it is behind a `&` reference                                             │
   --> src/rtfs.rs:118:7                                                                                                                │
    |                                                                                                                                   │
110 |   fn opendir(&self, _req: RequestInfo, path: &Path, _flags: u32) -> ResultOpen {                                                  │
    |              ----- help: consider changing this to be a mutable reference: `&mut self`                                            │
...                                                                                                                                     │
118 |       self._dir_handles.insert(                                                                                                   │
    |       ^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Adding mut like the message suggests is not a solution because then the function won't match the trait. How can I solve this? I considered moving the state to the module level, but theoretically there could be more instances and I don't want them to clash.

Tamás Szelei
  • 23,169
  • 18
  • 105
  • 180
  • In short, use "interior mutability'": `std::cell::RefCell`. – edwardw Dec 31 '19 at 13:37
  • If using RefCell is the answer, I'd appreciate a complete example of using it (and explaining why Cell isn't the right choice). I feel like the proposed duplicate is far more generic than this question and as a Rust beginner I have trouble applying those answers to my case. – Tamás Szelei Dec 31 '19 at 14:10
  • 1
    `_dir_handles` should be `RefCell>`, `_last_dir_handle`should be `Call`. `Cell` is for value (Copy) types, `RefCell` reference types (not `Copy`). – CoronA Dec 31 '19 at 14:21

0 Answers0