Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix FIXME's introduced by PR#1072 #1074

Open
mulkieran opened this issue Jul 30, 2018 · 10 comments
Open

Fix FIXME's introduced by PR#1072 #1074

mulkieran opened this issue Jul 30, 2018 · 10 comments
Assignees

Comments

@mulkieran
Copy link
Member

#1072 introduced two very similar fixme. We should fix that before some other code does the same thing.

@agrover
Copy link
Contributor

agrover commented Jul 30, 2018

// FIXME: To avoid this expect, modify create_filesystem
// so that it returns a mutable reference to the
// filesystem created.
// FIXME: To avoid this expect, modify add_blockdevs
// so that it returns a mutable reference to each
// blockdev created.

@agrover agrover added this to the Stratis 1.1 milestone Sep 24, 2018
@mulkieran mulkieran self-assigned this Oct 4, 2018
@mulkieran
Copy link
Member Author

I took a stab at the filesystem's one and that turns out to require some thought. It's impossible to implement it in StratPool::create_filesystems unless ThinPool::create_filesystems is changed so that its signature matches that of StratPool::create_filesystems. Otherwise, the thinpool is mutably borrowed multiple times, which we all know is bad. The mutable borrow would be safe in this case, because all we're getting is one filesystem after the other. But the compiler doesn't know that, so we need to do something to help it out.

Another way might be to get all the component filesystems mutably and look them up by name, but the first idea is probably the better.

@mulkieran
Copy link
Member Author

This has drifted too far down my stack, I don't expect I'll get back to it before January.

@tasleson
Copy link
Contributor

The filesystem is ultimately inserted into a hashmap buried inside the Table . When you get a mutable reference to the filesystem from the hash there will always be an expect if we know that the item exists. Therefore the expect won't really go away in the dbus call, it's just moved somewhere else right?

@mulkieran mulkieran assigned jbaublitz and unassigned mulkieran Sep 23, 2019
@mulkieran mulkieran removed this from the Stratis 1.1 milestone Sep 23, 2019
@mulkieran
Copy link
Member Author

@jbaublitz This is a puzzle problem, and not really urgent. If it conflicts w/ #1614, please mark it as blocked and leave it alone for now.

@jbaublitz
Copy link
Member

Blocked by stratis-storage/project#51 or more specifically the PR #1614.

@jbaublitz
Copy link
Member

Therefore the expect won't really go away in the dbus call, it's just moved somewhere else right?

I have looked into this a bit and I think I agree with this claim. Modifying the API for blockdevs to return a mutable reference has the same problem as filesystems apparently has. We can get a mutable reference from the newly created blockdevs, but once we have to transfer ownership to self.cache_devs or self.block_devs in the .add_blockdevs() method, we will run into using moved values errors from the borrow checker. We could do the same thing and reacquire mutable references to each of the blockdevs we've inserted, but as stated above, we will end up calling expect on the get operations on the HashMaps as we know for certain that these already exist. We have a few options here:

  1. Move the expect into the engine.
  2. Return an error if the UUID does not correspond to a blockdev struct, a code path which will never be reached.
  3. Filter out any UUID that does not correspond to a blockdev which feels error prone and could potentially cause some nasty bugs down the line if something changes (I would not recommend this).

@mulkieran What are your thoughts?

@mulkieran mulkieran removed the blocked label Oct 15, 2019
@mulkieran
Copy link
Member Author

Going to struggle with this one more time in December. Maybe I was thinking of using Entry?

@jbaublitz
Copy link
Member

Maybe there is a way to do it with Entry after all! I looked into this API and it looks very promising. I'm happy to remain the owner of this issue and try it again with that additional information. Thank you for the pointer.

Three things to consider:

  • Once we introduce threading down the road, if we lock at the pool level only, this should continue to work without any intervention. If we do more granular locking, the Entry approach will cease to work and we'll have to replace it with an Arc. This is not necessarily a good thing or a bad thing but something worth consideration. We may even want to address this issue at the same time as multithreading if we go with more granular locking.
  • I would like to evaluate the code in a little more depth to ensure that we are never going to bump into an issue where we call create_filesystems with a filesystem name that already exists. If we ever reach create_filesystems with a duplicate name, insert_or() will just return a mutable reference to the existing filesystem and we would never have any indication. If we are able to pass duplicates, we will need to do checks beforehand to make sure that this never occurs in create_filesystems. If it cannot occur, I'd like to add a comment specifying the precondition.
  • I think it would make sense that if we go with the Entry approach, we should modify Table, the structure causing the problem with ownership, to support a new method that will insert and give us back a mutable reference.

How does this all sound?

@jbaublitz
Copy link
Member

@mulkieran Transferring to you. I think I was a little overeager about this potentially working. I've done some digging and the Entry API gives different errors from the previous approach but still lifetime errors. Ultimately it seems to come down to this:

  • .entry() creates an Entry struct
  • Entry::or_insert() returns a mutable reference with a lifetime bound to the lifetime of the Entry struct the method was called on
  • If we return the mutable reference up the stack, the Entry struct goes out of scope which violates the rules of the borrow checker

I may be missing something but I don't think there's any more I can do on this issue. Let me know if you find a way to get it working.

@jbaublitz jbaublitz removed their assignment Nov 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants