-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Ensure that flush on the mfs root flushes its directory #4509
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
d9058e0
to
4895033
Compare
We may want to add some general sharness tests for stuff like this. That is, upload a file, directory, large, large, small, etc. in one subprocess and repeatedly check memory usage in the other (and see if it goes above some high watermark). Unfortunately, tests like this tend to be flaky (but we could probably set the watermark high enough to avoid false positives). |
Nevermind. I can't read. |
mfs/dir.go
Outdated
return d.getNode(false) | ||
} | ||
|
||
func (d *Directory) getNode(clear bool) (node.Node, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There has to be a cleaner way to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i'm thinking about it. Its pretty obnoxious right now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That cross my mind also, but I didn't find it objectionable enough to comment. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes LGTM, but I don't understand the code enough to be sure the change is doing what it is suppose to.
So, while this fixes the memory leak problem, it does bring up another interesting issue. We have the potential for someone to hold a stale reference to a directory, after it has been removed. |
One thing we could do for now is have a different call that we only use in the add code since we know we won't run into any of these stale reference problems. |
4895033
to
7616a59
Compare
There... thats a slightly better solution that doesnt introduce weirdness around the directory references. In any case though, the mfs directory thing needs work. Otherwise any use of mfs will not clear out its cache. |
7616a59
to
3bab073
Compare
// them to be garbage collected. | ||
// CAUTION: Take care not to ever call this while holding a reference to any | ||
// child directories. Those directories will be bad references and using them | ||
// may have unintended racy side effects. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly do you mean here? How will removing these from the map lead to race conditions?
I think what's throwing me is the term "cache". Is it a write cache? A read cache?
Answered offline. Basically, we could have open file descriptors and we'll lose updates to these files if we remove the references to them from the cache.
mfs/system.go
Outdated
} | ||
|
||
for _, name := range names { | ||
dir.Uncache(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of listing then uncaching, can we just uncache all cached names? That ListNames
call could get expensive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically, with sharded directories.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, youre right. This will go through all names, even if they arent cached.
return fmt.Errorf("invalid mfs structure, root should be a directory") | ||
} | ||
|
||
if err := dir.Flush(); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if we concurrently modify this directory? Can we end up uncaching non-flushed entries? Is that an issue?
Should we have a single FlushAndUncache()
method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats basically the purpose of this method. In my comment i make it explicit that you shouldnt use this method concurrently with any other operations since there are deeper issues that could potentially happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I'm working on improving this situation, FYI.
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
3bab073
to
3e6eabb
Compare
@Stebalien fixed the 'iterate over every single child' issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
During
ipfs add
, we periodically call flush on the mfs root to free up unused memory. ApparentlyFlush
on the mfs root object wasnt actually callingFlush
on its directory, which led to memory not actually being freed. I'm trying to think of the best way to test this.License: MIT
Signed-off-by: Jeromy jeromyj@gmail.com